Why isn't the Isdigit function working properly? - c

I wrote this short code to test my understanding of the isdigit function:
int inChar;
printf("enter input:");
scanf(" %d", &inChar);
if (isdigit(inChar))
printf("Your input was a number");
else
printf("Your input was not a number.\n");
When I test this program and I enter a number, C returns the else statement (Your input was not a number.). So regardless of if I enter a number or a letter, the program returns the else statement.
Why is this so?

isdigit() checks if a single character that was passed to it by converting the char value an unsigned char.
So, you can't directly pass any int value and expect it to work.
Man isdigit() says:
isdigit()
checks for a digit (0 through 9).
To check single digit, you can modify:
char inChar;
printf("enter input:");
scanf(" %c", &inChar);
if (isdigit((unsigned char)inChar)) {
printf("Your input was a number");
}
else {
printf("Your input was not a number.\n");
}
If you have an array (a string containing a number) then you can use a loop.

The function's purpose is to classify characters (like '3'). Running it on something that's read using %d doesn't make sense.
You should read a single char using %c. Remember to check that reading succeeded.

The C library function void isdigit(int c) checks if the passed character is a decimal digit character.
If you badly wanna try it with an int you can init in this way
int inChar = '2';
The following code gave expected results.
int main()
{
char inChar;
printf("enter input:");
scanf(" %c", &inChar);
if (isdigit(inChar))
printf("Your input was a number. \n");
else
printf("Your input was not a number.\n");
return 0;
}
Output:
vinay-1> ./a.out
enter input:1
Your input was a number

Related

How to check for non-number inputs in calculator in C

Just started learning C and tried to make a calculator to test myself. I thought it would be a fun challenge to make it so:
the program prints an error message to the user if the input(s) is not a number
the user can input a number again, without shutting down the program
What I've learned in C so far is:
printf, scanf
data types
if statements
loops
functions
My question is, is it possible to accomplish the task with the knowledge mentioned above. If it is, what is that solution? (I've been stuck on this for quite a while now, so I hope me giving up on doing it myself is acceptable). If it's not, what do I need to learn to be able to do it?
Here's my code
#include <stdio.h>
float num1;
float num2;
float answer;
char operation;
int isNumber; //1 means true, 0 means false
char restart;
int main ()
{
printf ("Please enter the first number: ");
isNumber = scanf("%f", &num1);
while (isNumber == 0)
{
printf("Please enter a valid number: ");
isNumber = scanf("%f", &num1);
}
//This just keeps reapeating the printf message.
//Also, I just wrote the code for the first input.
//If it doesn't work for this one, no point in writing it for other inputs.
printf ("Please enter an operation: ");
scanf (" %c", &operation);
printf ("Please enter the second number: ");
scanf ("%f", &num2);
if (operation == '+')
{
answer = num1 + num2;
}
else if (operation == '-')
{
answer = num1 - num2;
}
else if (operation == '*')
{
answer = num1 * num2;
}
else if (operation == '/')
{
while (num2 == 0)
{
printf ("Cannot divide by 0. ");
printf ("Please enter another number\n");
scanf ("%f", &num2);
}
answer = num1 / num2;
}
printf ("\nThe answer is: %f", answer);
printf ("\n\nEnter 1 to do another calculation. Enter anything else to quit: ");
scanf(" %c", &restart);
if(restart == '1')
main();
else
return 0;
}
scanf() only reads input that matches the format specifier (in your case this is %f). Characters that do not match the format specifier causes scanf() to stop scanning and causes scanf() to leave the invalid characters in the stdin buffer.
In your while loop if a invalid character is entered it will get stuck in the stdin buffer. This invalid character will then get read by the next scanf() call in the loop, which will also leave it in the stdin buffer. This will continue, again and again, resulting in an infinite loop.
As you might be able to tell scanf() is a unreliable and quick - yet not very robust way to take input.
To fix it you could use a hacky solution like this:
while ((scanf("%f", &num1)) != 1)
{
printf("Please enter a valid number: ");
int c;
while((c = getchar()) != '\n' && c != EOF);
}
// while loop "eats up" any characters
// that scanf has left in stdin buffer
Instead of scanf() i reccomend you get familiar with a function such as fgets() to take input. Then you can use a function like sscanf() to parse the input to see if it is a float.
As a beginner, while you are learning C, it is fine to use scanf(). But as you delve deeper into C and write more complicated pieces of software you must consider using safer and more robust alternatives to unreliable functions like scanf().
To well handle user input, consider dropping all scanf() calls. To read a line of user input, use fgets().
How to check for non-number inputs
Create a helper function.
Read a line of text into a buffer and parse with sscanf() or strod(). sscanf() is OK and used below. strod() is better, yet some corner cases are beyond what a learner may appreciate.
#define LINE_LENGTH_MAX 400
// Return 1 on success, EOF on end-of-file, 0 on failure
int read_double(double *dest, const char *prompt) {
if (prompt) {
fputs(prompt, stdout);
}
char buffer[LINE_LENGTH_MAX + 1];
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
return EOF;
}
int n = 0;
sscanf(buffer, "%f %n", dest, &n);
if (n == 0) {
// Scanning failed
return 0;
}
if (dest[n]) {
// Yet there was extra junk at the end
return 0;
}
return 1;
}
More advance code would used strtod() and detect lines longer than LINE_LENGTH_MAX.

