Stuck in a infinite loop after inputing the exit condition. - c

I am trying to make this run in a loop until a non-numeric input is given. The problem is that when I input a letter to exit the while loop, it goes into an infinite loop. It also goes into the first if statement and continues to loop through that. If someone has any ideas on how to fix this, it would be great.
int counter;
int input[100]
int num = 1
while (input[num] == 0)
{
printf("score #%d:", counter);
scanf("%d",&input[num]);
if (input[num] <= 0){
printf("you cannot use negative numbers\n");
continue;
}
if (input[num] >= 100){
printf("you cannot use numbers greater than 100\n");
continue;
}
num++;
counter++;
}

The problem is that when scanf is provided with a non-numeric input when you try reading with %d format, the non-numeric data does not get removed from the buffer. When your loop reaches scanf again, it gets the same data, and continues failing in an infinite loop.
To fix this, remove non-numeric input when scanf does not read a proper number of items:
int readCount = scanf("%d",&input[num]);
if (readCount != 1) {
scanf("%*s");
printf("Please enter a valid number.\n");
continue;
}
Note that your loop's ending condition is incorrect, because num is always past the last element that has been read. You can fix it like this:
while (num < 100)
{
... // Read and error checks go here
if (input[num] == 0) {
break;
}
num++;
counter++;
}

First of all,num is supposed to be 0 as array index starts from 0 not 1.
Then,you have input[num]==0 in the condition in the while . You test using an uninitialized variable as input has not been initialized. This is the same for counter.
Your code won't compile as you have missed the ; at the end of line 2 and 3.
Lastly,replace your scanf with the following code:
if(scanf("%d",&input[num])==0)
{printf("non-numeric character entered .Exiting loop...\n");
scanf("%*s");// asterick tells scanf to discard scanned string(clear the entered char)
break;
}
So finally,the modified code:
int counter=1; // initialize variable
int input[100]; //semicolon here
int num = 0; //num must be 0
while (1) //infinite loop
{
printf("score #%d:", counter);
if(scanf("%d",&input[num])==0) //if no value is scanned
{printf("non-numeric character entered .Exiting loop...\n");
scanf("%*s");// asterick tells scanf to discard scanned string(clear the entered char)
break;
}
if (input[num] <= 0 )
printf("you cannot use negative numbers\n");
else if (input[num] >= 100)
printf("you cannot use numbers greater than 100\n");
else{
num++;
counter++;}
}

Related

How to limit an integer's input to 2-12 only?

I want to strictly limit a user's input on an integer in this program to 2-12 only. How do I do that?
#include <stdio.h>
int main(){
int i;
scanf("%d", &i);
int diceThrown, diceResult;
int sum = 0;
for(diceThrown = 1; diceThrown <= i; diceThrown++){
scanf("%d", &diceResult); //limit this input to 2-12 only, how?
sum += diceResult;
}
if(sum >= 40){
sum = sum % 40;
if(sum == 12){
printf ("28\n");
} else if(sum == 35){
printf ("7\n");
} else{
printf ("%d\n", sum);
}
} else if(sum < 40){
if(sum == 12){
printf ("28\n");
} else if(sum == 35){
printf ("7\n");
} else{
printf ("%d\n", sum);
}
}
return 0;
}
Also just to clarify, that I'm still a beginner in programming (like only 2 months into C.SCi course), so if you could explain it to me like I'm not a expert that would be great.
scanf has no functionality to do what you want. You can just use an if to validate input.
if(scanf("%d", &diceResult) != 1 || diceResult < 2 || diceResult > 12) {
//handle invalid input here
}
If the input is invalid it is up to you what you want to do. You could ignore the input and ask the user to enter a valid number, you can quit the whole program or just ignore the error, or something else entirely.
You can also check the input repeatedly with an while:
while(scanf("%d", &diceResult) != 1 || diceResult < 2 || diceResult > 12) {
//prompt user to enter valid input here
}
As mentioned by chux, part of handling invalid input would be to cosume the invalid input and check for EOF.
The scanf("%d", &diceResult) != 1 will assure, that scanf actually read exactly one number and no parsing errors occurred.
Consider this:
#include <stdio.h>
int main(){
int x;
do
{
printf("give a number between [2-12]\n");
scanf ("%d",&x);
}
while(x<2 || x>12);
return 0;
}
You can use a do-while loop so that you only take the values that are between the 2-12 range. That way you can force the user to give an integer as an input that is in the range that you ask for, in that case from [2,12]. Otherwise the program will turn back and request a valid input again.

Wanted to check if the value entered is a number or else. "isdigit() is not working here as expected

