While input is not a number, goes into Infinite loop - c

I'm just a beginner and am trying to make a a program that asks for a number and if a letter is input, it says "that's not a number" and asks for a number again, until a number is input.
However, my program keeps going into an infinite loop with the current code. Any help would be appreciated to fix this. Also, I would also like the program to say "please input something" if nothing is input, but don't know how to do this. Thanks.
#include <stdio.h>
int main()
{
float i;
printf("enter a number");
while(scanf("%f", &i) != 1)
{
puts("That is not a number.");
scanf("%f", &i);
}
}

You need to clear the bad input from stdin after your scanf fails:
#include <stdio.h>
int main()
{
float i;
char trash[1024];
while (1)
{
printf("Please enter a number: ");
fflush(stdout);
if (1 == scanf("%f", &i))
break;
/* scanf failed: clear the bad input from stdin */
if (NULL == fgets(trash, sizeof(trash), stdin)) /* NOTE: assumes 1 entry per line and no line longer than 1023 characters */
exit((fprintf(stderr, "Unexpected EOF or error!\n"), 1));
puts("That is not a number.");
}
printf("You entered: %f!\n", i);
return 0;
}
As an alternative to the fgets() to clear the line, you could call scanf("%1023s", trash), which would only suck in the next whitespace delimited series of characters. This would allow you to handle multiple entries on a single line with mistakes intermixed, for example.

Your program goes into infinite loop because after the invalid input, (scanf("%d", &i) != 1)condition being TRUE, the invalid input which is left in the input buffer is not consumed, it's still in the buffer. So the same invalid input is read over and over again.
To avoid, once scanf() fails, you need to flush out all the input buffer contains before calling next scanf().
Maybe inside the while loop, calling getchar() until a newline or EOF will help. Also, the second scanf() can be removed, IMHO.

After your non numeric[More precisely input which doesn't match the formating of scanf()] input you need to clear the stdin. If not the same input will be read till stdin get cleaned or you terminate the program. A reference answer can be found on this question
Quoted
On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.
Reason for infinite loop : Since you don't clear stdin, same values will be read by scanf() and always full fill while condition resulting in a infinite loop.
Use following edited code :
#include <stdio.h>
int main()
{
float i;
char c;
printf("enter a number");
while(scanf("%f", &i) != 1)
{
puts("That is not a number.");
scanf("%f", &i);
while ((c = getchar()) != '\n' && c != EOF); // Flush stdin
}
}

Your code is taking input of a number. Thats why if you even give input a letter, it will take the ASCII value of the letter, which is a valid number. And Further more please take a character as an input. Here I have modified your code which should work
#include <stdio.h>
int main()
{
char i;
printf("enter a number");
while(1)
{
scanf("%c",&i);
if (c >=48 && c <= 57) // here ascii value of numbers between 0-9 is 48-57 respectively
{
puts("That is a number.");
break;
}
else
{
puts("That is not a number.");
scanf("%c",&i);
}
}
}

Related

Issues with scanf() and accepting user input

I am trying to take in user input with spaces and store it in an array of characters.
After, I want to take in a single character value and store it as a char.
However, when I run my code, the prompt for the character gets ignored and a space is populated instead. How can I take in an array of chars and still be allowed to prompt for a single character after?
void main()
{
char userIn[30];
char findChar;
printf("Please enter a string: ");
scanf("%[^\n]s", userIn);
printf("Please enter a character to search for: ");
scanf("%c", &findChar);
//this was put here to see why my single char wasnt working in a function I had
printf("%c", findChar);
}
scanf("%c", &findChar); reads the next character pending in the input stream. This character will be the newline entered by the user that stopped the previous conversion, so findChar will be set to the value '\n', without waiting for any user input and printf will output this newline without any other visible effect.
Modify the call as scanf(" %c", &findChar) to ignore pending white space and get the next character from the user, or more reliably write a loop to read the read and ignore of the input line.
Note also that scanf("%[^\n]s", userIn); is incorrect:
scanf() may store bytes beyond the end of userIn if the user types more than 29 bytes of input.
the s after the ] is a bug, the conversion format for character classes is not a variation of the %s conversion.
Other problems:
void is not a proper type for the return value of the main() function.
the <stdio.h> header is required for this code.
Here is a modified version:
#include <stdio.h>
int main() {
char userIn[30];
int c;
char findChar;
int i, found;
printf("Please enter a string: ");
if (scanf("%29[^\n]", userIn) != 1) {
fprintf(stderr, "Input failure\n");
return 1;
}
/* read and ignore the rest of input line */
while ((c = getchar()) != EOF && c != '\n')
continue;
printf("Please enter a character to search for: ");
if (scanf("%c", &findChar) != 1) {
fprintf(stderr, "Input failure\n");
return 1;
}
printf("Searching for '%c'\n", findChar);
found = 0;
for (i = 0; userIn[i] != '\0'; i++) {
if (userIn[i] == findChar) {
found++;
printf("found '%c' at offset %d\n", c, i);
}
}
if (!found) {
printf("character '%c' not found\n", c);
}
return 0;
}
scanf("%[^\n]s", userIn); is a bit weird. The s is guaranteed not to match, since that character will always be \n. Also, you should use a width modifier to avoid a buffer overflow. Use scanf("%29[^\n]", userIn); That alone will not solve the problem, since the next scanf is going to consume the newline. There are a few options. You could consume the newline in the first scanf with:
scanf("%29[^\n]%*c", userIn);
or discard all whitespace in the next call with
scanf(" %c", &findChar);
The behavior will differ on lines of input that exceed 29 characters in length or when the user attempts to assign whitespace to findChar, so which solution you use will depend on how you want to handle those situations.

