47

i have a piece of code like this:

int main (int argc, char *argv[]) 
{
   printf("%d\t",(int)argv[1]);
   printf("%s\t",(int)argv[1]);
}

and in shell i do this:

./test 7

but the first printf result is not 7, how can I get argv[] as a int? many thanks

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Michael
  • 545
  • 1
  • 5
  • 9
  • 3
    I know cnicutar already gave the answer, but it helps to understand what is going on. Do you know what argv[1] is exactly? I mean, can you explain why you get the output you get? – Mr Lister Mar 17 '12 at 08:25
  • In my opinion argv[0] is command itself and argv[1] is first parameter I input. In this case is 7. – Michael Mar 17 '12 at 13:27
  • Yes, that's right, but what is it? What type? What can you do with it? Why do you get the output you get in the above example? Can you do addition or multiplication with it, and what if the user doesn't type a number, but `./test seven` or something? – Mr Lister Mar 17 '12 at 13:57

5 Answers5

52

argv[1] is a pointer to a string.

You can print the string it points to using printf("%s\n", argv[1]);

To get an integer from a string you have first to convert it. Use strtol to convert a string to an int.

#include <stdio.h>
#include <errno.h>   // for errno
#include <limits.h>  // for INT_MAX, INT_MIN
#include <stdlib.h>  // for strtol


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

    errno = 0;
    long conv = strtol(argv[1], &p, 10);

    // Check for errors: e.g., the string does not represent an integer
    // or the integer is larger than int
    if (errno != 0 || *p != '\0' || conv > INT_MAX || conv < INT_MIN) {
        // Put here the handling of the error, like exiting the program with
        // an error message
    } else {
        // No error
        num = conv;
        printf("%d\n", num);
    }
}
sigjuice
  • 28,661
  • 12
  • 68
  • 93
ouah
  • 142,963
  • 15
  • 272
  • 331
40

