scanf resulting in infinite loop [duplicate] - c

This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 9 years ago.
I had this problem before but went around it using other operator. But the same operator can't be used here I think (the getche();). Anyway this works well and good but if I input a letter it goes into an infinite loop.
printf("Enter the number of the passenger you wish to edit.");
scanf("%d", &userchoice);
do
{
if(userchoice <= count || userchoice <= 1)
{
flag = 0;
}
else
{
printf("Please enter a valid input!");
scanf("%d", &userchoice);
flag = 1;
}
} while (flag == 1);

You should see this answer :
https://stackoverflow.com/a/1716066/2263879
The problem is with your scanf.

Yes , it will go into .
Since you are checking for userchoice<=1 , letter ascii value would be compared which will always be false and flag will always be 1
P.S: I am assuming count is pretty small number here , since you have not provided the value of it.

Do you mean userchoice between 1 and count, then the first if is incorrect.
This code works, when you want to test in-between 1 and count.
#include <stdio.h>
#include <ctype.h>
int main(int argc, char *argv[]) {
signed int count = 5;
signed int flag = 1;
signed int userchoice = 0;
printf("Enter the number of the passenger you wish to edit:");
scanf("%d", &userchoice);
do {
if(userchoice <= count && userchoice >= 1) {
flag = 0;
} else {
char c = '0';
if (scanf("%d", &userchoice) == 0) {
printf("Please enter a valid input!\n");
do {
c = getchar();
}
while (!isdigit(c));
ungetc(c, stdin);
}
}
} while (flag == 1);
printf("Done!");
}
Output:
a is not valid, because it is not a digit, 6 is bigger than count. 3 is possible and gets accepted.
Enter the number of the passenger you wish to edit:a
Please enter a valid input!
6
3
Done!

Related

Restrict input to symbols and other numbers (с program)

I have such a program
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main() {
float x, k;
int choose;
_Bool valid;
do {
valid = 1;
printf("\nChoose variant: \n1 - count of nums\n2 - float number\n3 - e:\nYour choose: ");
scanf(" %d", &choose);
while(isdigit(choose) == 0) {
printf("Please, choose number, not letter (number between 1 to 3): ");
fflush(stdin);
scanf(" %d", &choose);
}
while(choose > 3 || choose < 0) {
printf("Please, choose correct option (number between 1 to 3): ");
fflush(stdin);
scanf(" %d", &choose);
}
if(choose == 1 || choose == 2 || choose == 3) valid = 0;
} while (valid);
return 0;
}
I have such a program. I want to get the user to choose: 1, 2 or 3. I'm trying to put a check on characters and also on other numbers. I want the program to loop until I enter the correct one. But it does not work, I have already tried other methods to solve this problem, but it does not work for me. I have an idea that there is no cleaning here, maybe this is so?
I can also set a condition so that scanf is equal to one - this means that a character has been entered. But I want if the user enters "1gf ", for example, then the condition will also work, instead of continuing from 1.
Thank you very much in advance
Rather than checking for a numeric entry the program might scan in a character to test and then convert to an integer as in the following code snippet.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main()
{
float x, k;
int choice;
char choose;
int valid = 1;
do
{
printf("\nChoose variant: \n1 - count of nums\n2 - float number\n3 - e:\nYour choose: ");
scanf(" %c", &choose);
if((choose > '9'))
{
printf("Please, choose number, not letter (number between 1 to 3): ");
}
if((choose < '1' || (choose > '3')))
{
printf("Please, choose correct option (number between 1 to 3): ");
}
if(choose == '1' || choose == '2' || choose == '3') valid = 0;
}
while (valid);
choice = choose - '0';
printf("The choice is %d\n", choice);
return 0;
}
Following are some points to note.
The choose variable is defined as a character in lieu of an integer.
Testing is done over character ranges to determine if the entry is valid for this code.
The choice value is then determined simply by subtracting the integer value of the zero character from the entered character value.
Testing this out at the terminal resulted in the following sample output.
#Dev:~/C_Programs/Console/Choice/bin/Release$ ./Choice
Choose variant:
1 - count of nums
2 - float number
3 - e:
Your choose: e
Please, choose number, not letter (number between 1 to 3): Please, choose correct option (number between 1 to 3):
Choose variant:
1 - count of nums
2 - float number
3 - e:
Your choose: 4
Please, choose correct option (number between 1 to 3):
Choose variant:
1 - count of nums
2 - float number
3 - e:
Your choose: 2
The choice is 2
For sure, there are a multitude of ways the entries could be input and checked. This is just one way. Give it a try and see if it meets the spirit of your project.
You cant do this in standard C you need to use some additional libraries. For example in Linux ncurses.
#include <ncurses.h>
#include <string.h>
char *readstr(char *buff, size_t size, const char *allowed)
{
size_t cpos = 0;
int c;
while ((c = getch()) != ERR && c != '\n' && (cpos + 1) < size)
{
if(strchr(allowed, c)) buff[cpos++] = c;
else addstr("\b \b");
}
buff[cpos] = 0;
return c == ERR ? NULL : buff;
}
int main (void)
{
char number[7];
cbreak();
echo();
initscr();
if(readstr(number, sizeof(number), "0123456789"))
{
printf("you have entered: `%s`\n", number);
}
else
{
printf("ERROR!!!!\n");
}
return 0;
}

