How do I stop making this C code loop? [duplicate] - c

This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 6 years ago.
I have written some C code where you can pick from an answer by inputting a 1 or 2, and if you input a higher number it will bring you back to pick another number just fine. However, if I try to input something that's not a value or a number, like a string or character, the error message at the bottom will repeat infinitely. How can I make my code act the same as if you input a higher number than 1 or 2 when you input any other character? Here the code I use abstracted:
#include <stdio.h>
int a;
int main(){
b:scanf("%d", &a);
if(a==1)
{
a=0;
}
if(a==2)
{
a=0;
}
else
{
a=0;
printf("\nERROR: Please try again.\n\n");
goto b;
}
}
EDIT: Apparently the return value is still stuck in scanf() when it returns to it. How can I clear out scanf() of its return value?

Don't use gotos at all. Instead use while loops:
#include <stdio.h>
int main(void) {
int a, end = 1; //end determines if the loop should end
do { //a do-while loop - it's the same as a while loop, except it runs atleast once
scanf("%d", &a);
switch (a) { //switches the value of a
case 1:
case 2: printf("You entered %d\n", a);
end = 0; //sets end to 0, which will end the loop(see below)
break;
default: printf("\nERROR: Please try again.\n\n");
}
} while (end); //every non-zero value is true, so when I set end to 0, it will end the loop
return 0; //don't forget the return 0: it shows you that your program ran without error
}
So I wrote it that it ends as soon as you type a valid input. You also don't need to set a to zero, as you read it in again every time you run the loop.
EDIT: if you want to check for invalid input such as 5x, you can use the following:
int check, var, error;
char ch;
do {
error = 0;
check = scanf("%d%c", &var, &ch);
if (check != 2 || ch != '\n') {
printf("Wrong input. Try again -> ");
error = 1;
fflush(stdin);
}
} while (error);

#include <stdio.h>
int a;
int isNumeric(const char *str)
{
while(*str != '\0')
{
if(*str < '0' || *str > '9')
return 0;
str++;
}
return 1;
}
int main(){
char inputStr[10];
while(1){
scanf("%9s",inputStr);
if(!isNumeric(inputStr)){
a=0;
printf("\nERROR Not a number: Please try again.\n\n");
}else {
a = atoi(inputStr);
if(a==1){
a = 0;
}else if(a == 2){
a == 0;
}else{
a=0;
printf("\nERROR : Please try again.\n\n");
}
}`enter code here`
}
}
Have not tested. But I guess you will get a good idea. check strtol function. That is also useful.

Something like...
Note: Obviously 999 is an arbitrary value. Just chosen to give you an example.
#include <stdio.h>
int main(){
int a = 1;
while (a != 999){
scanf("%d", &a);
if(a==1)
{
a=0;
}
if(a==2)
{
a=0;
}
else if (a != 999)
{
a=0;
printf("\nERROR: Please try again.\n\n");
}
} // while()
} // main()

Related

Simple Calculator in C: How to reject any input other than numbers and why does the error message print infinitely?

