I have a function which takes an integer input by the user.
So I have:
scanf("%d, &x);
And then, the function:
test(int x);
Inside test(), I wanna check if the input is a digit or a character, so I tried:
if (isdigit(x))
// piece of code
printf("Done!\n");
else
printf("Bye!\n");
However, isdigit() does not seem to be working as the program is outputting "Bye!" immediately. What could be the problem?
Thanks.
You are passing integer not char!
isdigit(x) check whether x is a digit char e.g. '0', '1' but not 0, 1 what you are passing.
It behaves like:
isdigit('h') returns 0
isdigit('1') returns 1
isdigit(1) returns 0 // your are passing this
Read manual:
Standard C Library Functions ctype(3C)
isdigit() Tests for any decimal-digit character.
isdigit tests a character:
isdigit('5') == true;
isdigit(5) == false;
remove the semicolon:
if (isdigit(x)); // <===
Because of the semicolon, if it is a digit you execute an empty statement.
The C library function void isdigit(int c ) checks if the passed character is a decimal digit character.
The isdigit() function returns non-zero if c is a decimal digit otherwise 0.The input argument is an int, the value of which the application shall ensure is a character representable as an unsigned char or equal to the value of the macro EOF. i.e
ensure that your value is enclosed in single quotes.
You also seemed to have a ; after the if statement which shifts the expected control flow.
char x;
scanf(" %c", &x);
if (isdigit(x))
printf("Done!\n");
else
printf("Bye!\n");
Suspect OP wants to read a char
char x; // new type
scanf(" %c", &x); // new format specifier
if (isdigit(x)) // remove ;
// piece of code
printf("Done!\n");
else if (isalpha(x)) // added test #Joachim Pileborg
printf("Is a alpha!\n");
else
printf("Bye!\n");
Related
I need to receive from the user input that can come in 2 forms, char int float or char int, but I don't know which of them will be given. I tried this:
int main(){
char letter;
int num;
float value;
while(getchar()!=EOF){
scanf(" %c %d %f", &letter, &num, &value);
printf("%c\n", letter);
printf("%d\n", num);
printf("%f\n", value);
}
return 0;
}
The problem with this is when I give an input like this:
? 12345
g 12345 45.6
? 12345
Output given: Expected Output:
1 ?
2345 12345
0.000000 0.000000
1 g
2345 12345
45.599998 45.599998
? ?
12345 12345
45.599998 45.599998
Why is part of the number going in the place of the char and the char is ignored? Is there a way to fix this?
There are several problems here:
The missing char. When you do while(getchar()!=EOF) for the first time, you are consuming the first character in the stream, which happens to be '?'. The subsequent scanf() cannot retrieve that anymore, so it grabs the next non-whitespace character, which happens to be the '1' of the following number.
After that '1' is read, the rest of the number is parsed, providing the result 2345.
The following conversion tries to parse a float, but the next non-whitespace character is a g, so no float can be read, and the conversion fails.
You fail to check, how many conversions are successful. scanf() dutifully returns the number of successful conversions, but you ignore that.
If you had checked the return value, you would have found that the first scanf() call returns 2 because the character and the integer conversions finished successfully, but the float conversion failed.
Likewise, the second scanf() call should have returned 3, signaling that all three conversions succeeded. The last call to scanf() should return 2 again.
The gobbling up of a character in while(getchar()!=EOF) bites you again on the second line, this time it is the 'g' that's removed from the stream before the scanf() gets a chance to read it.
After the second call to scanf() successfully terminates, the '\n' character is left in the stream. Thus, the following while(getchar()!=EOF) gobbles that up, and the third scanf() call can finally correctly fetch the first character on the line ('?').
The float conversion fails again on the third input line, and the corresponding variable is left untouched, and you fail to detect this condition by ignoring the return value of scanf().
Long story short:
Each getchar() call consumes a character that cannot be read by scanf() anymore.
Any scanf() call that ignores the return value is a bug. Without checking that, you cannot know that you actually read anything.
Btw: man scanf and man getchar could have told you everything I just said. It pays off to know how to read manpages.
In this case, it's best to first retrieve the user input as char* (fgets-like) and then parse it with sscanf (not scanf, sscanf).
You will have to check the return value of sscanf in order to know wether the input user is correctly formatted.
If you need to check if there is not garbage value after the parsing (like "g 12345 45.6 garbagevalue"), you can add a %c after and check if the value have changed.
char letter;
int integerNumber;
double floatingNumber;
char end;
char *userInput = ...;
end = '\0';
if (sscanf(userInput, "%c %d %f%c", &letter, &integerNumber, &floatingNumber, &end) == 3 && end == '\0') {
// First form
} else {
end = '\0';
if (sscanf(userInput, "%c %d%c", &letter, &integerNumber, &end) == 2 && end == '\0') {
// Second form
} else {
// Error : Input not strictly "%c %d %f" or "%c %d"
}
}
Sound good to you ?
I wonder if it would be simpler to read in a block of data from the keyboard to a string from the keyboard and then analyse with sscanf as in the outline below
#define MAX_INPUT 100
char data_input[MAX_INPUT];
int finished=0, test;
char letter;
int num;
float value;
while (finished==0) {
// scanf("%s",data_input); //taken out after useful comments below
fgets(data_input,100,stdin); //replacement from comments...
// insert code using sscanf to read in data from user
test=sscanf(data_input, "%c %d %f", &letter, &num, &value);
if (test==3)
{
//success - sscanf successfully assigned 3 values...
// (ony if you have everything you need then....)
finished =1;
} else if (test==2){
// insert something to try to test if data from two data entries is ok....
// (ony if you have everything you need then....)
finished =1;
} else {
printf("problem with data entry - please type again\n");
}
}
with apologies to #Tom's because the use of sscanf was first suggested by him...
I have been trying to add some experience in C to my experience with Python and started with a basic addition program. One thing that I'm trying to do is check if the input is a number or a character as seen here:
#include <stdio.h>
#include <ctype.h>
int main()
{
int n, sum=0,c,value;
printf("Enter the Number of Integers You Want to Add\n");
scanf("%d", &n);
if(isdigit(n))
{
printf("Enter %d Integers\n", n);
for(c=1; c<=n; c++)
{
scanf("%d", &value);
if(isalpha(value))
{
printf("ENTER INTEGER NOT CHARACTER\n");
break;
}
else
{
sum = sum + value;
}
}
printf("Sum of Entered Integers = %d\n",sum);
}
else
{
printf("ENTER INTEGER NOT CHARACTER\n");
break;
}
return 0;
}
Initially I had tried this using isalpha(), and the program worked fine when adding numbers but interpreted characters as zeros instead of printing the "not an integer" statement. However, now that I reworked it to use isdigit(), it does not recognize ANY input as an integer, whether or not it is. Is there something that I'm just doing wrong?
When you use scanf to read an integer, you get just that, an integer. (To read a single character, you need %c and a pointer-to-char).
When you use isdigit(), you need to supply the representation of that character (e.g. in ASCII, the character '0' has the representation 48, which is indeed its value as an integer). To recap:
isdigit(0) is false
isdigit(48) is true (for ASCII, ISO8859, UTF-8)
isdigit('0') is true (no matter the character set)
isdigit('0' + n) is true for integers n = 0 ... 9
PS: Not testing the return value from scanf is asking for trouble...
Neither isdigit nor isalpha work as you think they do. The intent of those library functions is to check whether a given code point, represented as an int, is within a subset of points defined by the standard to be digit characters or alpha characters.
You should be checking the results of your scanf calls rather than assuming they just work, and acting on those results accordingly. If you request an integer and one is successfully scanned, then it will tell you so. If that fails, your course of action is probably to consume the rest of the line (through newline or EOF) and possibly try again:
#include <stdio.h>
int main()
{
int n,value,sum=0;
printf("Enter the Number of Integers You Want to Add\n");
if (scanf("%d", &n) == 1 && n > 0)
{
printf("Enter %d Integers\n", n);
while (n--)
{
if (scanf("%d", &value) == 1)
{
sum = sum + value;
}
else
{
// consume the rest of the line. if not EOF, we
// loop around and try again, otherwise break.
while ((value = fgetc(stdin)) != EOF && value != '\n');
if (value == EOF)
break;
++n;
}
}
printf("Sum of Entered Integers = %d\n", sum);
}
return 0;
}
Properly done you should be able to enter valid integers beyond single digits (i.e. values > 10 or < 0), which the above allows.
The %d marker to scanf tells it to interpret the input as a number (more accurately, it indicates that the pointer in the arguments points to an integer type). It can't do anything but put an integer into that argument. If it can't interpret the input as a number, scanf stops scanning the input and returns immediately.
isdigit() evaluates its argument as a character code, as Jens points out above. However, scanf already turned the character code into a pure number.
From the scanf man page:
On success, the function returns the number of items of the argument list
successfully filled.
In your program, you are trying to read just one item from stdin, so scanf should return 1. So check for that and you'll know that it all worked out ok:
printf("Enter the Number of Integers You Want to Add\n");
while(scanf("%d", &n) != 1) {
printf("That's not a valid integer. Please try again.\n");
}
You cannot use isdigit() the way you are using it because you're already using scanf to convert the user input to an integer. If the user had not input an integer, scanf would have already failed.
Look at the man pages for all the C functions you are using, they will show you what the function expects and what the return values will be under different circumstances.
In the case of isdigit(), the input is expected to be an unsigned char representing an ASCII character. This can be a bit confusing because ASCII characters are in fact represented as a type of integer, and a string is an array of those. Unlike languages like Python which hide all that from you. But there is a big difference between the STRING of a number (array of characters that contain the characters of the digits of the number) and the INTEGER itself which is in a form the processor actually uses to do math with... (simplified explanation, but you get the idea).
I have this code:
#include <stdio.h>
#include <ctype.h>
int main()
{
char x;
printf("Program shows your name and check if the first letter is capital");
while (scanf_s("%c", &x) !=1 || getchar() !='\n')
{
if (islower(x))
{
printf("Name begins with a capital letter\n");
while (getchar() != '\n')
;
}
else
{
printf("%c", x);
}
break;
}
while ((x = getchar()) != EOF)
{
printf("%c", x);
}
return 0;
}
For example:
When I type "Matthew" the result is "Mtthew". Whats wrong? I have no clue.
I tried to change almost everything in first "while" but i think the problem is not there. Any ideas?
The function getChar() removes a character from the input stream, so that it is no longer upon it. By using it within your conditional statement, it is:
Getting the character from the stream (a.k.a: removing it)
Comparing it, and finally
Discarding it (without having saved it somewhere)
If you refactor your code to consider this, then I believe your mystery character will return :-)
Change the first while to
while ((x = getchar()) != EOF && x != '\n')
EDIT: And change char x to int x because EOF isn't guaranteed to be representable by a char.
Your program worked without skipping a character when the following changes were made: (refer to comments in-line)
int x; //change to int for use with getchar()
printf("Program shows your name and check if the first letter is capital");
while (scanf("%d", &x) !=1 || getchar() !='\n')
^ //changed to d for int
But the comment made in #J.Murray's answer about getchar() eating a character is valid. So although your program worked for me, there are some input sequences for which it will not.
Note: The reason for using int as opposed to char is that getchar() can return EOF, which == -1. A char cannot contain a -1.
Certainly incorrect use of scanf_s("%c", &x)
The fscanf_s function is equivalent to fscanf except that the c, s, and [ conversion specifiers apply to a pair of arguments (unless assignment suppression is indicated by a *). The first of these arguments is the same as for fscanf. That argument is immediately followed in the argument list by the second argument, which has type rsize_t and gives the number of elements in the array pointed to by the first argument of the pair. (C111dr §K.3.5.3.2 6)
scanf_s("%c", &x, (rsize_t)1)
Other issues may exist.
Why the output is '4' ? , while input is 'A'
int main() { int a = 5;
if(scanf("%d",&a))
printf("%d",a+1);
else
printf("%d",a-1);
}
When type sepcifier %d is used then the function expects that a valid signed decimal integer number will be entered. It is evident that symbol 'A' is not a number so the input failed.
Now a question arises: what will the function return in this case?
According to the description of function scanf (the C Standard, 7.21.6.4 The scanf function):
3 The scanf function returns the value of the macro EOF if an input
failure occurs before the first conversion (if any) has completed.
Otherwise, the scanf function returns the number of input items
assigned, which can be fewer than provided for, or even zero, in the
event of an early matching failure.
So the condition in the if statement
if(scanf("%d",&a))
evaluated to 0 (false) and the else statement was executed.
else
printf("%d",a-1);
that outputed 4.
Take into account that in general you may enter symbol 'A' for integers. But in this case the corresponding integer variable must be declared as unsignedand format specifier of scanf must to be %x
For example
#include <stdio.h>
int main( void )
{
unsigned int a = 5;
if ( scanf( "%x", &a ) )
{
printf( "%u\n", a + 1 );
}
else
{
printf( "%u\n", a - 1 );
}
}
In this case the output will be 11.:) scanf will consider symbol 'A' as a hexadecimal representation of 10.
You instructed scanf to read a signed integer. The input didn't even start with a sign or digit, so scanf didn't find a signed integers, so scanf returned 0 (the number of input items successfully matched and assigned), dropping you into the else clause of the if. Since scanf didn't match anything, it didn't assign anything, meaning a wasn't changed, and a-1 is 4.
You didn't specify what you were expecting, so I don't know what fix to suggest.
In scanf() All the arguments you pass are pointers. There's no default-promotion among pointers, and it is crucial that you pass the exact format specifier that matches the type of the pointer.
for more clearance:-
Click here!
I've used getchar and putchar to succeessfully print my entered char to the screen before, however I've changed the code slightly and now it prints my entered char twice in a row. Code:
#include <stdio.h>
int main()
{
int charInput;
printf("Enter a char >> ");
charInput = getchar();
printf("%c", putchar(charInput));
return 0;
}
I know I could just use putchar without the printf but I wanted to experiment with them. The output I get is:
Enter a char >> a
aa
2 chars are printed to the screen?
The function putchar(charInput) itself print char 'a' and return decimal equivalent of char (e.g ascii) that is printed as char using printf() so total printed two a.
Read Manual page:
int putchar(int c);
The functions, fputc(), putc(), putchar(), putc_unlocked(), and
putchar_unlocked() return the character written. If an error
occurs, the value EOF is returned. The putw() function returns 0 on
success; EOF is returned if a write error occurs, or if an attempt is
made to write a read-only stream.
So you can assume:
printf("%c", putchar(charInput));
// ^ ^ first `a`
// | second `a`
is equivalent to:
temp = putchar(charInput); // first `a`
printf("%c", temp); // second `a`
putchar(charInput) will print your character once, and will then return its argument,
charInput. This then gets passed to printf, which prints the same character again.
This is because one comes fromprintf and another from putchar.
Do only this
putchar(charInput);