scanf() adds character to string

I have this code and it keeps adding what ever the guesses string is to the wordle string when I compare them, resulting in them to never be the same. How can I fix this?
#include <string.h>
int main() {
char wordle[5];
char guesses[5];
int guess = 5;
int value;
printf("Please input a secret 5 letter word:\n");
scanf("%s",wordle);
while (guess != 0){
printf("You have %d tries, please guess the word\n",guess);
scanf("%s",guesses);
value = strcmp(wordle,guesses);
if (value == 0){
printf("you win\n");
break;
}
guess = guess - 1;
}
return 0;
}```
Your program has undefined behavior. You're making two mistakes.
If your user enters 5 characters, it takes 6 characters to store the string. The program would attempt to write a null terminator into wordle[5] which is not a valid index.
Your user could enter any number of letters. You need to make sure they don't overflow your buffer.
#include <stdio.h>
#include <string.h>
int main() {
char wordle[6];
char guesses[6];
int guess = 5;
int value;
int chars_read;
do {
printf("Please input a secret 5 letter word:\n");
chars_read = scanf("%5s%*s\n", wordle);
} while(chars_read != 1 && strlen(wordle) != 5);
while (guess != 0){
do {
printf("You have %d tries, please guess the word\n", guess);
chars_read = scanf("%5s%*s\n", guesses);
} while(chars_read != 1 && strlen(wordle) != 5);
value = strcmp(wordle, guesses);
if (value == 0){
printf("you win\n");
break;
}
guess = guess - 1;
}
return 0;
}
See it in action
scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s
MSC24-C. Do not use deprecated or obsolescent functions
Your strings for wordle and guesses are too short. You need to make room for '\0'. They should be 6 bytes long not 5.
char wordle[6];
char guesses[6];

Scanning character caused problem in devC

So my code does the following:
Ask what's the option
If option is 1: Scan some numbers
If option is 2: Print those numbers
After each option, ask if user wanted to continue choosing (Y/N)
This is my main code
while(yesnocheck==1)
{
printf("What's your option?: ");
scanf("%d",&b);
switch(b){
case 1:
printf("How many numbers?: ");
scanf(" %d",&n);
a=(struct sv*)malloc(n*sizeof(struct sv));
for(int i=0;i<n;i++)
scanf("%d",&((a+i)->num));
break;
case 2:
for(int i=0;i<n;i++)
printf("%d\n",(a+i)->num);
break;
}
yesnocheck==yesnochecker();
}
And this is the yesnochecker function:
int yesnochecker()
{
char yesorno;
printf("Do you want to continue? (Y/N)");
while(scanf("%s",&yesorno))
{
if(yesorno=='Y')
return 1;
if(yesorno='N')
return 0;
printf("*Wrong input. Please reenter (Y/N): ");
}
}
So on dev C++, my code won't run correctly. After it's done option 1, when I enter "Y" then choose option 2, case 2 will display some weird numbers. However it works well on online C compilers.
And then, when I change the char yesorno in yesnochecker() function to char yesorno[2] and treat it as a string, the code does work.
Can someone shed some light?
It is a bad idea to read a char c with scanf("%s", &c);. "%s" requires a buffer to store a string. The only string which fits into a char is an empty string (consisting only of a terminator '\0' – not very useful). Every string with 1 character requires 2 chars of storage – 1 for the character, 1 for the terminator ('\0'). Providing a char for storage is Undefined Behavior.
So, the first hint was to use the proper formatter instead – "%c".
This is better as it removes the Undefined Behavior. However, it doesn't solve another problem as the following sample shows:
#include <stdio.h>
int cont()
{
char c; do {
printf("Continue (y/n): ");
scanf("%c", &c);
printf("Input %c\n", c);
} while (c != 'y' && c != 'n');
return c == 'y';
}
int main()
{
int i = 0;
do {
printf("Loop iteration %d.\n", ++i);
} while (cont());
/* done */
return 0;
}
Output:
Loop iteration 1.
Continue (y/n): y↵
Input 'y'
Loop iteration 2.
Continue (y/n):
Input '
'
Continue (y/n): n↵
Input 'n'
Live Demo on ideone
WTH?
The scanf("%c") consumes one character from input. The other character (inserted for the ENTER key) stays in input buffer until next call of any input function.
Too bad, without ENTER it is hard to confirm input on console.
A possible solution is to read characters until the ENTER key is received (or input fails for any reasons). (And, btw., getc() or fgetc() can be used as well to read a single character.):
#include <stdio.h>
int cont()
{
int c;
do {
int d;
printf("Continue (y/n): ");
if ((c = fgetc(stdin)) < 0) {
fprintf(stderr, "Input failed!\n"); return 0;
}
printf("Input '%c'\n", c);
for (d = c; d != '\n';) {
if ((d = fgetc(stdin)) < 0) {
fprintf(stderr, "Input failed!\n"); return 0;
}
}
} while (c != 'y' && c != 'n');
return c == 'y';
}
int main()
{
int i = 0;
do {
printf("Loop iteration %d.\n", ++i);
} while (cont());
/* done */
return 0;
}
Output:
Loop iteration 1.
Continue (y/n): y↵
Input 'y'
Loop iteration 2.
Continue (y/n): Hello↵
Input 'H'
Continue (y/n): n↵
Input 'n'
Live Demo on ideone
Please, note, that I changed the type for the read character to int. This is because getc()/fgetc() return an int which is capable to store any of the 256 possible char values as well as -1 which is returned in case of failing.
However, it isn't any problem to compare an int with a character constant (e.g. 'y'). In C, the type of character constants is just int (SO: Type of character constant).

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

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()

Check if input is a string (4 characters only) and if not return to input again

My aim is to accept 4-digit numbers, and 4-character strings (string should not contain digits or special characters)
If an invalid input is given the program should not terminate and it must allow the user to enter the details and continue until he wish to terminate.
I am able to find whether the input is a digit.
if(scanf("%d",&input)!=1)
{
printf("enter the number please");
... // I have option to re enter using while and flags
}
else
{
// I continue my work
...
}
To check it is four digits I have tried using the commands
i=0;
num = input;
while(num>0)
{
i = i+1;
num = num/10;
}
if(i==4){
...//I continue
}
else
printf("please enter four digit");
I have no idea of checking the same for characters. (I know how to check its length using strlen())
Please help me with the code in C. (Also help me to reduce/optimize the above logic to check whether the input is a 4-digit number)
I believe you want 2 inputs a number and a string. You can do that as
int number= 0;
char string[10] = { 0 };
do {
printf("please enter four digit");
scanf("%d", &number);
if(number >=1000 && number<= 9999)
break;
} while(1);
do {
printf("please enter four character string");
fgets(string, sizeof(string), stdin);
if(strlen(string) == 4)
break;
} while(1);
To check it is four digit number you can simply put a check whether the number lies between 1000 and 9999. (I am assuming you don't want the number to start with 0.)
strtol can help:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char s[32], *p;
int x;
fgets(s, sizeof(s), stdin);
if ((p = strchr(s, '\n')) != NULL)
*p = '\0';
x = (int)strtol(s, &p, 10);
if ((p - s) == 4) {
printf("%d\n", x);
} else {
printf("Please enter four digit\n");
}
return 0;
}
char input[16];
int ok = 1, k = 0;
if (scanf("%s", input) > 0 && strlen(input) == 4) {
// check if it's a word
for (; k < 4; k++)
if (!isalpha(input[k])) {
// check if it's a number
for (int k = 0; k < 4; k++)
if (!isdigit(input[k]))
ok = 0;
break;
}
}
else ok = 0;
if (!ok)
printf("invalid input, please enter a 4-digit number or 4-letter word");
else {
printf("valid input");
...
}
You can use gets()1 fgets() to get the whole line and check line length. If the first character is between '0' and '9' then check the remaining if they are 3 numbers too. If the first character is a valid character in string then check the 3 remaining chars if it's also valid in string.
1See Why is the gets function so dangerous that it should not be used?

Resources