user13077054
user13077054

Reputation:

How can I have access into *argv[ ] in C?

Say that I have this part of code. If user does not enter the file names as command line arguments I want to ask him again so as to enter them now but as it seems I cannot have access in argv[1] and argv[2]. For example when the first scanf is executed segmentation fault occurs. But in this case how can I read the arguments and place them into argv[1] and argv[2]? Thanks in advance for your help!

int main (int argc, char **argv)
{
    if (argc != 3)
    {
        printf("You did not enter two files.\n");
        printf("You can now enter those two files.\n");
        printf("file 1: ");
        scanf("%s", argv[1]);
        printf("file 2: ");
        scanf("%s ", argv[2]);
    }

    printf("%s\n", argv[1]);
    printf("%s\n", argv[2]);

    FILE *file1 = fopen(argv[1], "r");
    FILE *file2 = fopen(argv[2], "r");
}

Upvotes: 0

Views: 2742

Answers (6)

Gribek
Gribek

Reputation: 201

A segmentation fault occurs because length of the argv array is determined when the user runs the program. If you run a program like this:

./programName

argv is only 1 element long. It's impossible to access argv[1] or argv[2] after that. Still, You can get the necessary data and save them in regular variables.

Upvotes: 0

klutt
klutt

Reputation: 31389

Placing them in argv is the wrong approach. Much better to do something like this:

int main (int argc, char **argv)
{
    char f1[255];
    char f2[255];
    if (argc != 3)
    {
        printf("You did not enter two files.\n");
        printf("You can now enter those two files.\n");
        printf("file 1: ");
        scanf("%s", f1);
        printf("file 2: ");
        scanf("%s ", f2);
    } else {
        strcpy(f1, argv[1]);
        strcpy(f2, argv[2]);
    }
    FILE *file1 = fopen(f1, "r");
    FILE *file2 = fopen(f2, "r");
}

You should avoid writing to argv. That's in general a bad idea.

Upvotes: 0

dbush
dbush

Reputation: 223927

You can't do this because argv[1] and argv[2] are NULL pointers (if they even exist in the array), so you can't access them.

You need to approach the problem from a different way.

Instead of trying to change members of argv, assign them to other variables that hold the file names.

int main (int argc, char **argv)
{
    char file1[100], file2[100];
    if (argc != 3)
    {
        printf("You did not enter two files.\n");
        printf("You can now enter those two files.\n");
        printf("file 1: ");
        scanf("%s", file1);
        printf("file 2: ");
        scanf("%s ", file2);
    } else {
        strcpy(file1, argv[1]);
        strcpy(file2, argv[2]);
    }

    printf("%s\n", file1);
    printf("%s\n", file2);

    FILE *file1 = fopen(file1, "r");
    FILE *file2 = fopen(file2, "r");
}

Note that I made some assumptions about the length of a filename. Adjust as necessary.

Upvotes: 0

mrksngl
mrksngl

Reputation: 109

Note that argv[1] and argv[2] are only valid if argc >= 3. Thus accessing them is of course wrong.

Then if you want to read the arguments from stdin, you must make sure that you have memory where those strings are kept. You might use something like

char filename1[20], filename2[20];
char *f1, *f2;
if (argc == 3) {
  f1 = argv[1];
  f2 = argv[2];
} else {
  f1 = filename1;
  f2 = filename2;
  /* add code to read into filename1 and filename2 */
}
/* use f1 and f2 */

You can see that I only reserved 20 bytes for each filename, which was arbitrary chosen by me. It is critical here to not write more than 20 bytes into those arrays (including the terminating NUL char), so you should not use scanf like this.

You can see that this is not really straight-forward in C so there is also not an answer that suites all purposes.

Edit: also be sure to never write into any argc[...] memory, as it is supplied from the system. Although not marked const I would rather consider it as such.

Upvotes: 0

bitmask
bitmask

Reputation: 34628

You don't. As the popular phrase goes, every problem in computer science can be solved by an extra layer of indirection. In this case the indirection is that you define a clean interface for opening a file and pass it a char const*. But this pointer doesn't have to be argv[1].

You have to malloc your own buffer (because none exists) and write to it. Using scanf("%s",...) for this purpose will likely create a buffer overrun as you cannot know in advance how large your buffer needs to be.

Edit: Every single answer given to you suggesting to use char buffer[NUMBER] as the buffer for scanf will blow up in your face.

Upvotes: 2

wkkuna
wkkuna

Reputation: 66

Argv is passed from console and you pass it while executing your program.

First, you have to compile it with, for example:

gcc program.c -o program

And then execute it with arguments, for example:

./program arg1 arg2

If you wish to wait for a user to enter parameters for your program through the console you should use regular variables.

Upvotes: 0

Related Questions