CString Input & Output

String Input & Output

Printing a string in C is usually straightforward, but reading one safely takes real care — the most commonly taught approach, scanf("%s", ...), is also one of the most dangerous functions in the standard library when used carelessly. This page covers printing, the risk in scanf, and the safer alternative, fgets().
Printing Strings with printf
The %s conversion specifier tells printf to print a string: it writes characters starting at the given pointer until it hits the null terminator.

C
#include <stdio.h>

int main(void) {
    char name[] = "Ada";
    printf("Hello, %s!\n", name); // Hello, Ada!
    return 0;
}
Reading Strings with scanf
scanf("%s", buf) reads a sequence of non-whitespace characters into buf, stopping at the first space, tab, or newline, and automatically appends a null terminator.

C
#include <stdio.h>

int main(void) {
    char name[20];
    printf("Enter your name: ");
    scanf("%s", name); // no & needed -- name already decays to a pointer
    printf("Hi, %s!\n", name);
    return 0;
}
scanf("%s", ...) has NO bounds checking
This is the critical danger: scanf with a plain %s has no idea how big your buffer is. If the user types more characters than the buffer can hold, scanf keeps writing past the end of it anyway — a textbook buffer overflow. Never use unbounded %s on input that could come from a user or any untrusted source. If you must use scanf for a string, always give it a maximum width, one less than the buffer size to leave room for the terminator: for a 20-byte buffer, use %19s, not %s.

C
char buf[20];

scanf("%s", buf);   // DANGEROUS: unbounded, can overflow buf
scanf("%19s", buf); // SAFE: reads at most 19 chars, leaves room for '\0'
fgets(): The Safer Way to Read a Line
fgets() reads an entire line of input, up to a maximum number of characters you specify, and always respects the buffer size you give it. It is the recommended way to read string input in C. (See the dedicated page on gets(), puts() & fgets() for a deeper look at its full signature and return value.)

C
#include <stdio.h>

int main(void) {
    char line[50];
    printf("Enter a line: ");
    fgets(line, sizeof(line), stdin); // reads at most 49 chars + '\0', bounded by sizeof(line)
    printf("You typed: %s", line);
    return 0;
}
Newline Handling: scanf vs fgets

A key practical difference between the two is what happens to the newline character the user types when they press Enter.

Function

Stops reading at

Newline in result?

scanf("%s", ...)

The first whitespace character (space, tab, newline)

No -- the newline is left unread in the input buffer, not stored

fgets(buf, n, stdin)

A newline, or after n - 1 characters, whichever comes first

Yes -- the newline IS included in the stored string, if it fit

fgets often leaves a trailing newline to strip
Because fgets() keeps the newline character in the buffer, it is common to strip it afterward, for example by finding '\n' with strchr() and replacing it with '\0' if you don't want it in the string.
  • printf("%s", str) prints a string up to (not including) its null terminator

  • scanf("%s", buf) has NO bounds checking -- always use a width limit like %19s for a 20-byte buffer

  • fgets(buf, sizeof(buf), stdin) is the safer alternative -- it always respects the buffer size

  • scanf("%s") stops at whitespace and discards it; fgets() stops at a newline and keeps it in the string

  • Never trust unbounded string input from users -- it is one of the most exploited classes of bugs in C history