Why is this loop infinitely repeating? - c

The purpose of this program is to count the digits in an alphanumeric input. However, I used a loop to not execute the program unless the input is alphanumeric.
This is the code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
int main(){
int input,isanum,digitcount;
printf("\nEnter a number: ");
scanf("%d",&input);
isanum=isalnum(input);
while(isanum==0){
printf("\nIncorrect input. Try again: ");
scanf("%d",&input);
isanum=isalnum(input);
}
digitcount=0;
while(input!=0){
input=input/10;
digitcount++;
}
printf("\nNumber of digits = %d",digitcount);
return 0;
}
The problem is with the loop. It keeps looping infinitely and ignores the scanf statement and I don't know why. Am I using isalnum() incorrectly here?

You need to check the return value of scanf().
isalnum() takes a character, but you are passing an int. '1' is not the same as 1 in C.
You probably should consume an entire line each time, e.g. with fgets(), and then check if it fits your desired input format, e.g. with sscanf().
As it stands, you never consume anything, you just keep trying to read a number but there isn't one there so it fails every time. Failing to check the return value of scanf() is a contributing factor to your not noticing this.

Look at how isalnum() is defined: it expects a char *. You, however, give it an int *. The data is stored completely different there.
Besides, if you are reading in an int, you know beforehand that it will be alphanumeric, right?

Related

scanf() is not working for getting a sentence

I am learning the language C by myself and with the help of internet.
I came across an exercise, and I was able to read in everything with integers and double, but allowing the user to type in a full sentence and store it in a variable has given me hard time. Can someone explain how I can get a sentence from the user, and store it in a variable. I have tried many things, such as [%^\n] with scanf, and also fget but I am having some trouble. For some reason, it is not working.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int i = 4;
double d = 4.0;
char s[] = "Orange ";
// Declare second integer, double, and String variables.
int secondInt;
double justDouble;
char variable[500];
// Read and save an integer, double, and String to your variables.
scanf("%d", &secondInt);
scanf("%lf", &justDouble);
scanf("%[^ \n]", variable);
// Print the sum of both integer variables on a new line.
printf("%i\n ", i + secondInt);
// Print the sum of the double variables on a new line.
printf("%.1lf\n ", d + justDouble);
// Concatenate and print the String variables on a new line
printf("%s ", s);
printf("%s ", variable);
// The 's' variable above should be printed first.
return 0;
}
This should do the trick by using fgets() in general
#include <stdlib.h>
#include <stdio.h>
int main()
{
// variable to store the message
char msg[100];
// prompting the user to enter the message
printf("Pls enter a msg: ");
// using fgets() to retrieve a whole sentence from the user
fgets(msg, 100, stdin);
// printing the message to stdout
printf("%s", msg);
}
You can learn more about fgets here:
https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm
Let me know if anything is not clear so I can improve my answer
To work with scanf, you need to make sure that everything entered gets read.
In your example, you first expect an integer, and then a double. What does the user type to 'finish' entering the integer? Probably a <RET> (or a blank) - and now you need to scanf these too! Or they will 'clog' the input stream.
For example, your second scanf could be scanf(" %lf"... - note the blank before the % sign, it will read (and discard) any number of whitespace (which is <RET>, <TAB>, <space>).
scanf is very powerful, but needs a lot of detail understanding to be used correctly. Most people don't get it, and therefore claim "it's old and bad and shouldn't be used".
In professional software, it is generally avoided; not because it's not capable, but because the chance is too high that is used wrong, or that it is encountered by a developer that changes it and messes it up.

Infinite loop, program ignoring lines

I need a little help im sort of new to C programming. I'm having some trouble, for some reason the program won't read the line that im trying to take choice as input from the user which is causing me to have infinite loop neither the menu is printing.
Also stuff like this happen with me a lot of the time like when I copy my friends' code how it is it dosent run any loops even my teacher doesn't know why so if you can help in this too please do .
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main (){
int choice ,score=0;
char name [30];
puts("Welcome to our game , Have fun !\n ");
puts("Enter your name");
scanf("%c",name);
printf("1-Start new game\t2-show recorde\n3-Help \t4-Show score\n5-Reset score \t6-Quit game");
scanf("%d",choice);
while(choice!=6){
switch(choice){
case 1 :
break;
case 2 :
break;
case 3 :
break;
case 4 :
break;
default :
puts("\n invalid input ");
break;
}//end switch
}//end while loop
}//end main
Your usage of scanfis wrong.
scanf("%c",name);
Format specifier %c is not suitable to read a string. It only reads 1 single character.
The other members of name array will be untouched and as local variables are not initialized to 0, that is not a valid nul-terminated string.
As soon as you try to print name or perform any string operations with it, this will result in undefined behaviour.
As a result, whatever you type after first character, stays in input buffer and is fetched during next read attempt.
To fix this, use format specifier %s.
When you now try to read the choice as an integer
scanf("%d",choice);
the input buffer contains remaining letters and also \n from first call, which does not match any number.
After the call choice is not modified and still contains its indetermined content (You don't initialize it)
You should always check return value of scanf to see how many parameters were read. It would show you that it didn't find any value.
Besides that, you also provide invalid parameter. You must provide the address of an integer. This is undefined behaviour.
This is the reason why you always enable warnings in your compiler. It should warn you about this error.
To fix this, use
int ret = scanf(" %d", &choice);
if (ret != 1)
// error handling, try again, etc.
Note the space in the format string to skip whitespace including \n.
Finally, you enter your loop with a "random" value in choice and never try to read again. How would you expect to leave the loop without this?
If your teacher really doesn't know why, the missing indentation might be a reason.

How to fix infinite loops when user enters wrong data type in scanf()?

C beginner here. For the program below, whenever the user inputs a character or a string it enters an infinite loop. How would you fix this while still using scanf? And what would be the better methods of writing this program rather than using scanf? Thanks to those who will answer.
#include <stdio.h>
#include <ctype.h>
int main() {
int rounds = 5;
do {
printf("Preferred number of rounds per game. ENTER NUMBERS ONLY: ");
scanf("%d", &rounds);
} while(isdigit(rounds) == 0);
return 0;
}
Using 'scanf' require the input to be formatted. Scanf has very limited ability to handle bad input. The common solution will be to use fgets/sscanf, following the structure below:
char buff[256] ;
int rounds = 0 ;
while ( fgets(buff, sizeof(buff), stdin) ) {
if ( sscanf(buff, "%d", &rounds) == 1 ) {
// additional verification here
break ;
} ;
} ;
// Use rounds here ...
The fgets/sscanf will allow recovery from parsing error - the bad input line will be ignored. Depending on requirement, this might be accepted solution.
I'd say there are just two "fixes".
Retain the scanf call(s), warts and all. Carefully refrain from typing non-digits when scanf is expecting digits.
Abandon scanf and use something else. We've just been discussing this tactic over at this new question.
Once you're using scanf, it's always tempting to try to "fix" it, so there's potentially a third answer lurking here, explaining how to do better, more user-friendly, more error-tolerant input while still using scanf. In my opinion, however, this is a fool's errand, a waste of time. The easy, obvious fixes for scanf's many deficiencies are themselves imperfect and have further deficiencies. You will probably spend more time trying to fix a scanf-using program than you would have spent rewriting it to not use scanf -- and you'll get overall better results (not to mention a cleaner program) with the non-scanf-using rewrite anyway.
Change
scanf("%d", &rounds);
To
int ret;
if ((ret = scanf(" %d", &rounds)) != 1) { // Skip over white space as well
if (ret == EOF) break;
scanf("%*[^\n\r]"); // Consume the rest of the line
}
If you really like scanf, you can use getch to discard non-numeric input:
int rounds = MIN_INT;
while (scanf("%d", &rounds)) != 1)
if (getc() == EOF) /* discard a rubbish character */
break; // or other error-handling return
// rounds is only valid if we did not break, when its value should be MIN_INT.
// but you might need another indicator
C beginner here as well. Like you, I use scanf, and it can be problematic sometimes.
I've had your same problem and tried to solve it with scanf and basic stuff before finding a better solution.
I've tried different solution from here but I continue to have the same problems again and again, like if I type:
a number followed by a character (e.g. 123a), the result is a valid number (which i don't want); the result is '123'.
a string of numbers and chars that begin with a number (e.g. 1a2b3), the result is still a valid number which is '1'.
a char at the beginning (e.g. a123) can generate infinite loop.
... and so on... I've tried do...while, only while, for... nothing.
The only solution I have found to prompt the user until he/she writes only numbers is the following, but...
NOTE: if the user type a space, the program considers only the part before it, e.g. '12 3', only 12 is considered, 3 doesn't exist... unless you want use an infinite loop like I did so, in this case, you can enter multiple numbers, check them and run your program on them all at once. e.g.: '12 23 34 45' ...
NOTE 2: this is a very basic beginner solution, I am learning, and this is just what I found with what I know. Can't do any better right now and, as I said, I didn't find any other solution that I liked the output.
NOTE 3: I use the counter to sum up all the inputs that are not numbers and store the value if it finds one. If I don't use this solution I'll end up in the case where if the first character is a number but the rest aren't, it's still valid (e.g.: '12w3' is 12, which I don't want)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main (void)
{
while (1) // try also multiple inputs separated by space
{
char str[10]; // should be enough for short strings/numbers (?!)
int strlength, num, counter;
do
{
printf("Enter a number: ");
scanf("%s", str);
strlength = strlen(str);
counter = 0;
for (int i = 0; i < strlength; i++)
{
if (!isdigit(str[i]))
counter++;
}
if (counter != 0)
printf("%s is not a number.\n", str);
} while (counter != 0);
num = atoi(str);
printf("%d is a number. Well done!\n\n", num);
}
}
You can also put it in a function and away from the main().

Reading multiple lines of input with scanf

Writing a program for class, restricted to only scanf method. Program receives can receive any number of lines as input. Trouble with receiving input of multiple lines with scanf.
#include <stdio.h>
int main(){
char s[100];
while(scanf("%[^\n]",s)==1){
printf("%s",s);
}
return 0;
}
Example input:
Here is a line.
Here is another line.
This is the current output:
Here is a line.
I want my output to be identical to my input. Using scanf.
I think what you want is something like this (if you're really limited only to scanf):
#include <stdio.h>
int main(){
char s[100];
while(scanf("%[^\n]%*c",s)==1){
printf("%s\n",s);
}
return 0;
}
The %*c is basically going to suppress the last character of input.
From man scanf
An optional '*' assignment-suppression character:
scanf() reads input as directed by the conversion specification,
but discards the input. No corresponding pointer argument is
required, and this specification is not included in the count of
successful assignments returned by scanf().
[ Edit: removed misleading answer as per Chris Dodd's bashing :) ]
try this code and use tab key as delimeter
#include <stdio.h>
int main(){
char s[100];
scanf("%[^\t]",s);
printf("%s",s);
return 0;
}
I'll give you a hint.
You need to repeat the scanf operation until an "EOF" condition is reached.
The way that's usually done is with the
while (!feof(stdin)) {
}
construct.
Try this piece of code..
It works as desired on a GCC compiler with C99 standards..
#include<stdio.h>
int main()
{
int s[100];
printf("Enter multiple line strings\n");
scanf("%[^\r]s",s);
printf("Enterd String is\n");
printf("%s\n",s);
return 0;
}

A Way to deal with this input?

I'm trying to identify a way in which when data is input like such:
Name Integer
Name Integer
Name Integer
.
Each time the Name and Integer are entered, and a newline is detected, stuff is done with that name and integer, then again, and again, until the '.' is detected.
I've tried getchar() loops, and IF statements to detect '\n' for example, but none seem to work. Any ideas?
What about using scanf()?
scanf("%s %d\n", my_string, &my_int);
http://linux.die.net/man/3/scanf
scanf("%s%d\n", name, &intVar);
if((*name=='.') && (*(name+1)=='\0')){
return 0;
}
this should be suffice
How about:
#include <string.h>
#include <stdio.h>
int main()
{
char input[30];
gets(input);
while(strcmp(input, ".") != 0)
{
// do stuff
gets(input);
}
return 0;
}
Don't use scanf directly. It's surprisingly hard to use. It's better to read an entire line of input (for example, with fgets) and to then parse it (possibly with sscanf).

Resources