This Q&A is about plain C, not C++. (I don't know whether the answer is different for C++, but you may need to include cstring or so.)

Basic usage

The "string to long" (strtol) function is standard for this ("long" can hold numbers much larger than "int"). This is how to use it:

#include <stdlib.h>

long arg = strtol(argv[1], NULL, 10);
// string to long(string, endpointer, base)

Since we use the decimal system, base is 10. The endpointer argument will be set to the "first invalid character", i.e. the first non-digit. If you don't care, set the argument to NULL instead of passing a pointer, as shown.

Error checking (1)

If you don't want non-digits to occur, you should make sure it's set to the "null terminator", since a \0 is always the last character of a string in C:

#include <stdlib.h>

char* p;
long arg = strtol(argv[1], &p, 10);
if (*p != '\0') // an invalid character was found before the end of the string

Error checking (2)

As the man page mentions, you can use errno to check that no errors occurred (in this case overflows or underflows).

#include <stdlib.h>
#include <errno.h>

char* p;
errno = 0; // not 'int errno', because the '#include' already defined it
long arg = strtol(argv[1], &p, 10);
if (*p != '\0' || errno != 0) {
    return 1; // In main(), returning non-zero means failure
}

// Everything went well, print it as 'long decimal'
printf("%ld", arg);

Error checking (3)

As sigjuice pointed out, the function will happily ignore empty strings and not set errno. Our null byte check will also not trigger because a zero-length string has a \0 right at the start. So we need another import and another check:

#include <string.h>

if (strlen(argv[1]) == 0) {
    return 1; // empty string
}

Convert to integer

So now we are stuck with this long, but we often want to work with integers. To convert a long into an int, we should first check that the number is within the limited capacity of an int. To do this, we add a second if-statement, and if it matches, we can just cast it.

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

if (strlen(argv[1]) == 0) {
    return 1; // empty string
}
char* p;
errno = 0; // not 'int errno', because the '#include' already defined it
long arg = strtol(argv[1], &p, 10);
if (*p != '\0' || errno != 0) {
    return 1; // In main(), returning non-zero means failure
}

if (arg < INT_MIN || arg > INT_MAX) {
    return 1;
}
int arg_int = arg;

// Everything went well, print it as a regular number
printf("%d", arg_int);

To see what happens if you don't do this check, test the code without the INT_MIN/MAX if-statement. You'll see that if you pass a number larger than 2147483647 (231), it will overflow and become negative. Or if you pass a number smaller than -2147483648 (-231-1), it will underflow and become positive. Values beyond those limits are too large to fit in an integer.

Full example

#include <stdio.h>  // for printf()
#include <stdlib.h> // for strtol()
#include <errno.h>  // for errno
#include <limits.h> // for INT_MIN and INT_MAX
#include <string.h>  // for strlen

int main(int argc, char** argv) {
    if (strlen(argv[1]) == 0) {
        return 1; // empty string
    }
    char* p;
    errno = 0; // not 'int errno', because the '#include' already defined it
    long arg = strtol(argv[1], &p, 10);
    if (*p != '\0' || errno != 0) {
        return 1; // In main(), returning non-zero means failure
    }

    if (arg < INT_MIN || arg > INT_MAX) {
        return 1;
    }
    int arg_int = arg;

    // Everything went well, print it as a regular number plus a newline
    printf("Your value was: %d\n", arg_int);
    return 0;
}

In Bash, you can test this with:

cc code.c -o example  # Compile, output to 'example'
./example $((2**31-1))  # Run it
echo "exit status: $?"  # Show the return value, also called 'exit status'

Using 2**31-1, it should print the number and 0, because 231-1 is just in range. If you pass 2**31 instead (without -1), it will not print the number and the exit status will be 1.

Beyond this, you can implement custom checks: test whether the user passed an argument at all (check argc), test whether the number is in the range that you want, etc.

Luc
  • 5,339
  • 2
  • 48
  • 48
  • 1
    Better explained than the accepted answer. At least, for starters like me. – Dinei Apr 22 '17 at 16:19
  • `./example "" Your value was: 0 ` – sigjuice Aug 07 '21 at 22:00
  • @sigjuice Good catch, I guess we need another check for zero-length inputs, is that the correct way to handle this or is something else wrong? (You'd think the strtol function would just set errno if there is, y'know, an error, but then again, this *is* C after all...) – Luc Aug 09 '21 at 23:12
14

You can use strtol for that:

long x;
if (argc < 2)
    /* handle error */

x = strtol(argv[1], NULL, 10);

Alternatively, if you're using C99 or better you could explore strtoimax.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
6

You can use the function int atoi (const char * str);.
You need to include #include <stdlib.h> and use the function in this way:
int x = atoi(argv[1]);
Here more information if needed: atoi - C++ Reference

Angie Quijano
  • 4,167
  • 3
  • 25
  • 30
  • 1
    Never use `atoi()`. It provides no way to do any error checking - at all. Since it returns `int`, it always returns a value that could be a valid input. The only way to check if `atoi()` returns a correct answer is to use some other method to convert the input value to a number and compare the values. See https://stackoverflow.com/questions/17710018/why-shouldnt-i-use-atoi – Andrew Henle Jul 24 '19 at 09:21
1
/*

    Input from command line using atoi, and strtol 
*/

#include <stdio.h>//printf, scanf
#include <stdlib.h>//atoi, strtol 

//strtol - converts a string to a long int 
//atoi - converts string to an int 

int main(int argc, char *argv[]){

    char *p;//used in strtol 
    int i;//used in for loop

    long int longN = strtol( argv[1],&p, 10);
    printf("longN = %ld\n",longN);

    //cast (int) to strtol
    int N = (int) strtol( argv[1],&p, 10);
    printf("N = %d\n",N);

    int atoiN;
    for(i = 0; i < argc; i++)
    {
        //set atoiN equal to the users number in the command line 
        //The C library function int atoi(const char *str) converts the string argument str to an integer (type int).
        atoiN = atoi(argv[i]);
    }

    printf("atoiN = %d\n",atoiN);
    //-----------------------------------------------------//
    //Get string input from command line 
    char * charN;

    for(i = 0; i < argc; i++)
    {
        charN = argv[i];
    }

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

}

Hope this helps. Good luck!

pewpew
  • 700
  • 2
  • 9
  • 32