So I made a simple calculator that takes two numbers and a basic operation (+,-,*,/) and then prints out the result, and also an error message is printed when anything other than those four operators is entered. But I have these questions that I couldn't quite find the answers for:
1-How do I make a while loop that makes the program print an Error message and asks the user to enter the two numbers and the operation again when anything other than a number is entered into either %d's in the scanf?
2- Why does the program print out the error message infinitely when anything other than numbers is entered into either %d's in the scanf or when I try to enter each variable seperately (For example: 10 Enter / Enter 5 Enter, the program starts printing out the error message infinitely after I press enter after the "/").
Here is my code:
#include <math.h>
#include <stdio.h>
int main()
{
double n1=0.0,n2=0.0,result=0.0;
char operation=' ';
scanf("%lf%c%lf", &n1,&operation,&n2);
while(operation!='+' && operation!='-' && operation!='*' && operation!='/')
{
printf("Error! Invalid Operator.\n");
scanf("%lf%c%lf", &n1,&operation,&n2);
}
if(operation=='+')
{
result=n1+n2;
printf("%f",result);
}
else if(operation=='-')
{
result=n1-n2;
printf("%f",result);
}
else if(operation=='*')
{
result=n1*n2;
printf("%f",result);
}
if(operation=='/')
{
result=n1/n2;
printf("%f",result);
}
return 0;
}
I hope this is what you're looking for. You don't need math.h for this and I also replaced the ifs with switch statement.
#include <stdio.h>
int main()
{
double n1=0.0,n2=0.0,result=0.0;
char operation=' ';
/* char buf[10]; */
int ch;
while(1){
while(scanf("%lf%c%lf",&n1,&operation,&n2)!=3){
/* scanf("%[^\n]",buf); */
while( (ch = getchar()) != EOF && ch != '\n' ){;} //Use this as user3629249 suggested as buf might overflow
printf("Error.\n");
}
switch(operation){
case '+':
result=n1+n2;
printf("%lf",result);
return 0;
case '-':
result=n1-n2;
printf("%lf",result);
return 0;
case '*':
result=n1*n2;
printf("%lf",result);
return 0;
case '/':
result=n1/n2;
printf("%lf",result);
return 0;
default:
printf("Error! Invalid Operator.\n");
break;
}
}
return 0;
}

Scanf for integer not working as expected when I input float or string

I'm new to C language and I'm writing this code for fun. In here I take username first and then I'm taking a guess number from the user. And I wrote a function to check whether number is int or not (only need integer inputs.)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
char userName[30];
int userGuess, check;
int checkGuess(int, int);
printf("Enter your name - ");
scanf("%s",&userName);
int i = 0;
while(++i<=10)
{
printf("Enter Your Guess: ");
check = scanf("%d",&userGuess);
checkGuess(userGuess, check);
}
return 0;
}
int checkGuess(int userGuess, int check)
{
if(check == 1)
{
printf("yes int, %d.\n",userGuess);
} else
{
printf("Not int\n");
}
}
However when I put integers it works fine, but when I put a string or a float it just runs the loop till end.
You need to flush stdin when scanf fails
while (i < 10)
{
printf("Enter Your Guess: ");
check = scanf("%d", &userGuess);
if (check != 1)
{
// Flush stdin
while ((check = fgetc(stdin)) != '\n' && check != EOF);
}
else
{
// Increment i only when scanf has success
i++;
}
}
Take a look to Why to use fgets() over scanf() in C?

How can I monitor user input with getchar

I need to get a user input and check if it is a valid input.
The input must:
Start with space(may be multiple) or a number.
(Assuming condition one satisfied) After the number there may be any kind of characters as long as I manage to extract the number
Clarification for number valid values:
Can be multiple digit
Can't be negative number
Can't contain decimal point
Can't be scientific notation
Can't be hexadecimal
So I wrote this basic code which simply gets the input but I have no clue on where to start on applying these conditions
printf("Enter size of input:\n");
int c;
while((c=getchar())!='\n' && c!=EOF){
printf("%c",c);
}
For example :
Input - 4##2311413sadokalda ; expected output - 4
Input - !4a ; expected output - Invalid Size
You can have state machine as below.
printf("Enter size of input:\n");
int c;
int state = 0; //0 = space, 1 = number, 2 = number read
int number = 0;
while((c=getchar())!='\n' && c!=EOF){
switch(state)
{
case 0:
if (isdigit(c))
state = 1;
else if (c == ' ')
break;
else
//error
break;
case 1:
if (isdigit(c))
{
number = number*10 + (c-'0');
break;
}
else {
state = 2;
}
case 2:
printf ("%d\n",number);
}
}
You probably want something like this:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char* argv[]) {
printf("Enter size of input:\n");
char input[100];
fgets(input, sizeof input, stdin);
if (!isdigit(input[0]))
{
printf("Invalid Size\n");
}
else
{
int inputsize = strtol(input, NULL, 10);
printf("%d\n", inputsize);
}
}
Based on the problem statement you have given, i think this should give you your desired output
EDITED (After a few clarifications):
int main()
{
int c;
int i=0;
while((c=getchar())!='\n' && c!=EOF)
{
if(isdigit(c) || (char)c==' ') //isdigit() function check if given variable is a digit
{ printf("%c",c);
i+=1;
}
else
{
break;
}
}
if(i==0)
{ printf("Invalid size"); }
}