How to fix - unexpected output using getchar() and do-while

I am trying to make a simple code that will read a char from input and execute "Correct" or "Incorrect input" and run the code again until the correct input is entered. First of all it does not work for capital X. The other issue that I want to fix is that after the incorrect input I have to press enter to get the "Enter x" message, instead of getting in immediately after the incorrect input message.
#include <stdio.h>
int main()
{
do
{
printf("Enter x\n");
if (getchar()=='x'|| getchar()=='X')
{
printf("Entered char is X\n");
return 0;
}
else
{
printf("Input incorrect! Please try again!!!\n");
}
}
while (getchar()!='x' || getchar()!='X');
return 0;
}
You need to store the input in a variable, otherwise you keep asking for input several times in a row, for each getchar call.
For weird historic reasons, getchar actually returns an int, since the value EOF that can be returned from it is an int. So the variable must be int.
And finally, each time the user hits enter, a invisible line feed character \n is appended to the input stream. This character does you no good, so you should discard it with an extra read.
#include <stdio.h>
int main (void)
{
int input;
do
{
printf("Enter x\n");
input = getchar();
getchar(); // extra getchar to chew up line feed from stdin
if (input=='x'|| input=='X')
{
printf("Entered char is X\n");
}
else
{
printf("Input incorrect! Please try again!!!\n");
}
} while (input!='x' && input!='X');
return 0;
}
Please note that the opposite of input=='x'|| input=='X' is input!='x' && input!='X' (De Morgan's laws). "If input is not 'x' and input is not 'X' then loop".
When you hit the ENTER key the newline character \n is placed in input buffer. You need to consume that newline character in order to read the next character.
Also you are reading two time, which is unnecessary in this case. So your code should be like this
#include <stdio.h>
int main()
{
char inp;
do
{
printf("Enter x\n");
inp = getchar();
getchar(); // reading the newline character '\n'
if (inp == 'x'|| inp =='X')
{
printf("Entered char is X\n");
return 0;
}
else
{
printf("Input incorrect! Please try again!!!\n");
}
}
while (inp !='x' || inp !='X');
return 0;
}
p.s There is no need to put condition checking in while loop, since you are returning in if condition. while(true) would work fine. Thanks #bruno for pointing that out.
In your code:
if (getchar()=='x'|| getchar()=='X')
getchar() is called twice.
Instead, you should write it this way:
char c = getchar();
if (c=='x'|| c=='X')
for the second part, if your goal is print the message on a new line, then just simply change your printf to:
printf("\nInput incorrect! Please try again!!!\n");

EOF not working as expected (C)

I'm trying to use the EOF function but it doesn't work as I expect it. In the debugger mode it doesn't detect the second "scanf" function and just carries on. It keeps on missing out the "scanf" function now and then. Code is posted below
int main() {
char tempString;
int i = 0;
printf("Enter your letter\n");
scanf_s("%c", &tempString);
while (tempString != EOF) {
printf("You entered:%c\n", tempString);
scanf_s("%c", &tempString);
}
}
I have also tried it using the getchar() function but the same thing occurs, code is posted below:
int main() {
char tempString;
int i = 0;
printf("Enter your letter\n");
while ((tempString = getchar()) != EOF) {
printf("You entered:%c\n", tempString);
}
}
Thanks for reading
EDIT:
Firstly you omitted the length argument required by scanf_s for %c and %s formats.
Second, the %c format takes the next character from the input buffer. At the second (and subsequent) entries there was a newline left in the input buffer from the first input. Adding a space before the %c format specifier cleans off that leading whitespace.
Other formats, such as %s and %d do ignore leading whitespace, but not %c.
Thirdly, with scanf the use of EOF is not the way to go, you should control the loop with the return value from scanf which tells you the number of items successfully read.
This program starts by using scanf_s. The second entry ignores the newline after the first entry.
Then it moves to using getchar. In this test the function return value is int, so that's my data type here. That way EOF (-1) won't conflict with any required character data. Note that getchar starts by reading the newline left after the previous scanf_s (which only ignores leading whitespace.
#include <stdio.h>
int main(void)
{
char ch_scanf; // char type
int ch_getchar; // int type
printf("Using scanf_s\n");
if (scanf_s(" %c", &ch_scanf, 1) == 1) { // consumes any leading whitespace
printf("scanf_s value: %d\n", ch_scanf);
}
if (scanf_s(" %c", &ch_scanf, 1) == 1) { // consumes any leading whitespace
printf("scanf_s value: %d\n", ch_scanf);
}
printf("\nUsing getchar\n");
while ((ch_getchar = getchar()) != EOF) {
printf("getchar value: %d\n", ch_getchar);
}
return 0;
}
Sample session:
Using scanf_s
A
scanf_s value: 65
B
scanf_s value: 66
Using getchar
getchar value: 10
C
getchar value: 67
getchar value: 10
^Z
Finally if you want to use the standard library function scanf without MSVC ticking you off, you can do it like this
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
try this
#include <stdio.h>
int main(void) {
char tempString;
printf("Enter your letter\n");
while (scanf_s("%c%*c", &tempString, 1) != EOF) {//%*c for consume newline, 1 is buffer size
printf("You entered:%c\n", tempString);
}
return 0;
}
int tempString;//int for check EOF
printf("Enter your letter\n");
while ((tempString = getchar()) != EOF) {
printf("You entered:%c\n", tempString);
getchar();//consume newline
}
The behaviour of scanf() function in C
Is to read the input from the keyboard buffer till it encounters EOF (ie; till we
press enter key)
In general, it is not advisable to use "%c" in C to read an input character because
The value is collected in keyboard buffer till we hit enter and we could not restrict user entering single character
So, the best way to obtain a character is by using getchar() function.
In the program you have provided you can use any other character to check for end and not EOF since it is used in scanf() implementation to mark the input end.
You may other keys like esc to check for the end
#include <stdio.h>
#include <stdlib.h>
#define esc 27
int main()
{
char ch;
while((ch = getchar()) != esc) {
//print the entered character here
}
}
To know in depth about scanf() implementation look into this scanf() source code

when scanf returns 0 in c and just doesn't work

'when there is no successful assignments' i know that scanf returns 0 to indicate it, but is that the only thing that it does? this is my code:
#include<stdio.h>
int main(void) {
int val,x;
x=scanf("%d",&val);
if(x==1)
printf("success!");
else{
printf("try again\n");
scanf("%d",&val);
}
return 0;
}
if i enter a number, it works fine but if i enter a character scanf doesn't work anymore, this is what i get:
k
try again
process returned 0 (0x0) execution time :2.578 s
press any key to continue.
_
meaning that it doesn't allow me to enter a new value, why is that? is there something wrong in the code? if yes how can i fix it? should i stop using scanf?
When scanf doesn't work, the invalid data is still left in the stream. You'll have to read and discard the data from the stream first before you can enter more data.
#include<stdio.h>
int main(void) {
int val,x;
x=scanf("%d",&val);
if(x==1)
printf("success!");
else{
// Discard everything upto and including the newline.
while ( (x = getchar()) != EOF && x != '\n' );
printf("try again\n");
scanf("%d",&val);
}
return 0;
}
The scanf family of functions are broken-as-specified and should never be used for anything.
The correct way to write this program is to use getline, if available, or fgets otherwise, to read an entire line of user input. Then use strtol to convert the input to a machine integer, taking care to check for errors:
errno = 0;
result = strtol(line, &endptr, 10);
if (endptr == line || *endptr != '\n' || errno)
// invalid input

How to check if the user input an integer using scanf

I created a program to make a diamond out of *'s. I am looking for a way to check if the type of input is an integer in the C language. If the input is not an integer I would like it to print a message.
This is what I have thus far:
if(scanf("%i", &n) != 1)
printf("must enter integer");
However it does not display the message if it's not an integer. Any help/guidance with this issue would be greatly appreciated!
you can scan your input in a string then check its characters one by one, this example displays result :
0 if it's not digit
1 if it is digit
you can play with it to make your desired output
char n[10];
int i=0;
scanf("%s", n);
while(n[i] != '\0')
{
printf("%d", isdigit(n[i]));
i++;
}
Example:
#include <stdio.h>
#include <string.h>
main()
{
char n[10];
int i=0, flag=1;
scanf("%s", n);
while(n[i] != '\0'){
flag = isdigit(n[i]);
if (!flag) break;
i++;
}
if(flag)
{
i=atoi(n);
printf("%d", i);
}
else
{
printf("it's not integer");
}
}
Use fgets() followed by strtol() or sscanf(..."%d"...).
Robust code needs to handle IO and parsing issues. IMO, these are best done separately.
char buf[50];
fgets(buf, sizeof buf, stdin);
int n;
int end = 0; // use to note end of scanning and catch trailing junk
if (sscanf(buf, "%d %n", &n, &end) != 1 || buf[end] != '\0') {
printf("must enter integer");
}
else {
good_input(n);
}
Note:
strtol() is a better approach, but a few more steps are needed. Example
Additional error checks include testing the result of fgets() and insuring the range of n is reasonable for the code.
Note:
Avoid mixing fgets() and scanf() in the same code.
{ I said scanf() here and not sscanf(). }
Recommend not to use scanf() at all.
strtol
The returned endPtr will point past the last character used in the conversion.
Though this does require using something like fgets to retrieve the input string.
Personal preference is that scanf is for machine generated input not human generated.
Try adding
fflush(stdout);
after the printf. Alternatively, have the printf output a string ending in \n.
Assuming this has been done, the code you've posted actually would display the message if and only if an integer was not entered. You don't need to replace this line with fgets or anything.
If it really seems to be not working as you expect, the problem must be elsewhere. For example, perhaps there are characters left in the buffer from input prior to this line. Please post a complete program that shows the problem, along with the input you gave.
Try:
#include <stdio.h>
#define MAX_LEN 64
int main(void)
{ bool act = true;
char input_string[MAX_LEN]; /* character array to store the string */
int i;
printf("Enter a string:\n");
fgets(input_string,sizeof(input_string),stdin); /* read the string */
/* print the string by printing each element of the array */
for(i=0; input_string[i] != 10; i++) // \0 = 10 = new line feed
{ //the number in each digits can be only 0-9.[ASCII 48-57]
if (input_string[i] >= 48 and input_string[i] <= 57)
continue;
else //must include newline feed
{ act = false; //0
break;
}
}
if (act == false)
printf("\nTHIS IS NOT INTEGER!");
else
printf("\nTHIS IS INTEGER");
return 0;
}
[===>] First we received input using fgets.Then it's will start pulling each digits out from input(starting from digits 0) to check whether it's number 0-9 or not[ASCII 48-57],if it successful looping and non is characters -- boolean variable 'act' still remain true.Thus returning it's integer.

Resources