0

I have to check that argv[1] is an int, otherwise, print "error".

Any tips? What I have so far clearly is not correct.

int main(int argc, char *argv[])
{  
    if (argc == 2 && (int) argv[1] > 0)
    {
        printf("Hello, %s\n", argv[1]);
    }
    else
    {
        printf("ERROR\n");
        return 1;
    }
}
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Make sure you add the `[cs50]` tag. Otherwise, many will not know what `string` is as that is not a standard C type. – David C. Rankin Jul 23 '20 at 04:49
  • Since `string` is required to be a compatible type, it's probably better to just use `char *argv[]` and make the code more general. – paxdiablo Jul 23 '20 at 04:53

3 Answers3

7

The argv array is an array of strings, you cannot usefully cast that to an integer since it will give you the integer variant of the pointer.

What you need to do is use a function like strtol to convert the string to a number. The following complete program contains a function that will do that for you:

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

int checkStrLong(char *num, long *pValue) {
    // Attempt conversion, base ten, get address of first invalid character.

    char *nextCh;
    long val = strtol (num, &nextCh, 10);

    // Reject empty string, ensure whole string was used.

    if ((nextCh == num) || (*nextCh != '\0'))
        return 0;

    // Pass back value.

    *pValue = val;
    return 1;
}

int main(int argc, char *argv[]) {
    int i;
    long val;

    int len, maxLen = 0;
    for (i = 1; i < argc; i++) {
        if ((len = strlen(argv[i])) > maxLen) {
            maxLen = len;
        }
    }

    for (i = 1; i < argc; i++) {
        if (checkStrLong(argv[i], &val)) {
            printf ("%-*s: %ld\n", maxLen, argv[i], val);
        } else {
            printf ("%-*s: <INVALID>\n", maxLen, argv[i]);
        }
    }
    return 0;
}

The following transcript shows it in action for a few test values:

pax> ./testprog 1 -7 42 314159 44.2 21guns hello one23 ""
1     : 1
-7    : -7
42    : 42
314159: 314159
44.2  : <INVALID>
21guns: <INVALID>
hello : <INVALID>
one23 : <INVALID>
      : <INVALID>
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
5

You should somehow convert string to int.

You could check this answer where they recommed using strtol(), which supports error checking.

From the man page:

The implementation may also set errno to EINVAL in case no conversion was performed (no digits seen, and 0 returned).

So basically you should check errno. If it equals to EINVAL, it means there were no numbers to convert.

Additionally, if you want to print the error set at errno, you could use perror().


It's a good practice to check the return value, know what each case may mean, and to print the error msg with perror() in case some error occurred. It's good for you, so you familiarize with the tools you're using, it makes the software more robust, and in case the user makes a mistake somewhere (or anything bad happens), the user will receive some feedback on it. Basically, it's a win-win-win situation ;)

89f3a1c
  • 1,430
  • 1
  • 14
  • 24
0

I like using sscanf for scenarios such as this...

int main(int argc, char** argv)
{
    int num;

    if ((argc != 2) || (sscanf(argv[1], "%d", &num) != 1)) {
        printf("ERROR\n");
        exit(1);
    }
    printf("%d\n", num);
    return 0;
}

We check if there are 2 args then we use sscanf to convert argv at 1 to an int and check if it is a number.