Nearby lessons

66 of 124

C - String Input

Reading strings from the keyboard in C — scanf("%s") and why it stops at the first space, fgets() and why it is the safe choice, plus the classic trailing-newline problem and how to fix it.

scanf("%s") — One Word Only

The %s specifier skips leading whitespace, reads characters until the next whitespace, and appends '\0'. Note there is no & — an array name already is an address:

Example01
CCode Cell
1#include <stdio.h>
2 
3int main()
4{
5 char name[50];
6 
7 printf("Enter your name: ");
8 scanf("%s", name); /* no & before name */
9 
10 printf("Hello, %s!\n", name);
11 return 0;
12}
Output
Enter your name: Rahul
Hello, Rahul!

The Space Problem

Type a full name and scanf("%s") takes only the first word. The rest stays in the input buffer waiting for the next read:

Example02
CCode Cell
1#include <stdio.h>
2 
3int main()
4{
5 char first[50], second[50];
6 
7 printf("Enter full name: ");
8 scanf("%s", first); /* takes "Rahul" */
9 scanf("%s", second); /* takes "Sharma" from the buffer */
10 
11 printf("first = %s\n", first);
12 printf("second = %s\n", second);
13 return 0;
14}
Output
Enter full name: Rahul Sharma
first  = Rahul
second = Sharma

fgets() — Read a Whole Line

fgets takes three arguments: the buffer, its size, and the stream. Because you pass the size, it cannot overflow:

Example03
CCode Cell
1#include <stdio.h>
2 
3int main()
4{
5 char line[100];
6 
7 printf("Enter a sentence: ");
8 fgets(line, sizeof(line), stdin);
9 
10 printf("You typed: %s", line); /* no \n needed - fgets kept one */
11 return 0;
12}
Output
Enter a sentence: C is a great language
You typed: C is a great language

Removing the Trailing Newline

fgets stores the Enter key as '\n' inside the string. That extra character breaks comparisons and formatting, so strip it:

Example04
CCode Cell
1#include <stdio.h>
2#include <string.h>
3 
4int main()
5{
6 char line[100];
7 
8 printf("Enter a word: ");
9 fgets(line, sizeof(line), stdin);
10 
11 printf("Before: [%s] length %zu\n", line, strlen(line));
12 
13 line[strcspn(line, "\n")] = '\0'; /* the standard one-liner */
14 
15 printf("After : [%s] length %zu\n", line, strlen(line));
16 return 0;
17}
Output
Enter a word: hello
Before: [hello
] length 6
After : [hello] length 5

How the strcspn Trick Works

In simple words: strcspn(line, "\n") returns the index of the first newline — or the string's length if there is none. Writing '\0' at that index either replaces the newline or harmlessly rewrites the terminator that is already there. One line, safe in both cases.

The older manual version does the same thing with more code:

Example05
CCode Cell
1#include <stdio.h>
2#include <string.h>
3 
4int main()
5{
6 char line[100];
7 size_t len;
8 
9 printf("Enter text: ");
10 fgets(line, sizeof(line), stdin);
11 
12 len = strlen(line);
13 if (len > 0 && line[len - 1] == '\n')
14 line[len - 1] = '\0';
15 
16 printf("Cleaned: [%s]\n", line);
17 return 0;
18}
Output
Enter text: hello world
Cleaned: [hello world]

Mixing scanf and fgets

A scanf("%d") leaves the newline in the buffer, so the next fgets reads an empty line instantly. Clear the buffer between them:

Example06
CCode Cell
1#include <stdio.h>
2#include <string.h>
3 
4int main()
5{
6 int age;
7 char name[50];
8 int c;
9 
10 printf("Enter age: ");
11 scanf("%d", &age);
12 
13 while ((c = getchar()) != '\n' && c != EOF) { } /* flush the line */
14 
15 printf("Enter name: ");
16 fgets(name, sizeof(name), stdin);
17 name[strcspn(name, "\n")] = '\0';
18 
19 printf("%s is %d years old\n", name, age);
20 return 0;
21}
Output
Enter age: 25
Enter name: Rahul Sharma
Rahul Sharma is 25 years old

Limiting scanf Safely

If you must use scanf, give %s a width limit — it should be one less than the buffer size to leave room for '\0':

Example07
CCode Cell
1#include <stdio.h>
2 
3int main()
4{
5 char word[10];
6 
7 printf("Enter a word (max 9 chars): ");
8 scanf("%9s", word); /* 9 + terminator = 10 */
9 
10 printf("Stored: %s\n", word);
11 return 0;
12}
Output
Enter a word (max 9 chars): programming
Stored: programmi

Reading a Line with scanf

A scan set — %[^\n] — reads everything except newline. It works, but fgets is clearer and safer:

Example08
CCode Cell
1#include <stdio.h>
2 
3int main()
4{
5 char line[100];
6 
7 printf("Enter a sentence: ");
8 scanf("%99[^\n]", line); /* read until newline, max 99 chars */
9 
10 printf("You typed: %s\n", line);
11 return 0;
12}
Output
Enter a sentence: Learning C strings
You typed: Learning C strings

Never Use gets()

gets() reads a line but accepts no size limit. Type more than the buffer holds and it overwrites whatever follows in memory. It was deprecated in C99 and removed from the language in C11.

FunctionReadsSize limitVerdict
scanf("%s")One wordOnly with a widthUse with a width
scanf("%[^\n]")A lineOnly with a widthWorks, awkward
fgets()A lineAlwaysPreferred
gets()A lineNeverRemoved — never use
The three input mistakes that account for most beginner bugs: writing scanf("%s", &name) when name is already an address; expecting scanf("%s") to capture a full name with a space in it; and forgetting that fgets keeps the newline, so strcmp(input, "yes") never matches.
📝 Key Takeaways
  • scanf("%s") stops at the first whitespace — one word only.
  • Do not put & before a char array in scanf.
  • fgets(buf, sizeof(buf), stdin) reads a whole line safely.
  • fgets keeps the \n — strip it with strcspn.
  • gets() has no size limit and was removed from the C standard.

🧠 Test Your Knowledge

4 Questions
Progress: 0 / 4