简体   繁体   中英

Using isdigit with if

int main()
{
 int f;
 printf("Type your age");
 scanf("%d", &f);
 if(!isdigit(f))
  {
   printf("Digit");
  }
  else
  {
   printf("Is not a digit");
  }
return 0;
}

No matter if a typed 6 or a always shows me the "Digit" message

%d is an integer specifier. Change int f to char f and parse as a character. You are always passing an int into isdigit , which is why it is always true.

isdigit() should be passed a char not an int . And your if-else logic is reversed:

int main() {
    char f;

    printf("Type your age");
    scanf("%c", &f);

    if (isdigit(f)) {
        printf("Digit");
    } else {
        printf("Is not a digit");
    }

    return 0;
}

As mentioned in the comments, this will only work for a single digit age. Validating input is a major topic under the 'C' tag, a search will reveal many approaches to more robust validation.

There's actually no need to use isdigit at all here since scanf with the %d format specifier already guarantees that the characters will be digits with an optional leading sign. And there's a separate specifier to get rid of the leading sign, %u .

If what you input isn't of the correct format, scanf will tell you (since it returns the number of items successfully scanned).

So, for a simple solution, you can just use something like:

unsigned int age;
if (scanf("%u", &age) == 1) {
    puts("Not a valid age");
    return 1;
}
// Now it's a valid uint, though you may want to catch large values.

If you want robust code, you may have to put in a little more effort than a one-liner scanf("%d") - it's fine for one-time or throw-away programs but it has serious shortcomings for code intended to be used in real systems.

First, I would use the excellent string input routine in this answer (a) - it pretty much provides everything you need for prompted and checked user input.

Once you have the input as a string, strtoul allows you to do the same type of conversion as scanf but with the ability to also ensure there's no trailing rubbish on the line as well. This answer (from the same author) provides the means for doing that.

Tying that all together, you can use something like:

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

// Code to robustly get input from user.

#define OK       0      // Return codes - okay.
#define NO_INPUT 1      //              - no input given.
#define TOO_LONG 2      //              - input was too long.

static int getLine (
    char *prmpt,        // The prompt to use (NULL means no prompt).
    char *buff,         // The buffer to populate.
    size_t sz           // The size of the buffer.
) {
    int ch, extra;

    // Get line with buffer overrun protection.

    if (prmpt != NULL) {
        printf ("%s", prmpt);
        fflush (stdout);
    }
    if (fgets (buff, sz, stdin) == NULL)
        return NO_INPUT;

    // If it was too long, there'll be no newline. In that case, we flush
    // to end of line so that excess doesn't affect the next call.

    if (buff[strlen(buff)-1] != '\n') {
        extra = 0;
        while (((ch = getchar()) != '\n') && (ch != EOF))
            extra = 1;
        return (extra == 1) ? TOO_LONG : OK;
    }

    // Otherwise remove newline and give string back to caller.

    buff[strlen(buff)-1] = '\0';
    return OK;
}

// Code to check string is valid unsigned integer and within range.
// Returns true if it passed all checks, false otherwise.

static int validateStrAsUInt(
    char *str,                   // String to evaluate.
    unsigned int minVal,         // Minimum allowed value.
    unsigned int maxVal,         // Maximum allowed value.
    unsigned int *pResult        // Address of item to take value.
) {
    char *nextChar;
    unsigned long retVal = strtoul (str, &nextChar, 10);

    // Ensure we used the *whole* string and that it wasn't empty.

    if ((nextChar == str) || (*nextChar != '\0'))
        return 0;

    // Ensure it's within range.

    if ((retVal < minVal) || (retVal > maxVal))
        return 0;

    // It's okay, send it back to caller.

    *pResult = retVal;
    return 1;
}

// Code for testing above functions.

int main(void) {
    int retCode;
    unsigned int age;
    char buff[20];

    // Get it as string, detecting input errors.

    retCode = getLine ("Enter your age> ", buff, sizeof(buff));

    if (retCode == NO_INPUT) {
        printf ("\nError, no input given.\n");
        return 1;
    }

    if (retCode == TOO_LONG) {
        printf ("Error, input too long [%s]\n", buff);
        return 1;
    }

    // Check string is valid age.

    if (! validateStrAsUInt(buff, 0, 150, &age)) {
        printf("Not a valid age (0-150)\n");
        return 1;
    }

    // It's okay, print and exit.

    printf("Age is valid: %u\n", age);
    return 0;
}

(a) I'm reliably informed the author is actually quite clever, and very good looking :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM