Echo
Source: CS:APP3e, Bryant and O’Hallaron, problem 3.71
“Write a function good_echo
that reads a line from standard input
and writes it to standard output. Your implementation should work for
an input line of arbitrary length. You may use the library function
fgets
, but you must make sure your function works correctly even
when the input line requires more space than you have allocated for
your buffer. Your code should also check for error conditions and
return when one is encountered.”
My solution
fgets()
returns NULL on error or EOF if no characters were read,
and otherwise returns the buffer pointer. We can treat the return
value as a boolean value to enable buffer reuse, by making the
expression fgets(buf, BUFMAX, stdin)
the boolean condition for
a while
loop. The loop will continue for as long as the return
value of fgets()
is truthy. (This is the compact style one sees
in the character I/O section of K&R, §1.5.)
fgets()
appends a data-terminating ‘\0’, so we can use that as a
loop-terminating condition when initializing a for
loop to iterate
over the buffer.
This for
loop calls putchar()
to send each character to stdout.
The return value of putchar()
is the character, so we can test the
expression putchar(buf[i])
for equality with the newline character
‘\n’ and return if we encounter it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#define BUFMAX 8
void good_echo() {
char buf[BUFMAX];
int i;
// For as long as `fgets()` does not return NULL or EOF —
// that is, for as long as it is still accepting stdin...
while (fgets(buf, BUFMAX, stdin)) {
// At any point when `buf` has been filled, iterate over it.
for (i = 0; buf[i] != '\0'; i++) {
// `putchar()` sends the char to stdout. It also returns
// the char, so we can test it to see if it's a newline.
if (putchar(buf[i]) == '\n') return;
}
}
}
int main() {
good_echo();
return 0;
}