1

I have a code where I convert celsius to fahrenheit. And I need to check what user writes char or int.

I've tried isalpha and isdigit, but they do not work.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
    char t[] = "";
    scanf("%s", &t);
    if(isalpha(t))
    {
        printf("It's char\n");
    }
    else if (isdigit(t))
    {
        printf("It's int\n");
    }


    return 0;
}
Vlad from Moscow
  • 224,104
  • 15
  • 141
  • 268
I-Rey
  • 25
  • 4
  • 3
    How do they not work? You need to [edit] and clarify. – wjandrea Sep 21 '19 at 14:02
  • 1
    You are ignoring the return value of scanf() at your own risk. http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html – Yunnosch Sep 21 '19 at 14:02
  • You don't need `&` before `t` in `scanf()`. An array automatically decays to a pointer when used in an argument list. – Barmar Sep 21 '19 at 14:06
  • @Yunnosch : Good point in general, but short of perhaps encountering an EOF, any input can be successfully converted with `%s` as it is non specific about content. The string may well be empty of course. – Clifford Sep 21 '19 at 14:28
  • @Clifford You are right. But you do not seriously believe that is why OP ignores the return value in this case, do you? Anybody ignoring it deserves all the weird behaviour they get. Always, even if the cause is unrelated. Those who know not to ignore it, do a `(void)` in the rare cases they do it with good reason. – Yunnosch Sep 21 '19 at 14:35
  • @Yunnosch in a small experiment such as this, I probably wouldn't bother much with error checking either - it is not as if there is any user than yourself in such things. That said you should of course encourage good habits. In real code, I'd probably not use `scanf` at all for this, which is also what the link you posted recommends I think (TL:DR). – Clifford Sep 21 '19 at 16:05
  • @Yunnosch, REMEMBER that OP is a new contributor... :/ – Luis Colorado Sep 23 '19 at 03:44
  • @LuisColorado Thank you for reminding me. I-Rey, please accept my apology in case I have hurt you. But please also understand that I consider it wise not to ignore return values of any function you are using. This is true for experienced programmers and for others. You are new to StackOverflow, which means you might be new to programming. If you kindly ignore that I was talking *about you* with somebody else, instead of *to you* (this I consider the rudest what I did), there still remains the hopefully helpful advice to only ignore with good reason and then explicitly. – Yunnosch Sep 23 '19 at 05:44
  • Here is a discussion of an interesting way of getting scanf fail for quite unexpected reasons: https://stackoverflow.com/a/58056398/7733418 – Yunnosch Sep 23 '19 at 06:00
  • @Yunnosch, of course you are not due of it. You have not hurt me... With respect to your statement, it's also wise (and more for a library function) to get profit of the C use of defining only functions, and avoid the overhead of defining separately procedures and functions, and there's also strong legacy on using the `return` statement to return something related to the internal process followed by the function as a means of being more useful (e.g. the `return` value of `printf(3)` can be an example) This would be void if we had to forcibly cast to `void` every call to `printf()`... – Luis Colorado Sep 23 '19 at 07:33
  • ... as it should affect readability and maintainability of code. This can avoid a second call to this or another routine. – Luis Colorado Sep 23 '19 at 07:33
  • @LuisColorado You got me there. I openly admit to ignoring the return value of printf(). – Yunnosch Sep 23 '19 at 18:27

2 Answers2

2

isalpha and isdigit are applied to objects of the type int that contain a char.

You are trying to apply these functions to an object of the type char * (an array type is implicitly converted to a pointer type in expressions).

Moreover the array t declared like

char t[] = "";

is not enough large to store even one character gotten from scanf because it also need to store the terminating zero. Otherwise a call of scanf will have undefined behavior. And the call of scanf is also incorrect.

scanf("%s", &t);
            ^^^

It should be written at least like

scanf("%s", t);

You could declare an object of the type char like

char t;

and then use scanf like

scanf(" %c", &t);

and at last

if ( isalpha( ( unsigned char )t ) )
{
    printf("It's char\n");
}
else if ( isdigit( ( unsigned char )t ) )
{
    printf("It's int\n");
}
Vlad from Moscow
  • 224,104
  • 15
  • 141
  • 268
  • I'm afraid that `t` or `&t`, while misstyped, will point to the same place anyway. `scanf()` doesn't receive any type information in the parameter list, so, despite of being incorrect from a strong typed language point of view, the code is going to work. – Luis Colorado Sep 23 '19 at 03:47
1

Firstly:

char t[] = "";

creates a buffer of exactly one character, then

scanf("%s", t);

will overrun that buffer for anything but an empty string input. Making scanf() safe from overrun is not straightforward, but even then most naive implementation will have a practical buffer length e.g. ;

char t[128] = "" ;

If the expectation is to enter a string that can be converted to an int, then 10 decimal digits is sufficient for all positive 32bit integers.

scanf("%10s", t);

char and int are data types, here the user only ever enters a string. Your question is really whether the user has entered somthing that may be interpreted as an integer or not.

isalpha() and isdigit() operate on single characters, but t is a string.

The following will check the first character of the string t:

if( isdigit(t[0]) )
{
    printf("It's digit\n");
}
else
{
    printf("It's not a digit\n");
}

Note that it makes little sense testing for isalpha() because the union of all digits + all alpha, is still only a subset of all characters.

If in fact you simply wish to verify that the entire string is numeric then:

for( int i = 0; t[i] != 0 && isdigit(t[i]) i++ )
{
    // nothing
} 

if( t[i] == 0 )
{
     printf("It's numeric\n");
}
else
{
     printf("It's not entirely numeric\n");
}

Even then it is not a given that the numeric string can be represented by an int; it also has to be in range. You might also want to consider the possibility of a -/+ sign at the start, and might consider ignoring trailing non-numeric digits.

Clifford
  • 76,825
  • 12
  • 79
  • 145