Check vowels occurence in a string

This is the problem I'm trying to solve:
Input:
First line contains N, the size of the string.
Second line contains the letters (only lowercase).
Output:
Print YES if all vowels are found in the string, NO otherwise.
Constraints:
The size of the string will not be greater than 10,000. 1 ≤ N ≤ 10000
The following code I wrote is always showing NO.
#include <stdio.h>
#include<conio.h>
int main()
{
int a,b,c=0,d=0,e=0,f=0,g=0,i;
char string[10000];
scanf("%d",&a);
scanf("%s",string);
for(i=0;i<a;a++)
{
if(string[i]==('a'))
c=1;
if(string[i]==('e'))
d=1;
if(string[i]==('i'))
e=1;
if(string[i]==('o'))
f=1;
if(string[i]==('u'))
g=1;
}
if((c==1)&&(d==1)&&(e==1)&&(f==1)&&(g==1))
printf("YES");
else
printf("NO");
return 0;
getch ();
}
Here is an infinite loop that causes a problem:
for(i=0;i<a;a++)
You should increment i, instead of a (length of a string). If you fix this one char in loop statement, the program will run well at all. Anyway, I changed your code a bit to be more readable. Take a look if you want, just for your information, sir:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int len, a=0, e=0, i=0, o=0, u=0, it;
char string[10000];
scanf("%d", &len);
scanf("%s", string);
for(it=0;it<len;it++)
{
if(string[it]=='a') a = 1;
else if(string[it]=='e') e = 1;
else if(string[it]=='i') i = 1;
else if(string[it]=='o') o = 1;
else if(string[it]=='u') u = 1;
}
if(a && e && i && o && u) printf("YES\n");
else printf("NO\n");
system("PAUSE");
return 0;
}
I assume you are running your program under Windows, so instead of conio's getch() try to use system("PAUSE") or just even better way to do this (for both Windows for UNIX): getchar()
I've renamed all of your variables, but otherwise left the code the same.
#include <stdio.h>
#include<conio.h>
int main()
{
int foundA = 0, foundE = 0, foundI = 0, foundO = 0, foundU = 0;
int i, length;
char string[10000];
scanf("%d", &length);
scanf("%s", string);
for(i=0; i<length; length++)
{
if(string[i]==('a'))
foundA=1;
else if(string[i]==('e'))
foundE=1;
else if(string[i]==('i'))
foundI=1;
else if(string[i]==('o'))
foundO=1;
else if(string[i]==('u'))
foundU=1;
}
if((foundA==1)&&(foundE==1)&&(foundI==1)&&(foundO==1)&&(foundU==1))
printf("YES");
else
printf("NO");
return 0;
getch ();
}
Looking the the for-loop condition for(i=0; i<length; length++), I think it's pretty clear what's wrong. Instead of incrementing the counter, you're incrementing the length of the string. Eventually, the counter overflows to a negative number, and the loop terminates without ever looking at a character besides the first one. The lesson here is to name your variables properly.
If you want to be picky, then signed integer overflow is undefined behavior, but for most systems, INT_MAX + 1 will be INT_MIN.
This program can be done in more simpler way other as below.
#include <stdio.h>
#include<conio.h>
int main()
{
int i, flag = 0;
char string[10000], *ptr;
char cmp[] = "aeiou";
printf("Please enter string = " );
scanf("%s", string);
i = 0;
while(cmp[i])
{
ptr = string;
while(*ptr)
{
if(cmp[i] == *ptr)
break;
ptr++;
}
if(*ptr != cmp[i++])
{
flag = 1;
break;
}
}
if(flag == 1)
printf("NO");
else
printf("YES");
}
In this program I have used just one flag instead of 5 flags. Always try to write simple code rather then using unnecessary variable and flags.

