The Pitfalls of Reading User Input in C: a Story About scanf and Stdin
I recently had to write a piece of C code that takes some input from stdin, ignores the newline, discards whatever exceeds the buffer, and does this repeatedly in a loop.
Knowing something about scanf syntax (man) I came up with this:
#include <stdio.h>
void take_input(void)
{
char buf[20];
printf("> ");
scanf("%19[^\n]", buf);
printf("input=`%s`\n", buf);
}
int main(void)
{
for (int i = 0; i < 5; i++) {
take_input();
}
return 0;
}
(Note: The original code used an infinite loop, but a simple for is enough to demonstrate the behavior.)
When I ran it, the result was surprising:
$ gcc -o main main.c
$ ./main
> hello world↵
input=`hello world`
> input=`hello world`
> input=`hello world`
> input=`hello world`
> input=`hello world`
$ █
It consumed the string once and printed the same value 5 times. Why?
Read moreAbstractions and Inheritance in C - Elegant Foot-Shooting
Sometimes you want to abstract and generalize something in C code. For example, if you want to print the contents of a structure multiple times, you end up writing printf("%s %d %f\n", foo->bar, foo->baz, foo->boom) everywhere like a fool, and it intuitively seems that there should be a way to do foo->print(foo), and not just with foo, but with any structure.
Let's take an example: there is a guy with a first name and a last name, and there is a bird that has a name and an owner.
typedef struct Person Person;
struct Person {
char *first_name;
char *last_name;
};
typedef struct Bird Bird;
struct Bird {
char *name;
Person *owner;
};
To print information about these animals, a cunning C programmer would simply write two functions:
void Person_Print(Person *p) {
printf("%s %s\n", p->first_name, p->last_name);
}
void Bird_Print(Bird *b) {
printf("%s of %s %s\n", b->name, b->owner->first_name, b->owner->last_name);
}
And they would be right! But what if we have many such structures and our brains are corrupted by OOP?
Read more

