What is C String Input and Output- C Programming Course With Examples

Need Help or More Information?

Questions about this free C programming course, embedded C training or career guidance? Get in touch.

Free C Programming Course · Chapter 9 · Lecture 6 of 7

C String Input and Output

How printf, scanf and fgets handle strings, why scanf stops at spaces, and how to protect your buffers.

9
Chapter: Strings
6/7
Lecture in this chapter
Free
Always, for every student

What You Will Learn

  • How printf and puts print strings, and what %s expects
  • Exactly what scanf("%s") reads and what it leaves behind
  • How to use a field width to protect a buffer
  • How to read a whole line with fgets and strip the newline
  • How to print a buffer that has no terminator using a precision
  • Why C string input and output needs extra care on microcontrollers

Prerequisites

  • Lecture 4: string variables and capacity
  • Lecture 5: walking a string
  • Basic use of printf and scanf from the Input-Output chapter

Text only becomes useful when it can move in and out of your program. This lecture of the free C programming course covers C string input and output: the %s conversion, its surprising stopping rule, and the bounded alternatives you should reach for in real firmware. Good string input and output habits matter in any free embedded C course because the data that arrives on a serial port is never as polite as the examples in textbooks.

C String Output With printf and puts

printf("%s", text) expects the address of the first character and writes characters until it meets the terminator. That is why the argument can be an array name, a pointer or a literal: all three give an address. puts(text) does the same and adds a newline. Neither knows the size of your buffer, so both depend completely on the terminator being present.

When the text must come from a buffer that might lack a terminator, give %s a precision. %.4s prints at most four bytes and then stops, and the C standard guarantees it will not look beyond them. A precision of .* lets you pass the limit as an argument.

C String Input With scanf and %s

The %s conversion in scanf works in three steps: it skips whitespace, copies the non-whitespace characters that follow, and stores a terminator. It stops at the first whitespace character after the word, and that character stays in the input buffer for the next read. The function returns the number of conversions that succeeded, so always test the result.

Save this as scanf_demo.c. It reads twice with a width of 15 into two 16-byte arrays:

#include <stdio.h>

int main(void)
{
    char first[16];
    char second[16];

    printf("Type something: ");

    /* %15s: skip leading whitespace, read at most 15 non-space chars, add NUL */
    if (scanf("%15s", first) == 1)
        printf("first call  -> [%s]\n", first);

    /* The rest of the line is still waiting in the input buffer */
    if (scanf("%15s", second) == 1)
        printf("second call -> [%s]\n", second);

    return 0;
}
gcc -std=c17 -Wall -Wextra -o scanf_demo scanf_demo.c
./scanf_demo

First run, typing Anil Reddy and pressing Enter:

Type something: Anil Reddy
first call  -> [Anil]
second call -> [Reddy]

Second run, typing 26 letters without a space:

Type something: ABCDEFGHIJKLMNOPQRSTUVWXYZ
first call  -> [ABCDEFGHIJKLMNO]
second call -> [PQRSTUVWXYZ]

What the input buffer looks like between the two scanf calls (first run)

StepInput bufferfirstsecond
Before any callAnil Reddy newlineunsetunset
After first scanfspace Reddy newlineAnilunset
After second scanfnewlineAnilReddy

Reading the two runs

  • In the first run the space ended the first word. The second call skipped the leading space and picked up the next word.
  • In the second run the width of 15 stopped the first read before the word ended. The remaining letters were not lost: the second call collected them. That is the safety of a width, and also a warning that unread input remains.
  • The array name was passed without & because it already is an address.

The width is one less than the array size

%15s may store 15 characters plus the terminator, so it needs a 16-byte array. Writing %16s into a 16-byte array allows 17 bytes and overflows by one.

Read a Whole Line With fgets

When the input contains spaces, scanf("%s") is the wrong tool. fgets reads up to a newline or until the buffer is nearly full, always terminates the string and returns NULL on end of input. It keeps the newline when the line fits, so most programs trim it. The idiom line[strcspn(line, "\n")] = '\0' does that without a special case for a missing newline. The same program also demonstrates bounded printing with a precision.

#include <stdio.h>
#include <string.h>

int main(void)
{
    char line[32];

    printf("Enter a full line: ");
    if (fgets(line, sizeof line, stdin) == NULL)
        return 1;

    line[strcspn(line, "\n")] = '\0';      /* strip the newline fgets keeps */
    printf("line   = [%s]\n", line);
    printf("length = %zu\n", strlen(line));

    /* Bounded print for a buffer that has no NUL, e.g. bytes from a UART */
    char raw[4] = {'U', 'A', 'R', 'T'};
    printf("raw    = [%.4s]\n", raw);
    printf("prefix = [%.2s]\n", "firmware");
    return 0;
}
gcc -std=c17 -Wall -Wextra -o fgets_demo fgets_demo.c
./fgets_demo

