michithebest
michithebest

Reputation: 95

C: Check if a string is an integer and save it

I've been searching the internet for some time, but didn't find a simple solution for a actually simple problem in my eyes. I guess it has been asked already:

I'm reading a value like 20.1 or XYZ via sscanf from a file and saving it in char *width_as_string.

All functions should be valid in -std=c99.

Now I want to check if the value in width_as_string is an integer. If true, it should be saved in int width. If false, width should remain with the value 0.

My approaches:

int width = 0;
if (isdigit(width_as_string)) {
    width = atoi(width_as_string);
}

Alternatively, convert width_as_string to int width and convert it back to a string. Then compare if it is the same. But I'm not sure how to achieve that. I already tried itoa.

Functions like isdigit and itoa are not valid in std=c99, therefore I can't use them.

Thanks.

Upvotes: 0

Views: 138

Answers (3)

Read carefully some documentation of sscanf. It returns a count, and accepts the %n conversion specifier to give the number of character (bytes) scanned so far. Perhaps you want:

int endpos = 0;
int width = 0;
if (sscanf(width_as_string, "%d %n", &width, &endpos)>=1 && endpos>0) {
  behappywith(width);
};

Perhaps you want also to add && width_as_string[endpos]==(char)0 (to check that the number is perhaps space suffixed, then reaching the end of string) after endpos>0

You could also consider the standard strtol which sets an end pointer:

char*endp = NULL;
width = (int) strtol(width_as_string, &endp, 0);
if (endp>width_as_string && *endp==(char)0 && width>=0) {
  behappywith(width);
}

The *endp == (char)0 is testing that the end of number pointer -filled by strtol- is the end of string pointer (since a string is terminated with a zero byte). You could make that more fancy if you want to accept trailing spaces.

PS. Actually, you need to specify precisely what is an acceptable input (perhaps by some EBNF syntax). We don't know if "1 " or "2!" or "3+4" are (as C strings) acceptable to you.

Upvotes: 1

RCap107
RCap107

Reputation: 287

Actually, you could use sscanf at the very beginning to check whether the number is integer or not. Something like this

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

 int 
 main (int argc, char *argv[])
 {
    int wc; // width to check
    int w; // width

    char *string = "20.1";

    printf("string = %s\n", string);

    if (strchr(string, '.') != NULL)
    {
        wc = 0;
        printf("wc = %d\n", wc);
    }
    else if ((sscanf(string, "%d", &w)) > 0)
    {
        wc = w;
        printf("wc = %d\n", wc);    
    } else w = 0;

    return 0;
}

This is a sample program of course, it first searches the string for a "." to verify if the number could be float and discards it in such a case, then tries to read an integer if no "." are found.

Changed thanks to ameyCU's suggestion

Reference page for sscanf

Upvotes: 1

Houbie
Houbie

Reputation: 1517

How about strtol?

This gives a clear return value if something goes wrong, i think this is what you're looking for

http://www.cplusplus.com/reference/cstdlib/strtol/

Upvotes: 1

Related Questions