How to check if scanf() worked fine in C? [duplicate] - c

This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 7 years ago.
I am trying to see if user enters 3 correct input. If not the loop ask for input again and again until they correct it correctly.
#include <stdio.h>
int main(void) {
int num1,num2;
char str;
int check;
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
while (check != 3) {
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
}
}
Let's say if I entera, 5.4, c we get an infinite loop. Why is it giving an infinite loop?

There are far more ways to incorrectly use scanf in a loop that proper ones. The primary issue (aside from input or matching failures that are explained in the man page), is failing to empty the input buffer (stdin when reading from a terminal) after a failed conversion. (There is also the issue that the user must enter something.) When a user enters text and presses [Enter] a newline ('\n') is generated and placed in the input buffer to mark the end of line. When you enter a, 5.4, c, 'a' is fine, but 5.4 is not an int and the processing fails:
If processing of a directive fails, no further input is read, and
scanf() returns.
When scanf returns, it leaves the remaining characters in stdin and you loop and attempt to read again. scanf attempts to read what is left in stdin, processing again fails, and the loop continues endlessly.
In this situation the only way to prevent the indefinite loop is to manually empty the input buffer after you call to scanf. Something simple will do:
int c;
...
while (...) {
scanf (...)
while ((c = getchar()) != '\n' && c != EOF) {}
}
This will insure you start with an empty buffer on the next iteration. For example:
#include <stdio.h>
int main (void) {
int num1 ,num2, c;
char str;
while (printf ("\nEnter : ") &&
scanf (" %d, %d, %c%*c", &num1, &num2, &str) != 3) {
printf ("error: invalid input, required: 'int, int, char'\n");
/* empty remaining chars from input buffer */
while ((c = getchar()) != '\n' && c != EOF) {}
}
printf ("\n num1 : %d\n num2 : %d\n str : %c\n\n", num1, num2, str);
return 0;
}
Example Use
$./bin/scanf3
Enter : a
error: invalid input, required: 'int, int, char'
Enter : a, 5.4, c
error: invalid input, required: 'int, int, char'
Enter : 10, 25
error: invalid input, required: 'int, int, char'
Enter : 10, 25, a
num1 : 10
num2 : 25
str : a
note: this does not protect against the user entering nothing (just pressing [Enter]) and the cursor just sitting there blinking as it waits for input. That is an inherent behavior of scanf, part of which is the reason that line-oriented input methods (fgets or getline) are preferable when taking input.

First time scanf() reads the character then it reads the newline (enter/whitespace character ).This character is present in the input buffer and is read by the scanf() function.
So clear the buffer before reading the new user input using fflush(stdin).
EDIT : Tested in windows VS2013.Sorry i dont have Linux. Windows and Linux define the behaviour of fflush() in different way.If you are using in Windows platform :
int main(void) {
int num1, num2;
char str;
int check;
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
while (check != 3) {
////Flush the input buffer ////
fflush(stdin);
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
}
}
EDIT : this will work in all platforms.
Another simple way is to consume the remaining read line by
while ((c = getchar()) != '\n' && c != EOF);
so now
int main(void) {
int num1, num2;
char str,c;
int check;
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
while (check != 3) {
////read the remaining char ////
while ((c = getchar()) != '\n' && c != EOF);
printf("Enter : ");
check = scanf("%d,%d, %c", &num1, &num2, &str);
}
}

Related

Scanf function skips