I am stuck with a problem here in C. I am posting the question and the code I have written below. Here I have to enter 10 numbers in an array and then I need to check how many times a number appeared. But to verify that I have entered a number and not anything else, I have used "isdigit()" function. But this is of no use. Can anyone help me to solve it.
/*
(a) Ten numbers are entered from the keyboard into an array. The number to be searched is entered through the
keyboard by the user. Write a program to find if the number to be searched is present in the array and if it is present, display
the number of times it appears in the array.
*/
#include<stdio.h>
#include<ctype.h>
main()
{
int num[10];
int i, j, cnt=0;
char rept;
printf("Enter 10 numbers: \n\n");
for(i=0; i<=9; i++)
{
printf("Number %d = ", i+1);
scanf("%d", &num[i]);
fflush(stdin);
if ( !isdigit(num[i]) )
{
printf("OK\n");
}
else
{
printf("Invalid number. Enter again.\n");
i=i-1;
}
}
do
{
printf("\nEnter the number to be searched in array: ");
scanf(" %d", &j);
for (i=0 ; i<=24; i++)
{
if(num[i]==j)
cnt++;
}
if(cnt>0)
printf("\nNumber %d is present at %d places", j, cnt);
else
printf("\nNumber not present.");
printf("\n\nDo you want to search another number. Press Y to repeat. Any other key to exit");
fflush(stdin);
scanf("%c", &rept);
}while (rept=='y'||rept=='Y');
getch();
}
No you can't do that. isdigit() is supposed to work with characters and you passed a multigit integer variable.
What you can do is simply like this
if( scanf("%d",&a[i])== 1){
// you can be sure number is entered
}
And fflush(stdin) is undefined behavior.
So the use of scanf will be more prominent if you would do this
int clearstdin(){
int c;
while ((c = getchar()) != '\n' && c != EOF);
return (c == EOF);
}
In main()
int earlyend = 0;
for(size_t i=0; i<SIZE; i++){
...
...
int ret = scanf("%d",&a[i]);
while( ret == 0){
if( clearstdin() ){ /* EOF found */earlyend = 1; break; }
fprintf(stderr,"%s\n","Entered something wrong");
ret = scanf("%d",&a[i]);
}
if( earlyend ){ /*EOF found*/ }
if( ret == EOF) { /* Error occured */}
...
}
The %d conversion specifier will cause scanf to skip over any leading whitespace, then read a sequence of decimal digits, stopping at the first non-digit character. If there are no digit characters in the input (for example, you enter something like ”abc”), then nothing is read from the input stream, a[i] is not updated, and scanf will return 0 to indicate a matching failure.
So, you can do a test like
if ( scanf( “%d”, &a[i] ) == 1 )
{
// user entered valid input
}
But...
This doesn’t fully protect you from bad input. Suppose you enter something like ”123abc” - scanf will read, convert, and assign 123 and return a 1 indicating success, leaving ”abc” in the input stream to potentially foul up the next read.
Ideally, you’d like to reject the whole thing outright. Personally, I do this as follows:
char inbuf[SOME_SIZE]; // buffer to store input
if ( fgets( inbuf, sizeof inbuf, stdin ) ) // read input as text
{
char *chk; // use strtol to convert text to integer
int temp = (int) strtol( inbuf, &chk, 10 ); // first non-digit character written to chk
if ( isspace( *chk ) || *chk == 0 ) // if chk is whitespace or 0, input is valid
{
a[i] = temp;
}
else
{
// bad input
}
}
This still isn’t a 100% solution - it doesn’t make sure the user didn’t enter more characters than the buffer can hold, but it’s a step in the right direction.
Input validation in C is, frankly, a pain in the ass.

Read the digits for a number one at a time, checking for duplicates

