user5987642
user5987642

Reputation:

How to print argv arguments from main function in C?

So I just learnt that we can give two arguments into main function namely "argc" and "argv. However I am not able to understand what argv is in this: int main(int argc, char* argv[]);

Is argv an array of characters? or is it an array of pointers pointing to characters? Either way I am looking for a way to print out the arguments that the user passes to this program. This is the code the I wrote, but it's not printing the argv's so to speak. What's wrong in it? I guess it's my understanding of argv that's making this code incorrect.

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=0;i<argc-1;i++)
    {
        printf("%s",*argv[i]);
    }
    return 0;
}

After the suggestions that I got from answers, I corrected my code as follows.

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=1;i<argc;i++)
    {
        printf("%s",argv[i]);
    }
    return 0;
}

And I am using Ubuntu Linux in VMWare on my windows 8.1 pc. This is the output that I am getting. It's just printing argc and after that nothing. What's the problem? Is it the way I am compiling it or something in Linux terminal?

The snapshot of my terminal

In the above figure, I want the numbers 2,4,5,3 to be printed again, but they are not getting printed.

Thanks.

Upvotes: 23

Views: 119659

Answers (7)

3442
3442

Reputation: 8576

Let's explain things step by step. First of all, when you invoke your program by calling something like...

./my-program arg0 arg1 arg2

You're passing it a series of three arguments, right? And each argument is a string, right? Now, the main function, can have one of two prototypes, as specified by the C standard...

int main(); // Let's not worry about this for now
int main(int argc, char **argv);

The idea is that main is able to handle the arguments that you provided. argc provides the number of arguments. If you noticed, while passing three arguments, argc is 4! This happens because a first argument is passed before all others, ./my-program, and lets your program recognize itself.

Now, what does char **argv mean? Something of the form X* is a pointer to X, right? So, char * is a pointer to char, and char ** is a pointer to pointer to char. In C, a string is simply a zero-terminated array of char, and an array can be "degraded" into a pointer. This means that argv is an array of strings, the first of which, argv[0], is the program's name.

Now, the C standard allows you to write any "compatible" prototype for main. For instance, you can write any of these...

int main(int argc, const char *const argv[]);
int main(int argc, const char *argv[])
int main(int argc, const char **argv);
int main(int argc, const char *const *const argv);

You don't need to understand what they all mean now, just that argv is an array of strings, and that you should never modify strings as the original main prototype appears to trust you. Now, knowing that arguments start at argv[1], your code...

for(int i=0;i<argc-1;i++)

Means: "For each i in the range of 0 through argc - 1".

    printf("%s",*argv[i]);

Means: "Print the first character of the ith element of argv". Why would this be wrong? First of all, you're printing a char, and telling printf that it is a string. This has undefined behavior. Then, you're iterating over the first ith elements of argv. This means that the first, "non-argument" element will be included in the mix, and the last argument won't be. To solve it, write something like...

for(int i = 1; i < argc; i++)

Means: "For each i in the range from 1 up to argc".

    printf("%s", argv[i]);

Means: "Print the ith element of argv to stdout.

Upvotes: 30

Kidus
Kidus

Reputation: 474

argv is a NULL terminated array of strings. So one doesn't even need argc to print all the arguments passed to the main function. So if argv points to NULL then that's the end of the arguments passed.

So to sum it up, you can do this with a simple while loop, using only argv:

    while (*argv != NULL)
    {
            printf("%s\n", *argv);
            argv++;
    }

Upvotes: 6

haccks
haccks

Reputation: 106012

Is argv an array of characters? or is it an array of pointers pointing to characters?

argv is a pointer to pointer to char. When a list of arguments are passed through command line then an array of char pointers are created and each of these pointers points to each of these arguments, stored in the form of strings, along with the program name. argv points to the first pointer of this char * array. Therefore, argv[i] is a pointer to char.

                           +--------------------------+
              +----+  +--> | argument 1 (program name)|
argv[0]+----> |    |  |    +--------------------------+
              |  +----+
              +----|       +--------------------------+
              |  +-------> |       argument 2         |
              |    |       +--------------------------+
              +----+
              |  +----+    +--------------------------+
              |    |  +--> |       argument 3         |
              +----+       +--------------------------+
           "char *" array

You need to change

printf("%s",*argv[i]);  

to

printf("%s",argv[i]);  

*argv[i] is of type char. %s expects a type of char *.

Upvotes: 7

grek40
grek40

Reputation: 13438

Regarding

Is argv an array of characters? or is it an array of pointers pointing to characters?

argv is an array of c-strings (where each c-string is a pointer to characters). Consider the following command line:

$ your-executable arg1 "arg2 with space"

It would result in an array of strings with the following content (pseudo code)

argv[0] EQUALS "your-executable"
argv[1] EQUALS "arg1"
argv[2] EQUALS "arg2 with space"

As others mentioned, remove the * from printf("%s", *argv[i]); and fix your loop condition if you want to print all arguments

Upvotes: -1

Ruslan
Ruslan

Reputation: 19120

In your edited question you have fixed your main problem. Now notice that your prompt looks like

./mygrep245YourName@ubuntu:~/test$

Here ./mygrep245 is your output after you printed "5\n". You forgot to print line feeds, thus all the output and the subsequent shell output has been concatenated as it is. And the last argument 3 wasn't printed because you put i<argc-1 instead of i<argc or i<=argc-1 in your loop condition.

Upvotes: 3

Rahul Tripathi
Rahul Tripathi

Reputation: 172418

You can refer the document:

As you can see, main now has arguments. The name of the variable argc stands for "argument count"; argc contains the number of arguments passed to the program. The name of the variable argv stands for "argument vector". A vector is a one-dimensional array, and argv is a one-dimensional array of strings. Each string is one of the arguments that was passed to the program.

If you need to print it simply remove the * and try this:

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=0;i<argc-1;i++)
    {
        printf("%s",argv[i]);   //remove * from here
    }
    return 0;
}

Upvotes: 1

MikeCAT
MikeCAT

Reputation: 75062

char *argv[] is pointer to pointer to char because arrays in function arguments are automatically converted to pointer pointing at elements of the array.

You invoked undefined behavior by passing data having wrong type to printf(): %s expects char*, but you passed char (converted to int for variable number arguments).

Remove the extra * o dereference the pointer.

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=0;i<argc-1;i++)
    {
        printf("%s",argv[i]);
    }
    return 0;
}

Also you may want i<argc instead of i<argc-1. Why not print the last argument?

Upvotes: 4

Related Questions