Text, Tamed

Strings in C are a convention riding on arrays: characters, then '\0'. This chapter made you fluent in the convention from both sides, building and reading strings by hand, then letting the library do the walking, then stacking strings into a table, always under the capacity arithmetic that keeps C text handling safe. The recap.

The Convention

A string is a char array whose data ends at the null terminator. "hello" is six bytes: five characters and '\0'. Size is the array's capacity; length is the walk to the terminator. char w[] = "hello" lets the compiler count; an explicit too-small size silently drops the terminator in ANSI C, and %s or any string function on an unterminated array walks into undefined behaviour. The brace-list form makes the terminator your responsibility, so {'h','e','l','l','o'} is a char array and {'h','e','l','l','o','\0'} is a string; an array larger than its initializer is zero-filled to the end. The four byte-counts to know cold: '\0' one char (code 0), '0' one char (code 48), "0" two bytes, "" one byte. And because the digit characters have consecutive codes, c - '0' turns one of them into its numeric value.

Getting Text In and Out

On the way out, printf("%s", s) carries chapter 4's widths and flags, puts(s) prints the string plus a newline, and fputs(s, stdout) prints it with no newline added.

Three readers, three contracts. The hand-built getchar loop fills to capacity minus one and places '\0' itself. scanf("%19s", name) reads one whitespace-delimited word into a 20-byte buffer, width mandatory and equal to capacity minus one, array passed without &. fgets(buffer, size, stdin) reads a whole line, always terminates, returns NULL at end of input, and keeps the newline, which you trim by overwriting with '\0'. gets is the cautionary tale: no size parameter, unfixable, removed from the language. And mixing scanf with fgets revives the leftover-newline trap.

The Library

strlen returns the pre-terminator count as size_t (unsigned long, %lu). strcpy copies characters and terminator; strcat appends at the destination's terminator; both trust the caller that the destination holds combined length plus one, because arrays cannot be assigned with = and the functions cannot see capacities. strcmp is three-way: negative, zero, positive for before, equal, after, tested with < 0, == 0, > 0; a == b compares addresses, and a bare strcmp in a condition means "different". Each function's hand-written version is one terminator walk, and exams ask for them by name.

Tables of Strings

A list of names is a two-dimensional char array, char city[5][10], five rows of ten bytes where the second dimension is the longest name plus one. One subscript names a whole string, so city[i] goes straight to %s, strlen, and strcmp; two subscripts name a single character for %c. Read a list with the bounded scanf in a loop, guarding each read because an unfilled row printed with %s is undefined behaviour. Sort it with chapter 7's bubble sort, comparing strcmp(name[j], name[j + 1]) > 0 and swapping with three strcpy calls through a temporary row, since arrays support neither > nor =. The ordering is lexicographic by character code, so in ASCII all uppercase sorts before all lowercase.

One Program, Whole Chapter

A guarded fgets with trim, a copy-and-append into a buffer sized for the worst case (CAPACITY + 2: fgets stores at most 39 characters, and 39 + the '!' + the terminator is 41 bytes), and a three-way comparison used for equality: the chapter in one run. Type a line, predict all three outputs, then take the quiz.

Looking Ahead

Chapter 9 restructures everything you have written so far: functions, giving names to reusable work, and with them prototypes, pass-by-value, recursion, and the full storage-class story promised back in chapter 2.