Question: So I have an assignment to figure out whether a number on the command line is either an integer or a double.

I have it mostly figured it out by doing:

```
sscanf(argv[x], "%lf", &d)

```

Where "d" is a double. I then cast it to an int and then subtract "d" with itself to check to see if it is 0.0 as such.

```
d - (int)d == 0.0

```

My problem is if the command line arguments contains doubles that can be technically classified as ints.

I need to classify 3.0 as a double whereas my solution considers it an int. 
For example initializing the program.

```
a.out 3.0

```

I need it to print out

```
"3.0 is a double"

```

However right now it becomes

```
"3 is an int." 

```

What would be a way to check for this? I did look around for similar problems which led me to the current solution but just this one edge case I do not know how to account for.

Thank you.

Answer: 
To test if a string will covert to a `int` and/or `double` (completely, without integer overflow, without *undefined behavior*), call `strtol()/strtod()`. [@Tom Karzes](https://stackoverflow.com/questions/46250408/how-to-check-an-edge-case-in-taking-command-line-argument-in-c-and-evaluating-to/46252356#comment79464780_46250408)

The trouble with a `sscanf()` approach is that the result is *undefined behavior* (UB) on overflow. To properly detect, use `strtol()/strtod()`.

```
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>

bool is_int(const char *src) {
  char *endptr;
  // Clear, so it may be tested after strtol().
  errno = 0;
  // Using 0 here allows 0x1234, octal 0123 and decimal 1234.
  // or use 10 to allow only decimal text.
  long num = strtol(src, &endptr, 0 /* or 10 */);

#if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
  if (num < INT_MIN || num > INT_MAX) {
    errno = ERANGE;
  }
#endif

  return !errno && endptr > src && *endptr == '\0';
}

bool is_double(const char *src) {
  char *endptr;
  // Clear, so it may be tested after strtod().
  strtod(src, &endptr);

  // In this case, detecting over/underflow IMO is not a concern.
  return endptr > src && *endptr == '\0';
}

```
It is not entirely clear what the specific expectations are for your program, but it has at least something to do with the *form* of the input, since "3.0" must be classified as a double. If the form is *all* it should care about, then you should not try to convert the argument strings to numbers at all, for then you will run into trouble with unrepresentable values. In that case, you should analyze the character sequence of the argument to see whether it matches the pattern of an integer, and if not, whether it matches the pattern of a floating-point number.

For example:

```
int main(int argc, char *argv[]) {
    for (int arg_num = 1; arg_num < argc; arg_num++) {
        char *arg = argv[arg_num]; 
        int i = (arg[0] == '-' || arg[0] == '+') ? 1 : 0;  // skip any leading sign

        // scan through all the decimal digits
        while(isdigit(arg[i])) {
            ++i;
        }

        printf("Argument %d is %s.\n", arg_num, arg[i] ? "floating-point" : "integer");
    }
}

```

That makes several assumptions, chief among them:

* the question is strictly about form, so that the properties of your system's built-in data types (such as `int` and `double`) are not relevant.
* each argument will have the form of either an integer or a floating-point number, so that eliminating "integer" as a possibility leaves "floating-point" as the only alternative. If "neither" is a possibility that must also be accommodated, then you'll also need to compare the inputs that do not have integer form to a pattern for floating-point numbers, too.
* only decimal (or smaller radix) integers need be accommodated -- not, for example, hexadecimal inputs.

Under those assumptions, particularly the first, it is not just unnecessary but *counterproductive* to attempt to convert the arguments to one of the built-in numeric data types, because you would then come to the wrong conclusion about arguments that, say, are not within the bounds of representable values for those types.

For example, consider how the program should classify "9000000000". It has the form of an integer, but supposing that your system's `int` type has 31 value bits, that type cannot accommodate a value as large as the one the string represents.