Search code examples
catoi

Return of atoi() - C function


I have random strings and i want to sort them. I need to find those containing only digits (like xyz..., x,y,z are digits); What function to use?

I have tried atoi("3=fyth433"). But that returns 3. I was expecting it to return 0 for a string that contains characters that cannot be parsed as integers.


Solution

  • You can use a simple test:

    if (*buf && buf[strspn(buf, "0123456789")] == '\0') {
        /* buf only contains decimal digits */
    }
    

    strspn() returns the number of characters at the start of its first argument that match one character from the second string. The extra test on *buf avoids matching the empty string. The empty string contains only digits is true as it does not contain anything at all.

    If buf was read by fgets, you would check for '\n' instead of '\0', but as correctly pointed out by chux, there is a corner case if the last line does not end with a linefeed:

    #include <string.h>
    #include <stdio.h>
    
    ...
    
    char line[256];
    while (fgets(line, sizeof line, stdin)) {
        size_t ndigits = strspn(line, "0123456789");
        if (ndigits > 0 && (line[ndigits] == '\n' || line[ndigits] == '\0')) {
            /* line only contains decimal digits */
        } else {
            /* line is empty or contains at least one non digit character */
        }
    }
    

    You can also use the function isdigit() from <ctype.h>, but care must be taken to not pass char values directly as they might be negative, invoking undefined behavior. Here is an alternative:

    int string_has_only_digits(const char *str) {
        if (!*str) // empty string
            return 0;
        while (isdigit((unsigned char)*str))
            str++;
        return *str == '\0';
    }
    

    You cannot use strtol for this because it accepts an initial sequence of white space and an optional sign.