-1

I´d like to check if user input is a float/integer or a letter. For this purpose the use of scanf() is important. My problem is that a letter is saved as zero but I can´t exclude it.

I tried building solving it with if and as a condition I tried isalpha() and is digit().I tried a bunch of other things, but it´s not worth mentioning.

  • "My problem is that a letter is saved as zero" --> No nothing was saved. Read user input line with `fgets()`, then use `strtod()`. – chux - Reinstate Monica Nov 02 '22 at 23:07
  • `scanf` can only read things or not; it can't make any clever decisions. `%d` can only read an integer, or nothing. `%f` can only read a floating-point number, or nothing. `%s` can read any string — but it'll read it as a string, and it'll be up to *you* to, maybe, convert that string to an integer or a floating-point number, perhaps with `atoi` or `atof`. – Steve Summit Nov 02 '22 at 23:46
  • S. Doerr, What should happen to input if it is not a number? – chux - Reinstate Monica Nov 04 '22 at 04:48
  • 1
    @chux I have to use scanf() – S. Müller Nov 06 '22 at 11:35
  • 1
    @chux If the input isn't number the programm should end. – S. Müller Nov 06 '22 at 11:36
  • @SteveSummit I have found a solution, altough not the ideal one: – S. Müller Nov 06 '22 at 11:41
  • a = scanf(...); – S. Müller Nov 06 '22 at 11:42
  • if(a == 0){...} – S. Müller Nov 06 '22 at 11:43
  • Is it possible to write the first line the condition – S. Müller Nov 06 '22 at 11:44
  • Checking `scanf`'s return value is, if not "ideal", certainly a highly-recommended strategy. So don't feel bad about that. And you can absolutely collapse things, and write `if(scanf(…) == 0) { … }` or `if(scanf(…) != 0) { … }`, and those are generally good ways of writing it. Generally you don't need to re-use the return value later, so generally there's no need to store it in a variable (`a`).. – Steve Summit Nov 06 '22 at 11:51
  • You might be interested in these other [guidelines for using `scanf` simply and safely](https://stackoverflow.com/questions/72178518#72178652). (We've just talked abut what's now #10.) – Steve Summit Nov 06 '22 at 11:55
  • One correction to my earlier comment, though: generally you want to write `if(scanf(…) != 1) { /* scanf failed */ }` or `if(scanf(…) == 1) { /* scanf succeeded */ }`. `scanf` can also return the negative value `EOF` under some failure conditions. That is, it does not return 0/1 for fail/succeed. It actually returns `EOF`/0/1 for fail/fail/succeed, and if you ask it to read two or more values, it'll return 2 or more when it succeeds.) – Steve Summit Nov 06 '22 at 11:58
  • 1
    One more comment: whoever told you that you "have to use `scanf`" sounds like an idiot. Experience has shown that scanf is only good for reading very simple input and doing very simple things with it. But it's not good for doing something even mildly complicated, like reading something that might-be-a-letter-or-might-be-an-integer. In my opinion, `scanf` is something you only want to use during the first two or three weeks of your C programming career, until you've learned enough to be able to [use something better](https://stackoverflow.com/questions/58403537). – Steve Summit Nov 06 '22 at 12:04
  • With that said, if the assignment was to "read a sequence of numbers from the user, and have the user terminate the list by typing a letter", then `scanf` is a perfectly good tool for that task, as long as you check its return value, as you've discovered. – Steve Summit Nov 06 '22 at 12:06
  • @SteveSummit Thank you for your answer. (I have to use scanf, because we are only allowed to use functions we already had in class) – S. Müller Nov 06 '22 at 12:35

2 Answers2

0

... to check if user input is a float/integer or a letter ...

scanf() is a weak function to use when input is either convertable as a float, integer or character - yet OP reports scanf() is obliged. Requirement to use scanf() is misguided.

First read a line of user input into a string. Be sure to limit input width.

char line[100 + 1];
if (scanf(" %100[^\n]", line) == 1) {
  // Successfully read a line

Now process the string. Use strtof(), strtoll() to parse for float, integer. Test the endptr for conversion success.

 char *endptr;   //  Record end of conversion.

 errno = 0;
 long long ll = strtoll(line, &endptr, 10);
 if (endptr > line && errno == 0 && *endptr == 0) {
   // Successfully parsed a long int
   printf("long long: %ld\n", ll);
 } else {
   errno = 0;
   float f = strtof(line, &endptr);
   if (endptr > line && *endptr == 0) {
     // Successfully parsed a float
     printf("float: %.9g\n", f);
   } else {
     printf("otherwise <%s>\n", line);
   }
 }

Additional code useful to detect empty or long lines.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

If the actual requirement is something like this:

Read a series of numbers (integers or floating-point numbers) from the user. Stop reading when the user types something other than a number, such as a letter.

, then the solution, using scanf, is perfectly straightforward:

#include <stdio.h>

int main() 
{
    int maxnums = 10;
    double numbers[maxnums];
    int i;

    for(i = 0; i < maxnums; i++) {
        printf("enter a number, or nondigit to quit: ");
    fflush(stdout);

        double x;
    if(scanf("%lf", &x) != 1)
            break;

        numbers[i] = x;
    }

    int nnum = i;

    printf("you typed %d number(s):\n", nnum);

    for(i = 0; i < nnum; i++)
        printf("%d: %f\n", i, numbers[i]);
}

The loop stops (using the break statement; I hope you've gotten to that in class by now) if scanf returns something other than 1, indicating that no number could be read. The loop also stops after the user enters 10 numbers, because that's how big the input array is.

It looks like the loop reads only floating-point numbers, and in a sense it does, but if the user types a pure integer, like 123, without a decimal point, that's still perfectly acceptable as a floating-point input, and it will be read as the floating-point value 123.000.

On the other hand, if there was a requirement to be able to tell whether the user actually entered a pure integer versus a floating-point number, or if there was a requirement to do something else with the pure integers other than storing them in the same array with the floating-point inputs, or if there was a requirement to know (to read and perhaps process) the specific non-numeric input the user typed to terminate the input loop, none of those additional requirements could be met with this simple code. In fact, in my opinion, meeting any of those additional requirements using scanf is effectively impossible, and some completely different approach, not involving scanf, would be required.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103