In similar questions, the scanf reading a char or string skips because it takes in a new line from the input buffer after the "Enter" key is pressed for the previous scanf, but I don't think that's the issue here. This program does not skip the 2nd scanf if input1 is an integer, but it skips it for other types of inputs (double, char, string, etc.).
#include <stdio.h>
#include <string.h>
int main(){
int input1;
char input2[6];
printf("Enter an integer. ");
scanf("%d", &input1);
printf("You chose %d\n", input1);
printf("Write the word 'hello' ");
scanf(" %s", input2);
if (strcmp(input2,"hello")==0){
printf("You wrote the word hello.\n");
} else {
printf("You did not write the word hello.\n");
}
return 0;
}
Why does this happen?
Comments in code:
int input1 = 0; // Always initialize the var, just in case user enter EOF
// (CTRL+D on unix) (CTRL + Z on Windows)
while (1) // Loop while invalid input
{
printf("Enter an integer. ");
int res = scanf("%d", &input1);
if ((res == 1) || (res == EOF))
{
break; // Correct input or aborted via EOF
}
int c;
// Flush stdin on invalid input
while ((c = getchar()) != '\n' && c != EOF);
}
printf("You chose %d\n", input1);
Also, take a look to How to avoid buffer overflow using scanf
Did you try to write "%*c" after your %c or %s or %d ?
Something like this : scanf("%s%*c", input1);

scanf different position in the code in c [duplicate]

This question already has answers here:
problem in scanning character in C
(8 answers)
Closed 1 year ago.
int main()
{
char Operator;
int num1, num2, result;
/* printf("Enter operator: ");
scanf("%c", &Operator);*/
printf("Enter first and second value: ");
scanf("%d %d", &num1, &num2);
printf("Enter operator: ");
scanf("%c", &Operator);
if(Operator == '+')
{
result = num1 + num2;
printf("%d\n", result);
}
else if(Operator == '-')
{
result = num1 - num2;
printf("%d\n", result);
}
return 0;
}
I tried making a simple calculator, and I put scanf(the one that requests an Operator) where it is now, and it does not work. But if I put it where the comment is, above the "Enter first and second value" it then works. I would just like to know why does it work on one place and not the other.
Thanks in advance.
As pointed out in comments, Your first scanf is reading the integer values but it's not reading the newline in buffer. When you do scanf("%c", &Operator) again for taking character input, it reads that newline character still present in input buffer. To avoid this, you can use scanf(" %c", %Operator) instead which will discard all whitespace characters before matching character:
printf("Enter operator: ");
scanf(" %c", &Operator);
You can also use fgets() to read input into a string and then use sscanf() to read integers from string:
char input[100];
printf("Enter first and second value: ");
if (fgets(input, 100, stdin) == NULL) {
printf("No input provided!\n");
return -1;
}
if (strchr(input, '\n') == NULL) {
printf("Input Buffer Overflow\n");
return -1;
}
if (sscanf(input, "%d %d", &num1, &num2) != 2) {
printf("Error in reading characters\n");
return -1;
}
printf("Enter operator: ");
if (fgets(input, 100, stdin) == NULL) {
printf("No input provided!\n");
return -1;
}
if (strchr(input, '\n') == NULL) {
printf("Input Buffer Overflow\n");
return -1;
}
if (sscanf(input, "%c", &Operator) != 1) {
printf("Error in reading characters\n");
return -1;
}
From the Open Group Base Specifications Issue,
Input white-space characters (as specified by isspace()) shall be
skipped, unless the conversion specification includes a [, c, C, or n
conversion specifier.
%d format specifier will skip preceding input newline character (\n). That's why it works in the first case (case, where operator was read first) .
scanf leaves an newline character \n in the input buffer, after the first scanf.
The second scanf will read the extra \n from the input buffer to variable Operator. That's why it will not work.
Since the format specifier is %c, the newline character will not be skipped.
Solution : Use scanf(" %c", &Operator);. Add an extra space at the beginning.

i cant get this program to work correctly.

I have been asked to modify a program to read characters rather than numbers.
i modified the array into a char array. changed the two "%d" to "%c" as below
void main (void)
{
char a[100];
int counter;
int b;
counter = 0;
printf("please enter the length of the array: ");
scanf("%d", &b );
while (counter != b)
{
printf("please enter character: ");
scanf("%c", &a[counter]);
counter++;
}
a[counter] = '\0' ;
counter = 0;
while (a[counter] != '\0')
{
printf("\n");
printf("%c",a[counter]);
counter++;
}
}
when i run this the program does this:
please enter the length of the array: (4)
please enter character: please enter character: (a)
please enter character: please enter character: (a)
a
a
() are used to indicate the user inputs.
would be really good if i could get some help.
You have to remember that scanf leaves the newline in the input buffer, so when you try to read a character it will that newline.
The solution is very simple: Tell scanf to read and discard leading whitespace, by adding a space in the format code:
scanf(" %c", &a[counter]);
/* ^ */
/* | */
/* Note space here */

Infinite loop when assigning a float to an integer

Please i'm having an issue with my program. Whenever i try to input a float it's getting into an infinity loop. I know that the input is stored as an integer. How can prevent the user from entering a float (how to filter the input).
Why is the program getting into an infinite loop when the input is a float.
This is an example:
#include <stdio.h>
main()
{
int i = 0;
while(i<10){
system("cls>null");
printf("%d^2 = %d\n", i, i*i);
printf("Index: ");
scanf("%d", &i);
}
}
When you call scanf to read a number, but the input contains something incompatible with the input format specifier, scanf does not consume such incorrect input, leaving it in the buffer. Your program does not clear the buffer on input mismatch, entering an infinite loop: scanf tries to read an int again, sees that it's not there, and exits without modifying i. Your loop sees that i is less than 10, and calls the scanf again.
To fix this, check that scanf returned one input. Use the input when it is correct, or call scanf again with the %*[^\n]\n specifier, which means "read to the end of the string, and discard the input":
if (scanf("%d", &i) != 1) {
scanf("%*[^\n]\n");
}
Note the asterisk - it means that the consumed input needs to be discarded, rather than being written into a variable.
Better use fgets() to read a complete line from stdin, and strtol()
to parse it into an number, for example:
char buffer[256];
char *endp;
int i;
while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
// buffer now contains one line (including the terminating newline)
i = (int)strtol(buffer, &endp, 10);
// endp points to the first character after the parsed number:
if (endp > buffer && (*endp == 0 || isspace(*endp))) {
printf("%d^2 = %d\n", i, i*i);
} else {
printf("invalid input\n");
}
}
#include <math.h>
#include <stdio.h>
int main (void)
{
int i = 0;
float j = 0;
while(i<10)
{
system("cls");
printf("%d^2 = %d\n", i, i*i);
printf("Index: ");
if (scanf("%f", &j) <= 0 && j-fabs(j) != 0)
{
printf ("The input is not an interger");
}
}
}