Check validation from user in C programming

This is a snippet of my code. I'm confused why is digit can't function. It should if we input character/alphabet. The line is digit print "Please enter in numeric " but it doesn't print it. I need your opinion about this.
This my code:
printf("\nenter the amount of food to be purchased : ");
scanf("%d", &b);
printf("\n");
if (b >= 0) {
for (a=1; a<=b; a++){
printf("the price of food of- %d \t : ",a);
scanf("%d", &c);
printf("\n");
if (isdigit(c)) {
printf("Please enter in numeric !!\n");
while ((getchar()) != '\n');
system("PAUSE");
goto cashier;
}
printf("the amount ordered \t : ");
scanf("%d", &d);
printf("\n");
if (isdigit(d)) {
printf("Please enter in numeric !!\n");
while ((getchar()) != '\n');
system("PAUSE");
goto cashier;
}
scanf("%d", &c);. Reads an integer to c. When you call isdigit(c), you are not checking whether the input string is a number, you are checking whether the number inputted corresponds to an ascii character that represents a digit. This is not the intended behavior. What you want is this:
while (scanf("%d", &c) != 1) // Repeatedly get input until scanf reads 1 integer.
{
while (getchar()!='\n'); // Clear stdin.
puts("Please enter a number!");
}
// The resulting number is now stored in c.
This will try to read a number (not a string) into c. If the user does not enter 1 number, scanf() will not return 1 and the loop will try again. make sure that c is declared as an int and not a char, else numbers above 128 will overflow.

C program, getting the integer value of a character. Why everything comes out after line 10?

Hi I am new to programming and I got a trouble when I try to make a little change to the example in the book.
/* Chapter 3 Example, C Prime Plus */
#include <stdio.h>
int main(void)
{
char Letter, ch;
int intValue;
printf("Please enter a letter: \n");
scanf("%c", &Letter); /* user inputs character */
printf("The code for %c is %d.\n", Letter, Letter);
printf("Now is another we to implement the process: \n");
printf("RN, the value of ch is %c, and the value of intValue is %d\n", ch, intValue);
printf("Please enter a letter: \n");
scanf("%c", &ch);
intValue = ch;
printf("The code for %c is %d.\n", ch, intValue);
return 0;
}
When I run it, the outcome would be
Please enter a letter:
M
The code for M is 77.
Now is another we to implement the process:
RN, the value of ch is , and the value of intValue is 0
Please enter a letter:
The code for
is 10.
and the part
"
Now is another we to implement the process:
RN, the value of ch is , and the value of intValue is 0
Please enter a letter:
The code for
is 10. " will all come out without asking me to enter a value.
I want to know why and are there any other way to implement it that is different from examples in the book?
Thank you for your time!
Hi Matt_C and welcome to SO.
First, you don't need the second bloc of printfs and the scanf, it just trying to do the same thing and there is an order error.
Second, it is tricky when you try consecutive scanf, it holds the last key pressed (enter is the last key pressed = \n). This is why it skips the second scanf.
There a little solution for that, add a space at the beginning of the scanfs. Try this:
int main() {
char exit, letter;
while (1) {
printf("Please enter a letter: ");
scanf(" %c", &letter);
printf("\nThe code for '%c' is %d. \n\n", letter, letter);
printf("Exit ? (y/n): ");
scanf(" %c", &exit);
if(exit == 'y')
{
break;
}
system("clear"); // UNIX
//system("cls"); // DOS
}
}
Don't forget to choose one answer that you believe is the best solution to your problem.

calling main function in C

#define f(x) (x*(x+1)*(2*x+1))/6
void terminate();
main()
{
int n,op;
char c;
printf("Enter n value\n");
scanf("%d",&n);
op=f(n);
printf("%d",op);
printf("want to enter another value: (y / n)?\n");
scanf("%c",&c); // execution stops here itself without taking input.
getch();
if(c=='y')
main();
else
terminate();
getch();
}
void terminate()
{
exit(1);
}
In the program above , I want to take input from the user until he enters an n value.
For this I'm trying to call main() function repeatedly . If it is legal in C , I want to know why the program terminates at the scanf("%c",&c) as shown in commented line.
Someone , please help.
You should never call main from within your program. If you need to run it more then once use a while loop inside it.
Your execution stops because by default stdin in a terminal is line buffered. Also you are not using the return value from getch.
int main()
{
int n,op;
char c;
do {
printf("Enter n value\n");
scanf("%d",&n);
op=f(n);
printf("%d",op);
printf("want to enter another value: (y / n)?\n");
scanf("%c",&c);
} while (c == 'y')
return 0;
}
You first have
scanf("%d",&n);
which you have to press the Enter key for it to accept the number.
Later you have
scanf("%c",&c);
There is a problem here, which is that the first call to scanf leaves that Enter key in the input buffer. So the later scanf call will read that.
This is easily solved, by changing the format string for the second scanf call just a little bit:
scanf(" %c",&c);
/* ^ */
/* | */
/* Note space here */
This tells the scanf function to skip leading whitespace, which includes newlines like the Enter key leaves.
It's legal, but you'll have a STACKOVERFLOW after a while (pun intended).
What you need is a loop:
while (1) {
printf("Enter n value\n");
scanf("%d",&n);
op=f(n);
printf("%d",op);
printf("want to enter another value: (y / n)?\n");
scanf("%c",&c); // execution stops here itself without taking input.
getch();
if(c != 'y')
break;;
}

While Loop skipping scanf for it's condition.

I can't see why does the While loop just speed away and skipping the scanf for the char?
It would not even ask for my input and just loop like there's no tomorrow.
#include <stdio.h>
int main()
{
int number;
int multiply, ans;
char choice;
printf("-------------------------------------");
printf("\n MULTIPLICATION TABLE ");
printf("\n-------------------------------------");
do
{
printf("\nEnter an integer number:");
scanf("%d", &number);
printf("\nMultiplication of %d is :-\n", number);
printf("\n");
for(multiply=1; multiply<11; multiply++){
ans = number * multiply;
printf(" %d", ans);
}
printf("\n");
printf("\nWould you like to continue? [Y] for Yes,[N] for no : ");
scanf("%c", &choice);
printf("\n");
}
while(choice='Y');
printf("Thank You");
return 0;
}
scanf() doesn't do what you think it does (newline characters, buffering, etc.). It's preferred to use fgetc():
choice = fgetc(stdin);
For the same reason, you need to get rid of the trailing newline that
scanf("%d", &number");
leaves in the standard input buffer. To fix this, insert
fgetc(stdin);
after that particular call to scanf().
Also, C is not Pascal. The equality comparison operator - and the condition - you're looking for is
while (choice == 'Y')
the single equation mark denotes an assignment.
I think you need to use == operator for the comparison in while condition check as:
while(choice=='Y');
Currently you are using = operator, which is assigning Y to choice variable.
It has been a long time since I programmed in that language, but at a glance, you have:
while(choice='Y');
instead of:
while(choice=='Y');
== compares, = sets equal to. So the while loop is actually not checking the condition you're trying to set.

Resources