Mixing functions like fgets()
, scanf()
, and getchar()
is error-prone. The scanf()
function usually leaves a \n
character behind in the input stream, while fgets()
usually does not, meaning that the next call to an I/O function may or may not need to cope with what the previous call has left in the input stream.
A better solution is to use one style of I/O function for all user input. fgets()
used in conjunction with sscanf()
works well for this. Return values from functions should be checked, and fgets()
returns a null pointer in the event of an error; sscanf()
returns the number of successful assignments made, which can be used to validate that input is as expected.
Here is a modified version of the posted code. fgets()
stores input in a generously allocated buffer; note that this function stores input up to and including the \n
character if there is enough room. If the input string is not expected to contain spaces, sscanf()
can be used to extract the string, leaving no need to worry about the newline character; similarly, using sscanf()
to extract character or numeric input relieves code of the burden of further handling of the \n
.
#include <stdio.h>
int main(void)
{
int testcase;
char arr[30];
char F;
int m;
char buffer[1000];
do {
puts("Enter number of test cases:");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
} while (sscanf(buffer, "%d", &testcase) != 1 || testcase < 0);
while(testcase--)
{
puts("Enter the string");
/* if string should not contain spaces... */
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
sscanf(buffer, "%29s", arr);
printf("You entered: %s\n", arr);
putchar('\n');
puts("Enter a character");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
sscanf(buffer, "%c", &F);
printf("You entered: %c\n", F);
putchar('\n');
do {
puts("Enter a number");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* handle error */
}
} while (sscanf(buffer, "%d", &m) != 1);
printf("You entered: %d\n", m);
putchar('\n');
}
return 0;
}
On the other hand, if the input string may contain spaces, fgets()
can read input directly into arr
, but then the stored string will contain a \n
character, which should probably be removed. One way of doing this is to use the strcspn()
function to find the index of the \n
:
#include <string.h> // for strcspn()
/* ... */
puts("Enter the string");
/* or, if string may contain spaces */
if (fgets(arr, sizeof arr, stdin) == NULL) {
/* handle error */
}
/* replace newline */
arr[strcspn(arr, "\r\n")] = '\0';
printf("You entered: %s\n", arr);
putchar('\n');
/* ... */
Note that a maximum width should always be specified when using %s
with the scanf()
functions to avoid buffer overflow. Here, it is %29s
when reading into arr
, since arr
can hold 30 char
s, and space must be reserved for the null terminator (\0
). Return values from sscanf()
are checked to see if user input is invalid, in which case the input is asked for again. If the number of test cases is less than 0, input must be entered again.