Scan single character C

/*
Program to calculate trip and plan flights
*/
#define TRIP 6
#define DEST 1
#include <stdio.h>
int error_dest(int type_num, int cont_num, int dest_code, int check);
int main(void)
{
int check, type_num, cont_num, index, i, dest_code, trip_num, row, col;
int travelint[TRIP][DEST], travelarea[TRIP];
char area_code, S, M, L, N, P, K, R, C, U, W, O;
trip_num = 7;
while (trip_num > TRIP)
{
printf("Please enter the number of trips:");
scanf("%d", &trip_num);
if ( trip_num < TRIP)
{
printf("Valid trip number. Please proceed to enter destination code.\n");
}
else
{
printf("Invalid trips. Please enter no more then 6 trips.\n");
}
}
/*********************************************************************************/
for (i=0; i < trip_num ; i++) /*destination code input*/
{
printf("Please enter destination code:");
scanf("%d", &dest_code); /*input of destination code*/
check = error_dest(type_num, cont_num, dest_code, check);
if (check == 2)
{ travelint[i][0]=dest_code; }
else
{
while (check == 1)
{
printf("Please enter destination code:");
scanf("%d", &dest_code); /*input of destination code*/
check = error_dest(type_num, cont_num, dest_code, check);
if (check == 2)
{ travelint[i][0]=dest_code; }
}
}
printf("Please select from the following that best describes your destination:\n");
printf("S Small city - population under 50,000\n");
printf("M Medium city - population between 50,000 and 500,000\n");
printf("L Large city - pop. over 500,000\n");
printf("N Natural formation like a mountain, a lake, a cave, a geyser, a fjord, a canyon, etc.\n");
printf("P Designated park or reserve such as a wildlife refuge, a national park, a bioreserve, or a protected marine area\n");
printf("K Man made landmark like the Great Wall of China, the Taj Mahal, or Stonehenge\n");
printf("R State or province or region of a country\n");
printf("C Whole country\n");
printf("U Multiple countries like traveling through Europe\n");
printf("W Ocean voyage\n");
printf("O Any other type of destination - such as visiting the sites of the seven wonders of the world\n");
printf("Please enter the Area Letter code:");
scanf("%c", &area_code);
}
/*******************************************************************************/
/*print for destination_code*/
for (row = 0; row < trip_num; row++)
{
for (col=0; col < DEST; col++)
printf("Trip[%d] = %d\n", row+1, travelint[row][col]);
}
return 0;
}
error_dest(type_num, cont_num, dest_code, check)
{
cont_num = dest_code / 10000; /*math for error check*/
type_num = dest_code/1000 - cont_num*10;
if ( (cont_num <= 7) && (cont_num > 0) && (type_num <= 5) && (type_num >=0) )
{ /* loop for checking destination code*/
check = 2 ;
return check;
}
else
{
printf("%d is a invalid code\n", dest_code);
check = 1;
return check;
}
}
for some strange reason at the scanf("%c", &area_code); it just runs ahead and print the dest_code array without letting me input any character and I'm not sure what exactly I am doing wrong.
If you're looking to grab only one character, perhaps it would be better to use getchar() instead of scanf()?
Basically what's happening is this: you print the "Please enter the number of trips" message to the screen. The user types in 4 and then hits the enter key, which means the stdin buffer looks like this: "4\n". You then call scanf with the "%d" format string. scanf looks at the stdin buffer, and sees the 4. It looks at the next character, which is the newline, and sees it's not part of a number (as %d specifies), so it is done fulfilling the format string and leaves the file pointer at the newline. It converts the char '4' to an integer 4 and places it in trip_num and returns.
The next time you call scanf, it picks up where it left off at the newline. The format string this time is "%c", so it just grabs the next character from the buffer which is currently the newline ("\n"), places it in dest_code, and returns. If you want the scanf function to skip over the whitespace in this case, you have to explicitly tell it by adding a space before the "%c" format for the second scanf (destination code). Then scanf will skip over all whitespace (including that newline) until it encounters a non-whitespace character that it places in dest_code.
TL;DR: Change the second scanf call to scanf(" %c", &dest_code). And fix the other errors others have pointed out so other bugs won't manifest.
You may print area_code after scanf, I guess it may be '\n' which is the last character of the dest_code line you entered.
You should empty the buffer before reading a character from stdin:
int c = 0;
while (c != '\n' && c != EOF)
{
c = getchar();
}
then you can read your character using scanf or replace it with getchar.
This may or may not help, but previously stated you probably need to put the getchar() into the while loop. You may also need the fgets to grab the stdin from the keyboard.
while(1){
printf("Enter Message Type:");
fflush(stdout) ;
// scan msg.hdr from received message.
scanf("%d", &(msg.m_hdr));
while(getchar() != '\n'){}
printf("Enter your Message:");
fflush(stdout);
// grab data from keyboard
fgets(msg.m_data, sizeof(msg.m_data), stdin);
Use "fflush(stdin)" before you enter the character, i.e. before the "printf" statement for the character. It will flush out the input buffer and thus you can scan the desired character. Or simply give a Space before the "%c" command. Like---------- scanf(" %c", &area_code); ---------------

Resources