Exercise 3-2. Write a function
escape(s,t)that converts characters like newline and tab into visible escape sequences like\nand\tas it copies the stringttos. Use aswitch. Write a function for the other direction as well, converting escape sequences into the real characters.
Two functions walking their input strings character by character. escape converts control characters to two-character backslash notation using switch — the natural tool here since each character maps to a specific output pair. The output buffer must be sized at least twice the input length plus one, because every character could potentially expand to two. unescape reverses the process: on seeing a backslash it peeks at the next character to decide what control character to emit, consuming two input characters to produce one output character. Both functions must null-terminate the output string, and unescape‘s loop advance is non-uniform — always increment i, but only step by two when consuming a backslash sequence.
Solution
/* K&R Exercise 3-2 — escape and unescape
* Compile: gcc -ansi -Wall ex3-2.c -o ex3-2 */
#include <stdio.h>
void escape(char s[], char t[])
{
int i, j;
j = 0;
for (i = 0; t[i] != '\0'; ++i) {
switch (t[i]) {
case '\n':
s[j++] = '\\';
s[j++] = 'n';
break;
case '\t':
s[j++] = '\\';
s[j++] = 't';
break;
case '\\':
s[j++] = '\\';
s[j++] = '\\';
break;
default:
s[j++] = t[i];
break;
}
}
s[j] = '\0';
}
void unescape(char s[], char t[])
{
int i, j;
i = j = 0;
while (t[i] != '\0') {
if (t[i] == '\\') {
++i;
switch (t[i]) {
case 'n': s[j++] = '\n'; break;
case 't': s[j++] = '\t'; break;
case '\\': s[j++] = '\\'; break;
default: s[j++] = '\\'; s[j++] = t[i]; break;
}
} else {
s[j++] = t[i];
}
++i;
}
s[j] = '\0';
}
int main(void)
{
char original[] = "hello\tworld\nbye";
char escaped[64];
char restored[64];
escape(escaped, original);
printf("escaped: [%s]\n", escaped);
unescape(restored, escaped);
printf("restored: [%s]\n", restored);
return 0;
}
The default case in unescape handles unknown sequences like \q by passing them through unchanged — a safe choice since the input may come from text that was not produced by escape.
Compile and Run
gcc -ansi -Wall ex3-2.c -o ex3-2
./ex3-2
Sample Output
escaped: [hello\tworld\nbye] restored: [hello world bye]
The escaped string shows literal backslash-n and backslash-t. The restored string re-contains the actual tab character (visible as whitespace) and newline.
What This Exercise Teaches
switchfor character dispatch — cleaner than a chain ofif-elsewhen mapping individual characters to specific outputs- Output buffer sizing — two-character output from one-character input means the output buffer needs to be at least 2× input length + 1
- Round-trip inverse functions —
escapeandunescapeshould be each other’s exact complement; the restored string must match the original - Non-uniform loop advance —
unescapeconsumes 2 input characters (backslash + letter) to produce 1 output character
Set Up Your C Environment
- Install GCC on Windows 11
- Install GCC on macOS
- Install GCC on Ubuntu/Linux
- VS Code for C Programming
← Exercise 3-1 |
Chapter 3 Solutions |
Exercise 3-3 →
Book:
The C Programming Language, 2nd Ed — Kernighan & Ritchie