Skip to content
FollowtheDamnCode

Reading Strings

Getting a word or a line from the user.

5 minute read

Big idea

scanf("%s") reads one word. fgets reads a whole line, spaces included — and never more than fits.

One word: scanf

char name[20];
scanf("%19s", name);
  • No & — name is an array, so it's already an address.
  • %19s — read at most 19 characters, leaving room for '\0' in a 20-char array.
  • %s stops at the first space. Typing Maya Rao stores only Maya.
scanf stops at a space
#include <stdio.h>

int main(void) {
    char first[20];
    scanf("%19s", first);
    printf("Hello, %s!\n", first);
    return 0;
}
input
Maya Rao
output
Hello, Maya!

Run and edit it in the app.

A whole line: fgets

char line[50];
fgets(line, sizeof line, stdin);
  • line — where to store it.
  • sizeof line — the most it may store (50, including '\0') — fgets never overflows.
  • stdin — read from the keyboard ("standard input").

One catch: fgets keeps the Enter key — a '\n' — at the end of what it read. Remove it before printing or comparing:

Read a full line and strip the newline
#include <stdio.h>
#include <string.h>

int main(void) {
    char line[50];
    fgets(line, sizeof line, stdin);
    line[strcspn(line, "\n")] = '\0';
    printf("[%s]\n", line);
    return 0;
}
input
Maya Rao from Chennai
output
[Maya Rao from Chennai]

Run and edit it in the app.

strcspn(line, "\n") gives the index of the first '\n' (or the end, if there isn't one), and writing '\0' there cuts it off.

Watch it

Mixing scanf and fgets

After scanf("%d", &age), the Enter you pressed is still waiting. A following fgets reads that leftover '\n' straight away and returns an empty line:

Fix the bug: the city should be read correctly
#include <stdio.h>
#include <string.h>

int main(void) {
    int age;
    char city[40];
    scanf("%d", &age);
    fgets(city, sizeof city, stdin);
    city[strcspn(city, "\n")] = '\0';
    printf("%d, %s\n", age, city);
    return 0;
}
input
21
New Delhi
output
21, New Delhi

Run and edit it in the app.

One fix: after the scanf, skip the rest of that line with while (getchar() != '\n'); before calling fgets.

Never use gets

Old code uses gets(line). It has no size limit, so long input overwrites memory — it was so dangerous that it was removed from the C language. Use fgets.

Think of it like

scanf("%s") is a listener who stops at the first pause. fgets listens until you finish the sentence — and has a notepad of a fixed size, so it never writes off the edge.

🕷️ Spidey-sense: When J. Jonah Jameson calls, scanf hears "PARKER!" and hangs up. fgets gets the whole rant — up to the size of my voicemail box.

Key terms

  • fgets — Reads a line (with a size limit) into a char array.
  • stdin — Standard input: normally the keyboard.
  • Buffer overflow — Writing past the end of an array; %19s and fgets prevent it.

Check yourself

You type New York for scanf("%s", city). What's stored?

What does fgets keep at the end of the line?

Why never use gets?