Practice with arrays, structs, pointers and linked lists


1. Assume that we've declared and initialized a string as follows:
Write C code that loops over the string (i.e., the char array) and sets each char to the char immediately preceding it in the alphabet. You may assume that all the characters in the string are letters (and not 'a' or 'A'). For example, if we initialized the string like this:
char str[] = "hello";
Then the output should be: gdkkn

2. Write a function that takes a string as its argument, and reverses the string in place. So if your function is called like this:
char s[] = "hello";

rev(s);
printf("%s\n", s);

The output will be olleh
You can call strlen() (from string.h) in your code.

Solution:
void rev(char *s) {
  int len = strlen(s);
  if(len > 1) {
    for(int i = 0; i < len/2; i++) {
      char temp = s[i];
      s[i] = s[len - (i+1)];
      s[len-(i+1)] = temp;
    }
  }
}


3. Consider the following structs:
struct point {
   int x;
   int y;
};
struct rectangle {
   struct point upperLeft;
   struct point lowerRight;
};

struct point represents the x and y coordinates of a point in two dimensional space. The points in the struct rectangle represent the points at the upper left and lower right corners of a rectangle in two dimensional space. Write a function area() that takes a rectangle struct as its parameter, and returns the area of the rectangle.

int area(struct rectangle rec) {
  int topX = rec.upperLeft.x;
  int topY = rec.upperLeft.y;
  int botX = rec.lowerRight.x;
  int botY = rec.lowerRight.y;

  return (botX-topX)*(topY-botY);
}



4. Given the same structs as in the previous question, write a function that takes a struct rectangle r and a struct point p, and returns true if p lies within r and false otherwise.

bool inRectangle(struct rectangle rec, struct point p) {
  int topX = rec.upperLeft.x;
  int topY = rec.upperLeft.y;
  int botX = rec.lowerRight.x;
  int botY = rec.lowerRight.y;
 
  bool xFlag = (p.x < botX) && (p.x > topX);
  bool yFlag = (p.y > botY) && (p.y < topY);
  return xFlag && yFlag;
}


5. Write a function named duplicate() that uses dynamic memory allocation to create a copy of a string. For example, the call
p = duplicate(str);
would allocate space for a string the same length as str, copy the contents of str into the new string, and return a pointer to it. Have duplicate() return NULL if the memory allocation fails.

char *duplicate(char *s) {
   if(s == NULL) return NULL;
   int len = strlen(s);
   char *result = malloc((len+1)*sizeof(char));
   if(result == NULL) return NULL;
   strcpy(result, s);
   return result;
}

  

6. Given the struct node below:
struct node {
    int value;
    struct node *next;
};

Write the following function:
int countOccurrences(struct node *list, int n) {...}
which returns the number of occurrences of the integer n in the list. The first parameter is the linked list pointer (i.e., it points to the first element in the linked list.)

int countOccurrences(struct node *list, int n) {
   int count = 0;
   while(list != NULL) {
      if(list -> value == n) count++;
   }
   return count;
}


7. Assume that first is the list pointer for a linked list (so p points to the first node in the list.) struct node is declared in question 6. Write C code that deletes all nodes in the list and frees the memory for all nodes. Consider the code below. It is incorrect - how would you fix it?
struct node *p;
for(p = first; p!=NULL; p = p -> next)  free(p);

Correction:
struct node *cur = first, *prev = NULL;
while(cur != NULL) {
   prev = cur;
   cur = cur->next;
   free(prev);
}
first = NULL; prev = NULL;



8. Write a function that takes the pointer to a linked list of type struct node (as defined above), and removes the second node in the list. (Don't forget to call free()). You may assume that the list has at least two elements in it.
// pre: list != NULL and list points to a linked list containing at least two nodes
void removeSecond(struct node *list) {
    struct node *first = list, *sec = first->next;
    first->next = sec->next;
    free(sec);
}




9. Write a function max() that takes a pointer to a linked list and returns the maximum value stored in a list.
int max(struct node *list) {
    // Unspecified behavior if list is NULL
    int maxVal;
    if(list == NULL) return -1;
    maxVal = list -> value;
    list = list -> next;
    while(list != NULL) {
        if(list->value > maxVal) maxVal = list->value;
        list = list -> next;
    }
    return maxVal;
}


10. Consider the following two statements:
char *str = "hello";  char arr[] = "hello";
a) What is printed on kamek when the following statement is executed? What do the printed values mean?
printf("%zu \t %zu\n", sizeof(str), sizeof(arr));

b) Which of the following (if any) will produce a compilation error?
arr = str;    str = arr;     str[0] = 'j';     arr[0] = 'j';