Skip to main content

Arrays, Strings, and I/O Clinic

This practice page exercises Clusters 4 and 5. Keep the concept pages open for reference on the strlen/strcpy contract and array decay.

Compile every program with gcc -Wall -Wextra -std=c11 -o prog prog.c.

Retrieval Prompts

  1. State when an array expression does not decay to a pointer.
  2. State the contract of a C string.
  3. State why strncpy is not a drop-in safe replacement for strcpy.
  4. State why gets was removed in C11.
  5. State the difference between sizeof s and strlen(s) for char s[] = "abc";.

Compare and Distinguish

  • array int a[10] vs pointer int *p
  • string literal "hi" vs char a[] = "hi";
  • strncpy, strlcpy, snprintf, memcpy
  • sizeof array inside the function where it was declared vs inside a function that received it as a parameter
  • scanf("%d", &n) vs fgets + sscanf

Common Mistake Check

For each, identify the error:

  1. char name[8]; strcpy(name, "Kernighan");
  2. char *s = "hi"; s[0] = 'H';
  3. char buf[100]; sprintf(buf, "%s %s", a, b); where a and b are user input
  4. char buf[100]; fgets(buf, 100, stdin); buf[strlen(buf)-1] = '\0';
  5. int n; scanf("%d", n);
  6. printf(user_input);
  7. char dst[5]; strncpy(dst, "hello world", 5); then puts(dst);
  8. void f(int a[10]) { size_t n = sizeof a / sizeof a[0]; /* loop over n */ }

Array Decay Drill

Predict, then verify with a compiled test:

int a[5];
printf("%zu %zu %zu\n", sizeof a, sizeof &a, sizeof &a[0]);

Then write void f(int a[5]) that prints sizeof a and explain why the answer differs from outside.

C String Reimplementations

Without looking them up, write and test:

  1. size_t my_strlen(const char *s);
  2. int my_strcpy_safe(char *dst, size_t dst_size, const char *src); returning 0 on success, -1 on overflow.
  3. int my_strcat_safe(char *dst, size_t dst_size, const char *src); - same contract.
  4. char *my_strdup(const char *s); using malloc (you can forward-reference Module 2 on malloc).
  5. int my_strcmp(const char *a, const char *b);.

Test each with empty strings, exact-fit strings, and oversized inputs.

I/O Drill

Build a line-oriented tool:

  1. Read lines from stdin with fgets(buf, sizeof buf, stdin) where buf is char buf[1024].
  2. Strip trailing \n if present.
  3. Parse with sscanf or strtok depending on the task.
  4. Write results to stdout, errors to stderr.
  5. Exit 0 at EOF, non-zero on ferror(stdin).

Do all five for a program that reads word count per line and prints the total.

Struct and Modular Build Drill

Design a Buffer module that owns a growable byte buffer.

  1. buffer.h: opaque typedef struct buffer Buffer; plus buffer_create, buffer_append, buffer_data, buffer_len, buffer_destroy.
  2. buffer.c: the struct definition and implementations.
  3. main.c: read lines from stdin and collect into a Buffer until EOF, then write once via fwrite(buffer_data(b), 1, buffer_len(b), stdout).
  4. Makefile: compile main.o and buffer.o, link to app, support make clean.

Evidence Check

This page is complete only if you can:

  • write all five C-string helpers from memory with passing tests
  • explain sizeof inside and outside a function for the same array
  • build the Buffer module with a clean -Wall -Wextra -std=c11 run and a working Makefile