C User Input
Introduction to User Input in C
User input is a fundamental aspect of interactive programs. In C, there are several functions available for reading input from the user, each with its own characteristics and use cases.
Understanding how to properly handle user input is crucial for creating robust applications that can handle various types of data and prevent common issues like buffer overflows.
The scanf() Function
scanf() is the most commonly used function for reading formatted input in C. It reads data from stdin (standard input) and stores it according to the specified format.
Syntax: int scanf(const char *format, ...);
The function returns the number of successfully read items, or EOF on error.
#include <stdio.h>
int main(void) {
int age;
float height;
char name[50];
printf("Enter your name: ");
scanf("%49s", name); // Reads a single word (bounded)
printf("Enter your age and height: ");
int itemsRead = scanf("%d %f", &age, &height);
// Output without using \n in string literals
puts("");
printf("Hello %s!", name);
puts("");
printf("You are %d years old and %.2f meters tall.", age, height);
puts("");
printf("Items successfully read: %d", itemsRead);
puts("");
return 0;
}
Enter your name: John Enter your age and height: 25 1.75 Hello John! You are 25 years old and 1.75 meters tall. Items successfully read: 2
Limitations of scanf()
While scanf() is convenient, it has several limitations:
1. It stops reading at whitespace, making it unsuitable for reading strings with spaces
2. It doesn't perform bounds checking unless you provide a field width
3. It can leave unwanted characters (like newlines) in the input buffer
4. It requires precise format matching
#include <stdio.h>
int main(void) {
char city[20];
printf("Enter your city: ");
scanf("%19s", city); // Will only read until first space
printf("City: %s", city);
puts("");
// Safer bounded read to prevent overflow in smallBuffer
char smallBuffer[5];
printf("Enter a short word (max 4 chars): ");
scanf("%4s", smallBuffer); // Bounded — leaves room for '\0'
printf("Buffer content: %s", smallBuffer);
puts("");
// DANGER (do not enable): removing the width specifier can overflow
// scanf("%s", smallBuffer); // Potential buffer overflow
return 0;
}
Enter your city: New York City: New Enter a short word (max 4 chars): ThisIsALongString Buffer content: This
The fgets() Function
fgets() is a safer alternative for reading strings. It reads a line of input and includes the newline character, and it allows you to specify the maximum number of characters to read.
Syntax: char *fgets(char *str, int n, FILE *stream);
It returns the string pointer on success, or NULL on error or end of file.
#include <stdio.h>
#include <string.h>
int main(void) {
char name[50];
printf("Enter your full name: ");
if (fgets(name, sizeof(name), stdin)) {
name[strcspn(name, "\n")] = '\0'; // remove trailing newline if present
printf("Hello, %s!", name);
puts("");
}
// Reading another line
char address[100];
puts("Enter your address (press Enter when done):");
if (fgets(address, sizeof(address), stdin)) {
address[strcspn(address, "\n")] = '\0';
printf("Address: %s", address);
puts("");
}
return 0;
}
Enter your full name: John Doe Hello, John Doe! Enter your address (press Enter when done): 123 Main Street, City, State Address: 123 Main Street, City, State
Mixing scanf() and fgets() (Clearing Leftover Newlines)
When you use scanf() and then fgets(), the newline left in the input buffer by pressing Enter can cause fgets() to read an empty line. To avoid this, consume the leftover characters (usually the trailing '\n') before calling fgets().
#include <stdio.h>
int main(void) {
int n;
char line[64];
printf("Enter an integer: ");
if (scanf("%d", &n) == 1) {
int ch; // consume the rest of the line, including the newline
while ((ch = getchar()) != '\n' && ch != EOF) { }
}
printf("Enter a sentence: ");
if (fgets(line, sizeof line, stdin)) {
printf("You typed: %s", line);
}
return 0;
}
Reading Different Data Types
For reading different data types, you can combine fgets() with conversion functions like atoi(), atof(), or strtol()/strtod() for better error handling and safety.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char input[100];
int age;
double salary;
// Reading and converting integers
printf("Enter your age: ");
fgets(input, sizeof(input), stdin);
age = atoi(input); // Simple conversion (no error reporting)
// Reading and converting floating-point numbers
printf("Enter your salary: ");
fgets(input, sizeof(input), stdin);
salary = atof(input); // Simple conversion (no error reporting)
printf("Age: %d, Salary: $%.2f", age, salary);
puts("");
// Better error handling with strtol
printf("Enter a number: ");
fgets(input, sizeof(input), stdin);
char *endptr;
long number = strtol(input, &endptr, 10);
if (endptr == input) {
puts("No digits were found");
} else if (*endptr != '\0' && *endptr != '\n') {
printf("Further characters after number: %s", endptr);
puts("");
} else {
printf("Number: %ld", number);
puts("");
}
return 0;
}
Enter your age: 30 Enter your salary: 50000.50 Age: 30, Salary: $50000.50 Enter a number: 42abc Further characters after number: abc
Input Validation
Proper input validation is essential for creating robust programs. You should always validate that input meets expected criteria before using it.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void) {
char input[100];
int valid = 0;
int number = 0;
while (!valid) {
printf("Enter a positive integer: ");
if (!fgets(input, sizeof(input), stdin)) return 1;
// Check if input is a valid positive integer
valid = 1;
for (int i = 0; input[i] != '\0' && input[i] != '\n'; i++) {
if (!isdigit((unsigned char)input[i])) {
valid = 0;
puts("Invalid input. Please enter digits only.");
break;
}
}
if (valid) {
number = atoi(input);
if (number <= 0) {
valid = 0;
puts("Number must be positive.");
}
}
}
printf("You entered: %d", number);
puts("");
return 0;
}
Enter a positive integer: abc Invalid input. Please enter digits only. Enter a positive integer: -5 Invalid input. Please enter digits only. Enter a positive integer: 0 Number must be positive. Enter a positive integer: 42 You entered: 42
Best Practices for User Input
1. Use fgets() instead of gets() or unbounded scanf() for reading strings
2. Always check the return value of input functions
3. Validate input before using it
4. Use appropriate conversion functions with error checking (strtol/strtod for robust parsing)
5. Be aware of buffer sizes and prevent overflows (use field widths with scanf)
6. Clear the input buffer when mixing scanf() and fgets()
7. Provide clear prompts and error messages