Logic in detecting int in C

I would appreciate some help with this. I'm trying to create this simple program that repeatedly loops asking for the user to enter in an int. If he enters an int, it exits but if he enters something else or bigger than int (ex.4gs4r33) it will loop again asking to enter an int. This is what I have tried, and it's not working. It says it's an int even if it's not.
#include<stdio.h>
unsigned int findInt();
int main() {
printf("Please input an int.\n");
findInt();
}
unsigned int findInt() {
char input;
long num = 0;
int b = 0;
do {
scanf("%c", &input);
if (isdigit(input)){
num = num*10+input+'0';
b = 1;
}
else if (input == '\n')
b = 1;
else
b = 0;
} while(input != '\n');
if (b == 1)
printf("Great!\n");
else{
printf("Not an int \n");
findInt();
}
return 0;
}
Two possible approaches. One would be to modify your code:
b = 1; // start off with good intentions…
do {
scanf("%c", &input);
if (isdigit(input)){
num = num*10+input -'0'; // *** SUBTRACT '0', don't add it!
}
else if (input != '\n') {
b = 0;
break; // *** break when you find non-digit
}
} while (input != '\n');
Two changes: getting the math right as you compute the integer, and fixing the logic (so you break out of your loop when you find a non digit character)
Second approach:
char buf[100];
char intAsString[100];
fgets(buf, 100, stdin);
sscanf(buf, "%d", num);
sprintf(intAsString, "%d\n", num);;
if(strcmp(buf, intAsString) == 0 ) {
printf("yay - you entered an integer!\n");
}
I'm sure you can figure out how that works.
update a complete code snippet that solves the issue of "loop logic" as well: you call the findInt function once from the top level, and it keeps going until you get the int. Note - in order for this to work properly, I read the entire input at once (rather than one at a time), then pick off the characters one by one using sscanf (and updating the pointer manually). It has a number of advantages - not least of which is that you start with a fresh input every time you call findInt, instead of having the rest of the input buffer that still needs reading (and which was giving rise to "no,no,no,great!" - as you would keep reading the bad input until you got to the newline, and accept that...)
#include<stdio.h>
#include <ctype.h>
unsigned int findInt();
int main() {
findInt();
}
unsigned int findInt() {
char input;
char buf[100];
char *temp;
long num = 0;
int b = 0;
printf("please enter an int:\n");
fgets(buf, 100, stdin);
temp = buf;
do {
sscanf(temp++, "%c", &input);
if (isdigit(input)){
num = num*10+input-'0';
b = 1;
}
else if (input == '\n')
{
b = 1;
break;
}
else {
b = 0;
break;
}
} while(input != '\n');
if (b == 1)
printf("Great! %d is an integer!\n", num);
else{
printf("Not an int \n");
findInt();
}
return 0;
}
In the else branch - i.e. not a digit or a newline - you set b to 0. Now if a digit DOES follow you reset that to 1.
You'll probably want to break or somehow record the permanent failure instead of just continuing.
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>
void findInt(){
int x;
bool ok;
do{
char buff[32], *endp;
long long num;
ok = true;//start true(OK)
printf("Enter a number: ");
fgets(buff, sizeof(buff), stdin);
//strtoll : C99
x=(int)(num=strtoll(buff, &endp, 0));//0: number literal of C. 10 : decimal number.
if(*endp != '\n'){
if(*endp == '\0'){
printf("Too large!\n");//buffer over
while('\n'!=getchar());
} else {
printf("Character that can't be interpreted as a number has been entered.\n");
printf("%s", buff);
printf("%*s^\n", (int)(endp - buff), "");
}
ok = false;
} else if(num > INT_MAX){
printf("Too large!\n");
ok = false;
} else if(num < INT_MIN){
printf("Too small!\n");
ok = false;
}
}while(!ok);
}
,

Resources