Shouldn't *argv[1] return the value of the second char in the array?
Look at the signature:
int main(int argc, char *argv[])
Here, argv
is an array ([]
) of pointers (*
) to char
. So argv[1]
is the second pointer in this array. It points to the first argument given at the command line. argv[0]
is reserved for the name of the program itself. Although this can also be any string, the name of the program is put there by convention (shells do this).
If you just dereference a pointer, you get the value it points to, so *argv[1]
will give you the first character of the first argument. You could write it as argv[1][0]
, they're equivalent. To get the second character of the first argument, you'd write argv[1][1]
.
An important thing to note here is that you can never pass an array to a function in C. The signature above shows an array type, but C automatically adjusts array types to pointer types in function declarations. This results in the following declaration:
int main(int argc, char **argv)
The indexing operator ([]
) in C works in terms of pointer arithmetics: a[x]
is equivalent to *(a+x)
. The identifier of an array is evaluated as a pointer to the first array element in most contexts (exceptions include the sizeof
operator). Therefore indexing works the same, no matter whether a
is an array or a pointer. That's why you can treat argv
very similar to an array.
Addressing your "core" problem: You will always have strings in argv
and you want numeric input, this means you have to convert a string to a number. There are already functions doing this. A very simple one is atoi()
, you can use it like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2)
{
// use program name in argv[0] for error message:
fprintf(stderr, "Usage: %s [number]\n", argv[0]);
return EXIT_FAILURE;
}
int i = atoi(argv[1]);
printf("Argument is %d.\n", i);
return EXIT_SUCCESS;
}
This will give you 0
if the argument couldn't be parsed as a number and some indeterminate value if it overflows your int
. In cases where you have to make sure the argument is a valid integer, you could use strtol()
instead (note it converts to long
, not int
, and it can handle different bases, so we have to pass 10
for decimal):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char **argv)
{
if (argc != 2)
{
// use program name in argv[0] for error message:
fprintf(stderr, "Usage: %s [number]\n", argv[0]);
return EXIT_FAILURE;
}
errno = 0; // reset error number
char *endptr; // this will point to the first character not read by strtol
long i = strtol(argv[1], &endptr, 10);
if (errno == ERANGE)
{
fprintf(stderr, "This number is too small or too large.\n");
return EXIT_FAILURE;
}
else if (endptr == argv[1])
{
// no character was converted. This also catches the case of an empty argument
fprintf(stderr, "The argument was not a number.\n");
return EXIT_FAILURE;
}
else if (*endptr)
{
// endptr doesn't point to NUL, so there were characters not converted
fprintf(stderr, "Unexpected characters in number.\n");
return EXIT_FAILURE;
}
printf("You entered %ld.\n", i);
return EXIT_SUCCESS;
}