The program is meant to receive a number, one digit at a time, and use that digit as an index for the array to check if it's true; if so then break out of the loop and if not, set it to true and continue scanning the other digits til it reaches the last. It's supposed to tell only if a digit was repeated or not at this point.
I have this code so far but I can't seem to get it working. Can anyone help me? I noticed while troubleshooting on my own by testing the value of the variables after execution that sometimes the digits aren't even read, only the first digit entered is read.
Here's the code:
#include <stdio.h>
#define true 1
#define false 0
typedef int bool;
int main(void)
{
// Variables to contain the seen digits
bool seendig[10] = { false };
long entered;
int container;
printf("This Program Is Designed To Determine If Any Digits Has Been Repeated!\n Please Enter a Number: ");
scanf("%1d", &entered);
while (entered > 0)
{
container = entered;
if (seendig[container])
break;
seendig[container] = true;
entered /= 10;
}
if (entered > 0)
printf("\nThe Digit Was Repeated\n\n");
else
printf("The Digit Was Not Repeated\n\n");
system("pause");
return 0;
}
The part
container = entered;
if (seendig[container])
will cause out-of-range access if 10 or larger integer is inputted.
I guess
container = entered;
should be
container = entered % 10;
to get the least significant digit in decimal.
Is your code only trying to let the user input 1 number? or many number? If it is the latter then your scanf("%1d",&entered); should be inside of a loop and also I would recommend that you use a post-test loop or do-while loop since you need to let the user input a number first before checking it.
You should also consider 0 since it is a valid index value in an array
do {
printf("This Program Is Designed To Determine If Any Digits Has Been Repeated!\nPlease Enter a Number: ");
scanf("%d", &temp);
entered = temp;
if(temp >= 0){
while(temp > 0){
entered = temp % 10;
temp/=10;
}
}else{
break;
}
if(entered >= 0 && seendig[entered] != true){
seendig[entered] = true;
}else{
flag = 1;
}
printf("\n");
}while(flag == 0);
if (entered >= 0){
if(flag == 1){
printf("\nThe Digit Was Repeated\n\n");
}else{
printf("The Digit Was Not Repeated\n\n");
}
}else{
printf("The Digit You have Inputted is a Negative Value\n\n");
}
you should add this line of code to end of your while loop
scanf_s("%d", &entered);

Error check for character when reading in integers in C

For my programming class I've written a program to calculate the sum of divisors. So I've gotten to my final part which is error checking, which I am having a problem with if I read a character in. I have searched on S.O. earlier,as well as tried to figure something out, and couldn't find a solution that works for endless negative numbers until 100.
When I hit a character it sets it to 0 and just goes to the end, where I want it to exit once it reads it in
int main (void){
int userIN=0;
int i = 0;
int next = 0;
int temp= 105;
int cycle;
puts("Enter up to 10 integers less than or equal to 100");
while(scanf("%d ", &userIN) !=EOF && (i < 10))
{
if(userIN > 100){
printf("Invalid Input\n");
exit(1);
}
else if(userIN < 100)
{
Thanks for the help in advance
EDIT: The program is cycling through correctly, My Issue is error checking for a character being entered not anything with the code itself
scanf() returns a value other than EOF if it cannot read the values specified by the format string (e.g. with %d, it encounters data like foo). You can check for that. The caveat is that it does not read the offending data from stdin, so it will still be there to affect the next call of scanf() - which can result in an infinite loop (scanf() reporting an error, call scanf() again, it encounters the same input so reports the same error).
You are probably better off reading a whole line of input, using fgets(). Then check the input manually or use sscanf() (note the additional s in the name). The advantage of such an approach is that it is easier to avoid an infinite loop on unexpected user input.
You could loop while i is less than 10. The first if will see if scanf failed. If so the input buffer is cleared and the while loop tries again. If EOF is captured, then exit. If scanf is successful, the input is compared to 100 and if in range, the while loop counter is incremented.
Declare int ch = 0;
while ( i < 10) {
printf("Enter %d of 10 integers. (less than or equal to 100)\n", i + 1);
if(scanf(" %d", &userIN) != 1)
{
while ( ( ch = getchar()) != '\n' && ch != EOF) {
//clear input buffer
}
if ( ch == EOF) {
exit ( 1);
}
}
else {
if(userIN > 100){
printf("Invalid Input\n");
}
else
{
i++;// good input advance to the next input
printf("Valid");
}
}
}

prevent reading and returning of string value

int getIndex(){
int index = 0;
do{
printf("Enter your Index(0..80),-1 to STOP,-2 to RESTART,-3 to START NEW BOARD: ");
scanf("%d", &index);
} while (!(index >= -3 && index <=80));
return index;
}
Hello, given that i have written the above method in C for a sudoku game board . what can i do to prevent the user from entering a alphabet? and keep prompting until the valid input is gotten. i have just started C .what is limiting me is the scanf flag specifier, i specified a int flag which means if a user enters a string, im screwed.
All you need is to check the return value of scanf and then clear the character from the input buffer(stdin) if any invalid input was entered. So change your code to the following:
int getIndex()
{
int index = 0;
while(1) //infinite loop
{ printf("Enter your Index(0..80),-1 to STOP,-2 to RESTART,-3 to START NEW BOARD: ");
if(scanf("%d", &index)==1) //scanf is successful scanning a number(input is a number)
{
if(index >= -3 && index <= 80) // if input is in range
break; //break out of while loop
printf("Number must be in range of -3 to 80\n"); //input is a number,but not in range
}
else //input is not a number
{
scanf("%*s"); //Clear invalid input
//printf("Invalid input\n");
fprintf(stderr, "Invalid input\n"); //printf also works but errors are meant to be in the stderr
}
}
return index;
}

Resources