COMP1911 23T2 Introduction to Programming
  1. Write a function, that mirrors the behaviour of the library function strncat. Your code should use the following prototype.

    void mystrncat(char str1[], char str2[], int n);
    

    Reminder: strncat appends str2 to str1, over writing the terminating null char ('\0') at the end of str1, and then adds a terminating null byte char. strncat will use at most n bytes from str2.

    void mystrncat(char str1[], char str2[], int n) {
        int i, len;
    
        // find the end of the first string
        len = 0;
        while (str1[len] != '\0'){
            len = len + 1;
        }
    
        // start copying from the second string
        i = 0;
        while (i < n && str2[i] != '\0') {
            str1[len] = str2[i];
            len = len + 1;
            i = i + 1;
        }
        str1[len] = '\0';
    }
    
  2. What does this program print?
    #include <stdio.h>
    
    int main(int argc, char *argv[]) {
        printf("%s", argv[argc - 1]);
        return 0;
    }
    
    

    It prints the last command line argument.
  3. Write a C program last_argument_reversed.c which writes out its last command line argument with the characters in reverse order.

    Your program should print nothing if there are no command line arguments.

    For example:

    ./last_argument_reversed The quick brown fox
    xof
    
    Sample solution for last_argument_reversed.c
    #include <stdio.h>
    
    int main(int argc, char *argv[]) {
        int  i;
    
        if (argc > 1) {
            i = 0;
            while (argv[argc - 1][i] != '\0') {
                i = i + 1;
            }
            while (i > 0) {
                i = i - 1;
                printf("%c", argv[argc - 1][i]);
            }
            printf("\n");
        }
    
        return 0;
    }
    
    
  4. What are the differences between f1 and f2?
    #define SIZE 5
    int * f1(void){
        int nums[SIZE] = {1,2,3,4,5};
        return nums;
    }
    
    int * f2(void){
        int * nums = malloc(sizeof(int) * SIZE);
        int i = 0;
        while(i < SIZE){
            nums[i] = i+1;
            i = i + 1;
        }
        return nums;
    }
    
    Both f1 and f2 create arrays of integers of size 5 and set the data with the integers from 1..5. However in f1, nums is a local variable, so the array is on the stack. f1 then attempts to return the address of the array. This is dangerous and may not compile and/or generate compiler warnings. This is because as we know once the function finishes, the memory used by all the local variables of the function can be reused by other parts of the program.

    f2 uses malloc to create a chunk of memory big enough to store 5 integers. However since it has used malloc the memory will be allocated on the heap and won't be reused until the program explicitly frees it.

  5. Write a function with the following prototype to reverse a string
    char * reverseString(char * s);
    

    Then write a program that uses the function to read in a string from standard input and print it in reverse

    Sample solution reverse.c
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define MAX 100
    char * reverseString(char *s);
    
    int main(void){
        char input[MAX];
        char * reverse;
        
        printf("Enter a string: ");
        if(fgets(input,MAX,stdin) != NULL){
            reverse = reverseString(input);
            printf("%s\n",reverse);
            free(reverse);   
        }
     
        return 0;
    }
    
    char * reverseString(char *s){
       char * reversed = malloc(sizeof(char) * (strlen(s) + 1));
       
       int i = strlen(s)-1;
       int j =0;
       while(i >= 0){
            reversed[j]=s[i];
            j++;
            i--;
       }
       reversed[j] = '\0';
       return reversed;
    }
    
    
  6. Consider the following code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAXITEMS 4
    
    int z;  
    
    void fun(int x);
    
    int main(int argc, char * argv[]) {
        
        int var = 5;
        int array[MAXITEMS] = {1,9,1,7};
        int * q = malloc(sizeof(int));
        char s0[] = "Hello";
    
        //DO SOMETHING WITH THE VARIABLES
        fun(var);
        
    
        return EXIT_SUCCESS;
    }
    
    void fun(int x){
        int myFun = x/2.0;
        printf("I am having %d times the fun you are!\n",myFun);
    }
    
    What section of memory (text,data,stack,heap) would the following be stored in
    • var
      stack
    • array
      stack
    • q
      stack
    • *q
      heap
    • s0
      stack
    • The code for the main and the function
      text
    • z
      data
    • x
      stack
    • myFun
      stack

    Extra Home Study Questions

    .
    1. What would be the output of the following code?
      int x = -9;
      int *p1 = &x;
      int *p2;
      
      p2 = p1;
      printf("%d\n", *p2);
      *p2 = 10;
      printf("%d\n",x);
      
      -9
      10
      
    2. Given the following code fragment:
      char goals[] = "All your goals belong to us.";
      char *a, *b, *c;
      
      a = goals + 5;
      b = &goals[10];
      c = goals + (b - goals) + (b - a);
      
      The fragment is valid C. It executes without error. Indicate clearly and exactly what the following expressions evaluate to:

      1. a == goals
        0 - this is asking whether a points to the same memory address as goals. It doesn't.
      2. a > goals
        1 - a points to a higher memory address than goals
      3. goals > c
        0 - goals does not point to a higher memory address than c
      4. c - b
        5
      5. goals - a
        -5
      6. a[0] != b[0]
        0 - a[0] is 'o', so is b[0]
      7. *c
        'b' - the letter that c points to
      8. goals[a - goals] == *a
        1 as they both have the value 'o'
      9. c[a - b]
        'o'
    3. Given the following code fragment:
      int i = 0;
      int j = 0;
      char *s = "ceded";
      
      while (s[i] != '\0') {
        j = j + s[i] - 'a';
        i = i + 1;
      }
      printf("%d %d\n", i, j);
      
      The fragment is valid C. It executes without error. Indicate clearly and exactly what output will be printed.
      5 16
      

      Here, s is a char pointer that points to the first letter of the string "str". We can index into it since strings are arrays. The loop terminates when s[i] is '\0', i.e., 0, which happens when i is 5.
      Indexing into s gives individual characters; subtracting 'a' from each of those gives the 'distance' between the character and 'a', e.g., s[0] - 'a' => 'c' - 'a' = 2.

    4. Write a function with the prototype below that calculates the sum and the product of all the integers in the given array.
      void sumProd(int nums[], int len, int *sum, int *product);
      
      Sample solution (whole program)
      #include <stdio.h>
      
      void sumProd(int nums[], int len, int *sum, int *product);
      
      int main(int argc, char *argv[]){
         int nums[] = {3,4,1,5,6,1};
         int prod;
         int sum;
      
         //Pass in the address of the sum and product variables
         sumProd(nums, 6, &sum, &prod);
      
         printf("The sum is %d and prod is %d\n",sum,prod);
         return 0;
      }
      
      
      // Calculates the sum and product of the array nums.
      // Actually modifies the  variables that *sum and *product are pointing to
      void sumProd(int nums[], int len, int *sum, int *product) {
          int i;
          *sum = 0;
          *product = 1;
          for (i = 0; i < len; i = i + 1) {
              *sum = *sum + nums[i];
              *product = *product * nums[i];
          }
      }