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.
Explain
Read a bounded line and reject a numeric value outside the permitted range.
Trace
Run the same program with 31 instead of 28 and explain why it rejects the answer.
Apply
Reject invalid text instead of silently using an incorrect integer.
Input and Output: follow the data
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.
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.
Result
Count: 28
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
Read the starting values
The supplied sample line is 28 followed by a newline. strtol reads 28 and the helper skips its trailing whitespace.
Perform the operation
The range check succeeds, so the helper writes 28 into the caller’s count and printf formats that int using %d.
Check the observable result
Count: 28
Count: 28
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.
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.