Search code examples
ccommand-line-argumentsargvargc

Why aren't there any passed arguments to argv[]?


So, I noticed that my argc is always 1 as I will always get the message Error: missing command line arguments!, but as stated in code I am using argv[1] and argv[2] to read the files names.

Shouldn't automatically argc be 3 in this case, and to be able to pass that error?

Notes:

  1. If I am not using if (argc < 2) statement, after I enter the name for the output file my program crushes.
  2. For the input file I already have this one created in the project folder, so I just enter the name of that file.

This is the code:

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

FILE *IN, *OUT;

int main(int argc, char* argv[])
{
    if (argc < 2) 
    {
        printf("Error: missing command line arguments!\n");
        return 1;
    }

    printf("Enter the name of the file with the input data: ");
    scanf("%s", argv[1]);

    printf("\nEnter the name of the file for the output data: ");
    scanf("%s", argv[2]);

    IN = fopen(argv[1], "r");
    OUT = fopen(argv[2], "w");  

    fclose(IN);
    fclose(OUT);

    return 0;
}

Solution

  • You're complete mis-understanding the purpose of argc and argv. They are supposed to receive the supplied command line argument (program parameters) before the program startup, not supposed to hold the scannned input at runtime.

    Quoting C11, chapter §5.1.2.2.1,

    If they are declared, the parameters to the main function shall obey the following constraints:

    — The value of argc shall be nonnegative.

    argv[argc] shall be a null pointer.

    — If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup. The intent is to supply to the program information determined prior to program startup from elsewhere in the hosted environment.

    and

    If the value of argc is greater than zero, the string pointed to by argv[0] represents the program name; argv[0][0] shall be the null character if the program name is not available from the host environment. If the value of argc is greater than one, the strings pointed to by argv[1] through argv[argc-1] represent the program parameters.

    To elaborate, when a program is invoked like

    ./a.out three total arguments
    

    then, in your program

    • argc will be 4
    • argv[0] will be ./a.out
    • argv[1] will be three
    • argv[2] will be total
    • argv[3] will be arguments
    • argv[4] will be NULL (see the property for argv[argc] above)

    (To generalize, argv[1] - argv[argc-1] will hold the supplied arguments, argv[argc] will be NULL)

    You don't need to explicitly scan the input, those values will be populated from the host environment.

    On the other hand, you cannot just invoke the program like

    ./a.out
    

    and exptect argc to be 3 (or any other value, other than 1, for that matter) and argv[1] - argv[n-1] to be valid because at compile-time the invokes program has no way to know that you plan to supply some values at runtime. It's not clairvoyant.