ProgramGuru

C Input and Output: Read Bounded Text and Validate Numbers

C Input and Output: Read Bounded Text and Validate Numbers

A school form receives text, not automatically a valid student count. A blank, overlong or nonnumeric answer needs to be rejected before arithmetic uses it.

Output formatting describes values with a matching printf conversion. Input must first fit its buffer and then satisfy a conversion and range contract before it becomes trusted program data.

  1. Explain

    Read a bounded line and reject a numeric value outside the permitted range.

  2. Trace

    Run the same program with 31 instead of 28 and explain why it rejects the answer.

  3. Apply

    Reject invalid text instead of silently using an incorrect integer.

Input and Output: follow the data

  1. Start

    A school form receives text, not automatically a valid student count. A blank, overlong or nonnumeric answer needs to be rejected before arithmetic uses it.

  2. Operation

    Output formatting describes values with a matching printf conversion. Input must first fit its buffer and then satisfy a conversion and range contract before it becomes trusted program data.

  3. Result

    Count: 28

A guided model of this example. The illustration explains the process; run the complete C program to check its output.

Understand the operation

fgets reads at most capacity minus one characters and adds a terminator on success. Check its return value and detect a line that did not fit; otherwise a partial answer can masquerade as complete input.

strtol supplies both a converted value and an end position. errno detects range failure; the end position reveals missing digits or unwanted trailing text. The helper checks the allowed count 0–30 before converting to int. Pointer parameters are introduced here as addresses; the pointer lesson explains their object-access mechanics.

Read the complete C program

This complete C17 program uses a small school example. Read declarations before the statements that use their values. Each printf format describes how the corresponding value is written to standard output.

C17 · complete program

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
static int parse_count(const char *line, int *count) {
  char *end;
  errno = 0;
  long value = strtol(line, &end, 10);
  if (end == line || errno == ERANGE) return 0;
  while (isspace((unsigned char)*end)) end++;
  if (*end != '\0' || value < 0 || value > 30) return 0;
  *count = (int)value;
  return 1;
}
int main(void) {
  char line[64];
  int count;
  if (fgets(line, sizeof line, stdin) == NULL || (strchr(line, '\n') == NULL && !feof(stdin)) || !parse_count(line, &count)) {
    puts("Enter a whole count from 0 to 30");
    return 0;
  }
  printf("Count: %d\n", count);
  return 0;
}

Example input

28

Expected output

Count: 28
Run in C compiler →

Follow the values through the code

C17 · code used in this explanation

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
static int parse_count(const char *line, int *count) {
  char *end;
  errno = 0;
  long value = strtol(line, &end, 10);
  if (end == line || errno == ERANGE) return 0;
  while (isspace((unsigned char)*end)) end++;
  if (*end != '\0' || value < 0 || value > 30) return 0;
  *count = (int)value;
  return 1;
}
int main(void) {
  char line[64];
  int count;
  if (fgets(line, sizeof line, stdin) == NULL || (strchr(line, '\n') == NULL && !feof(stdin)) || !parse_count(line, &count)) {
    puts("Enter a whole count from 0 to 30");
    return 0;
  }
  printf("Count: %d\n", count);
  return 0;
}

The supplied sample line is 28 followed by a newline. strtol reads 28 and the helper skips its trailing whitespace.

The range check succeeds, so the helper writes 28 into the caller’s count and printf formats that int using %d.

Follow the worked calculation

  1. Read the starting values

    The supplied sample line is 28 followed by a newline. strtol reads 28 and the helper skips its trailing whitespace.

  2. Perform the operation

    The range check succeeds, so the helper writes 28 into the caller’s count and printf formats that int using %d.

  3. Check the observable result

    Count: 28

    Count: 28
A guided model of this example. The illustration explains the process; run the complete C program to check its output.

Try a small variation

C17 · code used in this explanation

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
static int parse_count(const char *line, int *count) {
  char *end;
  errno = 0;
  long value = strtol(line, &end, 10);
  if (end == line || errno == ERANGE) return 0;
  while (isspace((unsigned char)*end)) end++;
  if (*end != '\0' || value < 0 || value > 30) return 0;
  *count = (int)value;
  return 1;
}
int main(void) {
  char line[64];
  int count;
  if (fgets(line, sizeof line, stdin) == NULL || (strchr(line, '\n') == NULL && !feof(stdin)) || !parse_count(line, &count)) {
    puts("Enter a whole count from 0 to 30");
    return 0;
  }
  printf("Count: %d\n", count);
  return 0;
}

Run the same program with 31 instead of 28 and explain why it rejects the answer.

Worked answer

The text contains a valid integer, but that integer violates the school’s separate 0–30 requirement. Parsing success and application validity are distinct checks.

C17 · complete program

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
static int parse_count(const char *line, int *count) {
  char *end;
  errno = 0;
  long value = strtol(line, &end, 10);
  if (end == line || errno == ERANGE) return 0;
  while (isspace((unsigned char)*end)) end++;
  if (*end != '\0' || value < 0 || value > 30) return 0;
  *count = (int)value;
  return 1;
}
int main(void) {
  char line[64];
  int count;
  if (fgets(line, sizeof line, stdin) == NULL || (strchr(line, '\n') == NULL && !feof(stdin)) || !parse_count(line, &count)) {
    puts("Enter a whole count from 0 to 30");
    return 0;
  }
  printf("Count: %d\n", count);
  return 0;
}

Example input

31

Expected output

Enter a whole count from 0 to 30
Run in C compiler →

Recognize the important boundaries

printf %d expects an int argument; %zu expects size_t. A mismatched format is not merely a visual formatting problem.

Checking scanf’s return count helps detect conversion failure but does not make an out-of-range numeric conversion safe. Use checked text conversion for untrusted numeric input. fgets reads text lines, not arbitrary binary records.

Check your understanding

Choose the answer, then compare the reasoning for every option.

Why reject 31 when strtol converted it successfully?
Choose one answer. You can try again.

Answer and explanation

It exceeds the allowed classroom capacity.

Correct. The syntax of a number and its permitted application range are different contracts.

Use the idea independently

Output formatting describes values with a matching printf conversion. Input must first fit its buffer and then satisfy a conversion and range contract before it becomes trusted program data.

Continue with string storage and termination.

Language reference: WG14 C11 committee draft. These examples use the C17-compatible subset of the explained language features.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: C Hello World Program →