Twelve problems, from beginner to advanced, that use pointers. In most of them the main function is already complete, and you write the body of the requested function. Press "Check" to run your code with real gcc on several inputs and see whether the output is correct.
Note: Run and Check send your code to Wandbox, a free external compiler service, and run it with gcc.
void swap(int *a, int *b) that swaps the values of two int variables. The main function is complete (it reads two integers, calls swap, and prints them in the form "a = value, b = value")."Run" executes your code with the input above. "Check" tests it against 4 prepared inputs.
tmp. *a is the variable that a points to (the a in main) itself, so tmp = *a; *a = *b; *b = tmp; swaps them.#include <stdio.h> void swap(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; } int main(void) { int a, b; scanf("%d %d", &a, &b); swap(&a, &b); printf("a = %d, b = %d\n", a, b); return 0; }
void swap(int a, int b), only the copies inside the function are swapped and the variables in main do not change. The caller passes addresses with &a, and the function modifies what they point to with *a. If you forget the *, as in a = b;, you only change the pointer (a local variable) and nothing happens.void divmod(int a, int b, int *q, int *r) that returns the quotient and remainder of a ÷ b through pointer parameters. The main function is complete."Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
return can return only one value. Receive the addresses of the variables where the results should go (&q, &r) and write to what they point to, as in *q = a / b;.#include <stdio.h> void divmod(int a, int b, int *q, int *r) { *q = a / b; *r = a % b; } int main(void) { int a, b, q, r; scanf("%d %d", &a, &b); divmod(a, b, &q, &r); printf("Quotient: %d\n", q); printf("Remainder: %d\n", r); return 0; }
& in front of variables passed to scanf). If you forget the * and write q = a / b;, you are assigning an int to a pointer, so the compiler gives a warning (an error in gcc 14 and later). Even if it did run, q in main would not be updated and would stay uninitialized.int sum(const int *a, int n) that returns the sum of an int array with n elements. Do not use the subscript [ ]; add up the elements by advancing a pointer one element at a time. The main function is complete (it reads N (1 ≤ N ≤ 100) and N integers (each between −10000 and 10000) and prints the sum)."Run" executes your code with the input above. "Check" tests it against 4 prepared inputs.
for (const int *p = a; p < a + n; p++), p points to each element in turn, from the first to the last. The value of the element it points to is *p.#include <stdio.h> int sum(const int *a, int n) { int s = 0; for (const int *p = a; p < a + n; p++) { s += *p; } return s; } int main(void) { int n, a[100]; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } printf("Sum: %d\n", sum(a, n)); return 0; }
a to a function, the address of the first element is passed. a + i is the address of the element i positions ahead, and a[i] means the same as *(a + i). const int * is a promise that "this function does not modify what it points to", so accidentally writing *p = 0; causes a compile error. a + n points one past the last element, so the condition uses < (with <= you read out of range).int my_strlen(const char *s) that returns the length of a string (the number of characters before '\0'), using a pointer and without using strlen. The main function is complete (it reads a string of letters and digits without spaces (1–99 characters) and prints its length)."Run" executes your code with the input above. "Check" tests it against 4 prepared inputs.
*s is not '\0', count as you advance the pointer one character at a time with s++. while (*s != '\0') can also be written as while (*s).#include <stdio.h> int my_strlen(const char *s) { int len = 0; while (*s != '\0') { len++; s++; } return len; } int main(void) { char str[100]; scanf("%99s", str); printf("Length: %d\n", my_strlen(str)); return 0; }
'\0' (the null character). Its length is not the size of the array (100) but the number of characters up to '\0'. What s++ advances is the pointer inside the function (a copy), so str in main does not move. If you mix up s and *s and write while (s != '\0'), then because '\0' is a constant with value 0, it becomes a comparison of "whether s is NULL". s never becomes NULL, so the loop does not stop and keeps reading past the end of the array (the compiler also warns about this).void minmax(const int *a, int n, int *max, int *min) that finds the maximum and minimum of an int array with n elements and writes them to the variables pointed to by the pointer parameters max and min. The main function is complete (it reads N (1 ≤ N ≤ 100) and N integers (each between −10000 and 10000) and prints the results)."Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
*max = *min = a[0];, then compare with the second element onward and update. What you compare against is *max (the value it points to).#include <stdio.h> void minmax(const int *a, int n, int *max, int *min) { *max = a[0]; *min = a[0]; for (int i = 1; i < n; i++) { if (a[i] > *max) *max = a[i]; if (a[i] < *min) *min = a[i]; } } int main(void) { int n, a[100], max, min; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } minmax(a, n, &max, &min); printf("Max: %d\n", max); printf("Min: %d\n", min); return 0; }
if (a[i] > max), you are comparing a value with an address, and the compiler warns about it.void reverse(int *a, int n) that reverses the order of an int array with n elements in place. Use two pointers, one to the first element and one to the last, and swap while moving them toward each other. The main function is complete (it reads N (1 ≤ N ≤ 100) and N integers, and prints the array after reverse, separated by spaces)."Run" executes your code with the input above. "Check" tests it against 4 prepared inputs.
int *left = a; and int *right = a + n - 1;, and while left < right, swap *left and *right and move inward with left++ and right--.#include <stdio.h> void reverse(int *a, int n) { int *left = a; int *right = a + n - 1; while (left < right) { int tmp = *left; *left = *right; *right = tmp; left++; right--; } } int main(void) { int n, a[100]; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } reverse(a, n); for (int i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); return 0; }
a + n - 1, not a + n (a + n is outside the array). An array is passed as the address of its first element, so modifying it inside the function also changes the array in main. If you keep swapping all the way to the end (until left reaches the last element), every pair is swapped twice and returns to its original order, so the key is to stop in the middle.void to_upper(char *s) that rewrites the lowercase letters (a–z) in a string as uppercase in place. Leave all other characters unchanged. Do not use library functions such as toupper; process the string one character at a time with a pointer. The main function is complete (it reads a string of letters and digits without spaces (1–99 characters) and prints the converted string)."Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
while (*s != '\0'), and if 'a' <= *s && *s <= 'z', rewrite it with *s = *s - 'a' + 'A';. Do not forget s++ at the end.#include <stdio.h> void to_upper(char *s) { while (*s != '\0') { if ('a' <= *s && *s <= 'z') { *s = *s - 'a' + 'A'; } s++; } } int main(void) { char str[100]; scanf("%99s", str); to_upper(str); printf("%s\n", str); return 0; }
*s - 'a' + 'A' shifts a lowercase letter to uppercase. Since the function modifies the string, the parameter is char * without const. If you put s++ inside the if, the loop gets stuck on the first character that is not lowercase and never ends.int *find(int *a, int n, int key) that searches an int array with n elements for the value key from the beginning and returns a pointer to the first matching element. If it is not found, return NULL. The main function is complete: it computes the index from the difference between the returned pointer and the start of the array (pointer subtraction) and prints it. The input is N (1 ≤ N ≤ 100), N integers, then key."Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
for (int *p = a; p < a + n; p++), and when *p == key, return that p. If the loop ends, nothing was found, so return NULL.#include <stdio.h> int *find(int *a, int n, int key) { for (int *p = a; p < a + n; p++) { if (*p == key) { return p; } } return NULL; } int main(void) { int n, a[100], key; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } scanf("%d", &key); int *p = find(a, n, key); if (p == NULL) { printf("Not found\n"); } else { printf("Index: %d\n", (int)(p - a)); } return 0; }
p - a, gives not a number of bytes but how many elements apart they are (which is why it is the index). The returned pointer points into the array a in main, so it is still valid after the function ends. On the other hand, returning the address of a local variable inside the function is a mistake (it disappears when the function ends).void sort3(int *a, int *b, int *c) that rearranges the values of three int variables so that *a ≤ *b ≤ *c. You may use the provided swap function for swapping. The main function is complete (it reads three integers and prints them after sort3, separated by spaces)."Run" executes your code with the input above. "Check" tests it against 6 prepared inputs.
*a > *b", "swap if *b > *c", and "swap again if *a > *b". a is already a pointer, so pass it to swap without &, as in swap(a, b).#include <stdio.h> void swap(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; } void sort3(int *a, int *b, int *c) { if (*a > *b) swap(a, b); if (*b > *c) swap(b, c); if (*a > *b) swap(a, b); } int main(void) { int x, y, z; scanf("%d %d %d", &x, &y, &z); sort3(&x, &y, &z); printf("%d %d %d\n", x, y, z); return 0; }
*c, but the order of *a and *b is not settled yet, so the third step is needed (you can check this with the input 2 3 1). Writing swap(&a, &b) passes an int **, so the types do not match. The key point is that you can pass the pointers you received as they are.malloc, and read N integers (each between −1000 and 1000). Print the average to two decimal places, and on the next line print the values greater than the average in input order, separated by spaces (if there are none, print nothing after "Above average:"). If the allocation fails, print "Memory allocation failed" and exit, and always free the memory at the end."Run" executes your code with the input above. "Check" tests it against 5 prepared inputs.
int *a = malloc(sizeof(int) * n);; if a == NULL, it failed. Once allocated, you can use it like an ordinary array with a[i]. For "greater than the average", compare with integers as in a[i] * n > sum rather than with decimals, so there is no rounding error.#include <stdio.h> #include <stdlib.h> int main(void) { int n; scanf("%d", &n); int *a = malloc(sizeof(int) * n); if (a == NULL) { printf("Memory allocation failed\n"); return 1; } long long sum = 0; for (int i = 0; i < n; i++) { scanf("%d", &a[i]); sum += a[i]; } printf("Average: %.2f\n", (double)sum / n); printf("Above average:"); for (int i = 0; i < n; i++) { if ((long long)a[i] * n > sum) { printf(" %d", a[i]); } } printf("\n"); free(a); return 0; }
malloc. Always free allocated memory when you are done with it (forgetting causes a memory leak). malloc returns NULL when it fails, so check before using it. In C, the return value of malloc (void *) can be assigned to an int * without a cast. If you forget to multiply by sizeof(int) and write malloc(n), only N bytes are allocated and you write out of range.char *concat(const char *a, const char *b) that builds the string made by joining two strings a and b in that order in memory allocated with malloc, and returns a pointer to its start. If the allocation fails, return NULL. The main function is complete (it reads two strings of letters and digits without spaces (1–19 characters each), prints the result and its length, then calls free). You may use the functions in string.h."Run" executes your code with the input above. "Check" tests it against 4 prepared inputs.
strlen(a) + strlen(b) + 1 bytes (the +1 is for the final '\0'). After allocating, copy a with strcpy(s, a); and append b with strcat(s, b);.#include <stdio.h> #include <stdlib.h> #include <string.h> char *concat(const char *a, const char *b) { char *s = malloc(strlen(a) + strlen(b) + 1); if (s == NULL) { return NULL; } strcpy(s, a); strcat(s, b); return s; } int main(void) { char a[20], b[20]; scanf("%19s %19s", a, b); char *s = concat(a, b); if (s == NULL) { printf("Memory allocation failed\n"); return 1; } printf("%s (%d chars)\n", s, (int)strlen(s)); free(s); return 0; }
char s[40]; inside the function and returning its address is a mistake. The array disappears when the function ends, and the returned pointer becomes invalid. Memory allocated with malloc stays until it is freed, so it is fine to return it. In exchange, the receiving side (main) is responsible for calling free. If you forget the +1, the '\0' is written outside the allocated area.strcmp). Do not move the name array names itself; rearrange only the contents of the array p of pointers to each name. Write the following two functions.void swap_ptr(char **x, char **y): swaps the contents (pointers) of two char * variablesvoid sort_names(char *p[], int n): bubble-sorts using swap_ptr"Run" executes your code with the input above. "Check" tests it against 4 prepared inputs.
char * variables inside the function, so receive their addresses (char **). The body of swap_ptr has the same shape as the int swap; only the type of the temporary variable becomes char *. In the sort, call swap_ptr(&p[j], &p[j + 1]); when strcmp(p[j], p[j + 1]) > 0.#include <stdio.h> #include <string.h> void swap_ptr(char **x, char **y) { char *tmp = *x; *x = *y; *y = tmp; } void sort_names(char *p[], int n) { for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - 1 - i; j++) { if (strcmp(p[j], p[j + 1]) > 0) { swap_ptr(&p[j], &p[j + 1]); } } } } int main(void) { int n; char names[10][20]; char *p[10]; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%19s", names[i]); p[i] = names[i]; } sort_names(p, n); printf("Sorted:"); for (int i = 0; i < n; i++) printf(" %s", p[i]); printf("\nOriginal:"); for (int i = 0; i < n; i++) printf(" %s", names[i]); printf("\n"); return 0; }
swap_ptr(char *x, char *y), only the copies inside the function are swapped. Unlike swapping the string contents with strcpy, this only swaps pointers, so no characters are copied. strcmp compares by character code, so uppercase (K) comes before lowercase (a). Writing p[j] > p[j + 1] would compare addresses instead.