Expected output when you type Anil Reddy:

Enter a full line: Anil Reddy
line   = [Anil Reddy]
length = 10
raw    = [UART]
prefix = [fi]

Choosing the Right Way to Read Strings

FunctionReadsStops atSafe against overflow?
scanf("%s")one wordwhitespaceNo, unless you give a width
scanf("%15s")one word, max 15whitespace or widthYes
fgetsa line, max size minus 1newline or limitYes
getsa linenewlineNever. Removed in C11

String Input and Output on Microcontrollers

On a desktop, stdin and stdout just work. On a microcontroller they do not exist until you connect them to hardware, usually by retargeting the low-level read and write routines to a UART. Full printf and scanf pull in a lot of code, and many small projects use a reduced library or their own tiny functions that read characters from the UART until a newline arrives, storing them in a fixed array and adding the terminator. The concepts from this lecture, a bounded buffer and a terminator you always write yourself, apply unchanged.

A bounded UART line reader

Byte arrives → Store if space remains → Newline? → Write the NUL → Hand string to parser

Real-World Uses and Common Mistakes

Use 1

Serial console commands

Read a line from the UART, then split and compare it with known commands.

Use 2

Reading configuration names

Prompt for a device name with a width that matches the storage array.

Use 3

Logging

Print a fixed-size binary field as text using a precision.

MistakeEffectFix
scanf("%s", buf) with no widthOverflow on long inputAdd a width: %15s for 16 bytes
Expecting %s to read a sentenceOnly the first word is storedUse fgets
Ignoring the return valueUses unset variables on empty inputCompare it with the number of conversions you expect
Mixing scanf and fgetsLeftover newline gives an empty lineUse one style, or consume the rest of the line
Passing &buf where an address of char is expectedType warningPass buf

Best Practices, Performance and Security

  • Prefer fgets for lines and always trim the newline.
  • For any string input and output code, define the buffer size once, and build the scanf width from it, so they cannot drift apart.
  • Performance: scanf parses format strings at run time and is heavy for small devices; a hand-written character loop is smaller and faster.
  • Security: unbounded string input is the textbook cause of stack buffer overflows. Every read from outside your program needs a limit.

Summary and Key Takeaways

  • %s prints until the terminator and needs one to be there.
  • scanf("%s") reads one whitespace-free word and leaves the rest in the buffer.
  • A width of N needs an array of N + 1 bytes.
  • fgets reads a whole line safely; gets must never be used.
  • A precision such as %.4s prints a buffer that has no terminator.
  • Safe string input and output always has a limit: a width, a buffer size or a precision.

You can now handle string input and output in a C program safely. The final lecture of this chapter puts everything together in a small command-matching lab and then tests you with a quiz and a set of interview questions on C strings that employers like to ask.

Frequently Asked Questions

Why does string input with scanf(“%s”) read only one word?

The %s conversion skips leading whitespace, then reads characters until the next whitespace character. Spaces, tabs and newlines all end the word, so “Anil Reddy” gives you “Anil” first and leaves ” Reddy” in the input buffer.

Do I need the & operator when reading a string with scanf?

No. The array name already converts to the address of its first element, so you pass name, not &name. You do need & for single variables such as an int.

How do I stop scanf from overflowing my buffer?

Put a field width in the conversion: %15s reads at most 15 characters and adds the terminator, so it fits a 16-byte array. The width is always one less than the array size.

What is the safest way to read a whole line?

Use fgets(buf, sizeof buf, stdin). It reads at most size minus one characters, always terminates the string and keeps the newline if it fit. Remove the newline with buf[strcspn(buf, "\n")] = '\0'.

Why must I never use gets()?

gets has no way to limit the number of characters it stores, so any long line overflows the buffer. It was deprecated and then removed from the C standard in C11.

Can string output print a char array that has no terminator?

Yes, if you give printf a precision. %.4s writes at most four bytes and stops, so a four-byte UART buffer can be printed safely even without a zero byte.

Topics Covered in This Lecture

C string input and outputscanf percent sfgetsfield widthprintf precisionembedded C programmingfree embedded C course

Keep Going With the Free C Programming Course

EmbeddedPathashala teaches C from the first printf to embedded-ready pointers and strings, completely free. Next: a command-parser lab, a quiz and interview questions.

Need Help or More Information?

Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *