isdigit() and system("cls") produce infinite loop - c

I was at first having trouble with a scanf() function being skipped, but I fixed that by adding in a space before %c in the scanf() function.
When trying to ask for input from the user as to whether the screen should be cleared, the scanf(" %c", cClear); conversion specifier gives an infinite loop, it is expecting a character, but responds to input as if not a character.
I believe it may have something to do with my input buffer.
I tried to use fflush(stdin) to no avail, I also used printf("%d", (int) cClear); to see the output, which was zero.
One other problem I have is trying to check user input for a digit.
I use:
if (isdigit(iSelection) == 0) {
printf("\nPlease select a valid numerical value.\n");
continue;
to check user input and restart the while loop, but anytime a character is entered and not an integer, I get an infinite loop.
My goal is to give the user the option to clear the screen after each calculation, and to also check input for being a digit.
Any help is appreciated.
//excluding code prior to main() and function definitions
int main(void) {
int iSelection = -1;
double foperand1 = 0, foperand2 = 0;
int ioperand1 = 0, ioperand2 = 0;
char cClear = '\0';
while (iSelection) {
printf("\n\nTHE CALCULATOR\n");
printf("\nCalculator menu:\n");
printf("\n1\tAddition");
printf("\n2\tSubtraction");
printf("\n3\tMultiplication");
printf("\n4\tDivision");
printf("\n5\tModulus (Integers only)");
printf("\n6\tTest if Prime (Integers only)");
printf("\n7\tFactorial (Integers only)");
printf("\n8\tPower");
printf("\n9\tSquare Root");
printf("\n0\tExit\n");
printf("\nPlease enter your selection: ");
scanf("%d", &iSelection);
//here we check for if input was a digit
if (isdigit(iSelection) == 0) {
printf("\nPlease select a valid numerical value.\n");
continue;
switch(iSelection) {
case 0:
break;
case 1:
printf("\nEnter the two numbers to add seperated by a space: ");
scanf("%lf %lf", &foperand1, &foperand2);
printf("\n%.5lf + %.5lf = %.5lf\n", foperand1, foperand2, addNumbers(foperand1, foperand2));
break;
}
//here we ask the user if they want to clear the screen
fflush(stdin)
if (iSelection != 0) {
printf("\nDo you want to clear the screen? ('y' or 'n'): ");
scanf("%c", cClear);
//printf("%d", (int) cClear); //used this to help debug
//scanf("%d", iSelection);
if (cClear == 'y')
system("cls");
}
}
printf("\nExiting\n");
return 0;
}
one error I get is "system" is declared implicitely. Could it possibly be the windows operating system not recognizing the pre defined function call?

Thanks to the people who commented to help me figure this out.
I had forgotten to add the (&) to the scanf() function call for the system"cls" function call, as well as didn't include the correct library (stdlib.h).
I was also able to make the program stop skipping the scanf() function by adding a space to the " %c" conversion specifier.
scanf Getting Skipped
I was able to make the isdigit() function work by changing the variable 'iSelection' to a character, but then I also had to change my case values to characters, not integers.

Related

Validate integer against chars

I'm trying to make a program where the user inputs value to an array. What is actually required is that the program should validate against a char character. So if the user inputs a random char such as 'n' the program should tell him "You introduced a char, please input an integer: ".
How is that possible to make that without using a char variable?
for (i = 1; i <= size; i++) {
printf("Introduce the value #%d of the list: ", i);
scanf("%d", &list[i]);
if () { // I'm blocked right in this line of code.
printf("What you tried to introduce is a char, please input an integer: ");
scanf("%d", &list[i]);
}
Thanks in advance.
As #MFisherKDX says, check the return value of scanf. From the scanf man page:
These functions return the number of input items successfully matched
and assigned, which can be fewer than provided for, or even zero in
the event of an early matching failure.
The value EOF is returned if the end of input is reached before either
the first successful conversion or a matching failure occurs. EOF is
also returned if a read error occurs, in which case the error
indicator for the stream (see ferror(3)) is set, and errno is set
indicate the error.
So capturing the return value of scanf in an int variable and then comparing that variable to 1 (in your case, because you are only attempting to read 1 item) should tell you if scanf successfully read an integer value.
However, there is a nasty pitfall when using scanf that you should be aware of. If you do type n at the prompt, scanf will fail and return 0, but it will also not consume the input you typed. Which means that the next time you call scanf, it will read the same input (the n character you typed), and fail again. And it will keep doing so no matter how many times you call scanf. It always amazes me that computer science educators continue to teach scanf to students, given not only this potential pitfall, but several other pitfalls as well. I wish I had a nickel for every hour that some CS student somewhere has spent struggling to get scanf to behave the way their intuition tells them it should. I'd be retired on my own private island by now. But I digress.
One way around this particular pitfall is to check if scanf failed, and if so, to purposely consume and discard all input from stdin up to and including the next newline character or EOF, whichever comes first.
First let's look at some unfixed code that causes an infinite loop if you enter a non-integer as input:
// Typing the letter 'n' and hitting <Enter> here causes an infinite loop:
int num, status;
while (1) {
printf("Enter a number: ");
status = scanf("%d", &num);
if (status == 1)
printf("OK\n");
else
printf("Invalid number\n");
}
The above code will (after you type n and hit <Enter>), will enter an infinite loop, and just start spewing "Invalid number" over and over. Again, this is because the n you entered never gets cleared out of the input buffer.
There are a few possible ways to get around this problem, but the consensus seems to be that the most portable and reliable way to do so is as follows:
// Fixed. No more infinite loop.
int num, status;
while (1) {
printf("Enter a number: ");
status = scanf("%d", &num);
if (status == 1)
printf("OK\n");
else {
printf("Invalid number\n");
// Consume the bad input, so it doesn't keep getting re-read by scanf
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) ;
if (ch == EOF) break;
}
}
The function scanf() will returns the number of elements read, so in this case it will return 1 every time it reads an int and 0 when it reads a char, so you just need to verify that return value.
Keep in mind that after reading a character it will remain in the buffer so if you use the scanf() command again it will read the character again and repeat the error. To avoid that you need to consume the character with while(getchar() != '\n');
With that in mind I modified your code so that it works properly printing an error message if a character is introduced and asking for a new int.
for (int i = 1; i <= size; i++) {
printf("Introduce the value #%d of the list: ", i);
while (!scanf("%d", &list[i])) { //verifies the return of scanf
while(getchar() != '\n'); //consumes the character in case of error
printf("What you tried to introduce is a char\n");
printf("please introduce the value #%d of the list: ", i);
}
}

How to enter a letter to quit a program in C

I am new to C programming. I have been writing this code to add numbers and I just need help with this one thing. When I type the letter 'q', the program should quit and give me the sum. How am I supposed to do that? It is currently the number 0 to close the program.
#include <stdio.h>
int main()
{
printf("Sum Calculator\n");
printf("==============\n");
printf("Enter the numbers you would like to calculate the sum of.\n");
printf("When done, type '0' to output the results and quit.\n");
float sum,num;
do
{
printf("Enter a number:");
scanf("%f",&num);
sum+=num;
}
while (num!=0);
printf("The sum of the numbers is %.6f\n",sum);
return 0;
}
One approach would be to change your scanf line to:
if ( 1 != scanf("%f",&num) )
break;
This will exit the loop if they enter anything which is not recognizable as a number.
Whether or not you take this approach, it is still a good idea to check the return value of scanf and take appropriate action if failed. As you have it now, if they enter some text instead of a number then your program goes into an infinite loop since the scanf continually fails without consuming input.
It's actually not as straightforward as you'd think it would be. One approach is to check the value returned by scanf, which returns the number of arguments correctly read, and if the number wasn't successfully read, try another scanf to look for the quit character:
bool quit = false;
do
{
printf("Enter a number:");
int numArgsRead = scanf("%f",&num);
if(numArgsRead == 1)
{
sum+=num;
}
else // scan for number failed
{
char c;
scanf("%c",&c);
if(c == 'q') quit = true;
}
}
while (!quit);
If you want your program to ignore other inputs (like another letter wouldn't quit) it gets more complicated.
The first solution would be to read the input as a character string, compare it to your character and then convert it to a number later. However, it has many issues such as buffer overflows and the like. So I'm not recommending it.
There is however a better solution for this:
char quit;
do
{
printf("Enter a number:");
quit=getchar();
ungetc(quit, stdin);
if(scanf("%f", &num))
sum+=num;
}
while (quit!='q')
ungetc pushes back the character on the input so it allows you to "peek" at the console input and check for a specific value.
You can replace it with a different character but in this case it is probably the easiest solution that fits exactly what you asked. It won't try to add numbers when the input is incorrect and will quit only with q.
#Shura
scan the user input as a string.
check string[0] for the exit condition. q in your case
If exit condition is met, break
If exit condition is not met, use atof() to convert the string to double
atof() reference http://www.cplusplus.com/reference/cstdlib/atof/

do-while loop "enter more (y/n)" - character issue

So I'm working on basic C skills, and I want to design a code which enters as many numbers as the user wants. Then, it should display the count of positive,negative & zero integers entered.
I've searched Google & StackOverflow. The code seems fine according to those programs.
It compiles & runs. But whenever I input anything after the prompt "enter more? y/n", it returns to the code..
Please have a look at the code below:
#include<stdio.h>
int main()
{
int no,count_neg=0,count_pos=0,count_zero=0;
char ch='y';
clrscr();
do
{
puts("Enter number");
scanf("%d",&no);
if (no>0)
count_pos++;
else if (no<0)
count_neg++;
else
count_zero++;
puts("want more? - y/n ");
scanf("%c",&ch);
}
while (ch=='y');
if (ch=='n')
{
printf("No of positives = %d",count_pos);
printf("No of negatives = %d",count_neg);
printf("No of zeros = %d",count_zero);
}
getch();
return 0;
}
The problem is with "scanf("%c", &ch);"
What happens actually is :
Suppose you enter 'y' as a choice and hit 'enter'(return), the return is a character and
its character value is 10(since its a new line character), thus the scanf takes the 'return'
as its input and continues.
Solution :
1. use getchar() before scanf()
// your code
getchar();
scanf();
//your code
getchar() takes the return value as its input, thus you are left with your actual value.
add '\n' to scnaf()
// code
scanf("\n%c", &ch);
//code
when scanf() encounters the '\n' character it skips it (google about scanf, to know how
and why ), thus stores the intended value inside 'ch'.
A "better" form for:
int main()
is:
int main(void)
clrscr is not standard C.
You ought to check the return-value of any function which might indicate "interesting status," such as a failure condition, and from which you can gracefully deal with the situation. In this case, scanf is such a function.
I believe that your first do ... while condition will become false because it will pick up the newline character following your first scanf call. You might want to read about getchar or getc, instead of using scanf for the task of checking whether or not to run the loop again. You can "eat" unwanted characters, including a newline.
Here, I have corrected the problem. The problem was this that the "enter" you press after each number is a character and is takenup by the scanf() as it is there to scan some characters. So I have added a getchar(); before the scanf();so the "enter" is taken up by getchar(); and scanf() is now free to take your input.
#include<stdio.h>
int main()
{
int no,count_neg=0,count_pos=0,count_zero=0;
char ch='y';
clrscr();
do
{
puts("Enter number");
scanf("%d",&no);
if(no>0)
count_pos++;
else if(no<0)
count_neg++;
else
count_zero++;
puts("want more? - y/n ");
getchar();//<---- add this here
scanf("%c",&ch);
}
while(ch=='y');
if(ch=='n')
{
printf("No of positives = %d",count_pos);
printf("No of negatives = %d",count_neg);
printf("No of zeros = %d",count_zero);
}
getch();
return 0;
}
To fix the input is to use a C String like this scanf("%s",...);
This might break if you input more than one character because scanf will keep reading until the user hits enter, and your ch variable is only enough space for one character.
I run your code in Online compiler. I am not sure about other compiler.
I slightly changed your code. i.e., first i read char then int. If i do not change the order, char variable holds int variable value. This is the reason ( ch variable holds values of no variable).
#include<stdio.h>
int main()
{
int no,count_neg=0,count_pos=0,count_zero=0;
char ch='y';
do
{
puts("Enter number");
scanf("%c",&ch);
scanf("%d",&no);
if(no>0)
count_pos++;
else if(no<0)
count_neg++;
else
count_zero++;
puts("want more? - y/n ");
}
while(ch=='y');
if(ch=='n')
{
printf("No of positives = %d",count_pos);
printf("No of negatives = %d",count_neg);
printf("No of zeros = %d",count_zero);
}
return 0;
}
EDIT:
whenever integer and char are read through keyboard. it stores int value and enter key value. so this is the reason.
You have to add
scanf("%d",&no);
you code
......
.....
fflush(stdin);
scanf("%c",&ch);
use:
ch = getche();
instead of:
scanf("%c", &ch);

how to read enter input on c

This function will be called by the menu.
void exponentiation()
{
int i, result = 0, first, second;
printf("\n%s\n%s\n\n%s",
"1) Exponentiation",
"------------------",
"Enter 1st integer: ");
scanf("%d", &first);
printf("Enter 2nd integer: ");
scanf("%d", &second);
printf("%d raised to %d equals %d\n", first, second, result);
main();
}
From this function I need to read the user input, if the user input is "enter" without any integer, it should be going back to the menu which is calling the main().
I already tried to get the input.
For example:
if(first == '\n')
{main();}
or
if(first == 10) /**which is 10 is ASCII code for enter**/
{main()}
Both ways it didn't work at all, any suggestions?
both ways it didn't work at all, any suggestion
The function scanf returns the number of items it successfully scanned. You should check its return and go back if it doesn't matches your expectations.
Also you should know %d ignores whitespace. So if the user hits return without entering an integer, scanf simply skips over it and waits for something else.
If you insist on not ignoring whitespace this way, you should avoid scanf and use other input methods such as fgets. Get input from the user line by line and use sscanf, strtoul and strtok to make sense of it.

Why does my program loop without receiving any new input?

I am trying to make is so that my program will start over once the answer is given. It just won't function again once I run it once. I want to make it functional to where the user doesn't have to start the program up again. Thanks!
#include <stdio.h>
#include <math.h>
int main()
{
float firstnum, secondnum, answer;
char function;
printf("\nHello and welcome to my calculator!\n"); //Intro
start: //Area to loop to when program completes
printf("\nPlease input the function you would like to use. These include +, -, *, /.\n"); //Asking for function input
scanf("%c", &function); //Receiving Function Input
printf("\nNow please input the two variables.\n"); //Asking for variables
scanf("%f", &firstnum);
scanf("%f", &secondnum); //Receiving Input for Variables
if (function == '+') //Doing calculation
{
answer = firstnum+secondnum;
}
else if (function == '-')
{
answer = firstnum-secondnum;
}
else if (function == '*')
{
answer = firstnum*secondnum;
}
else if (function == '/')
{
answer = firstnum/secondnum;
}
else
{
printf("Sorry that was an incorrect function. The correct inputs are +, -, *, /."); //If they don't follow the directions
}
printf("Your answer is %f \n", answer); //Answer
goto start; //Loop
return 0;
}
It's the [enter] key. Your first scanf is reading the enter key you pressed to terminate the previous iteration.
So you need to add another scanf("%c", &function); or getchar(); just before the goto to eat the newline.
When reading in numbers, scanf will eat any initial whitespace; but when reading characters, it won't. It gives you the very next byte in the stream.
A better way, perhaps, would be to tell `scanf` where to expect all the newlines. This way you don't need that *weird* mystery line that doesn't appear to do anything but isn't commented (!); because that's gonna cause problems when you play with this code again months from now.
//scanf("%c\n", &function); /* read a character followed by newline DOESN'T WORK */
...
//scanf("%f\n", &secondnum); /* read a number followed by newline DOESN'T WORK */
This way, trailing newlines are consumed. Which is, I think, the more intuitive behavior (from the User side).
Nope. Doesn't work. Wish it did, cause I'd look less foolish.
I'm not upset by the goto. It's nice to see an old friend. This is an appropriate use of it if ever there was one. It is exactly equivalent to the while form. So you should certainly be aware that most people will prefer to see while(1) because it tells you more about what's going on than label:. But for an infinite loop in a function smaller than a screen, why not? Have fun. No baby seals will be harmed. :)
This is why you use loops. (And try not to use goto for this).
#include <stdio.h>
#include <math.h>
int main() {
float firstnum, secondnum, answer;
char function, buffer[2];
while(1) {
printf("\nHello and welcome to my calculator!\n");
printf("\nPlease input the function you would like to use. These include +, -, *, /.\n");
scanf("%s", &buffer);
function = buffer[0];
printf("\nNow please input the two variables.\n");
scanf("%f", &firstnum);
scanf("%f", &secondnum);
if (function == '+') answer = firstnum+secondnum;
else if (function == '-') answer = firstnum-secondnum;
else if (function == '*') answer = firstnum*secondnum;
else if (function == '/') answer = firstnum/secondnum;
else printf("Sorry that was an incorrect function. The correct inputs are +, -, *, /.");
printf("Your answer is %f \n", answer);
}
return 0;
}
This should go in an infinite loop, so use an input from the user to break; the loop to exit the program
Note : I have replaced the scanf %c with %s indicating an input of a string & used a buffer.
scanf("%s",&buffer); function = buffer[0];
(Updated as per discussion in comments)
One "best practise" regarding scanf is to check it's return value. In regards to the return value of scanf, I suggest reading this scanf manual carefully and answering the following questions:
int x = scanf("%d", &foo); What do you suppose x will be if I enter "fubar\n" as input?
Where do you suppose the 'f' from "fubar\n" will go?
If it remains in stdin, would you expect a second scanf("%d", &foo); to be successful?
int x = scanf("%d", &foo); What do you suppose x will be if I run this code on Windows and press CTRL+Z to send EOF to stdin?
Would it be safe to use foo if x is less than 1? Why not?
int x = scanf("%d %d", &foo, &bar); What would you expect x to be if I enter "123 456\n" as input?
Do you suppose the '\n' will still be on stdin? What value would char_variable hold following scanf("%c", &char_variable);?
EOF can be sent through stdin in Windows by CTRL+Z, and in Linux and friends by CTRL+D, in addition to using pipes and redirection to redirect input from other programs and files.
By using code like int function; for (function = getchar(); function >= 0 && isspace(function); function = getchar()); assert(function >= 0); or char function; assert(scanf("%*[ \n]%c", &function) == 1); you can discard leading whitespace before assigning to function.

Resources