Search code examples
cfilenamescommand-line-argumentsgetopt

options using getopt in c


I want the put a sub-option in a string so that I can use it as a file name for reading a file:

char *nvalue = NULL;
char *dvalue = NULL;
char *input = NULL;
char inputfilename[] = "\"";
int ar;

int main(int argc, char *argv[])
{
   while ((ar = getopt(argc, argv, "hn:d:i:")) != -1)
      switch (ar)
      {
         case 'h':
            printf("something");
            break; /* added */
         case 'n':
            nvalue = optarg;
            if (isdigit(nvalue))
               stop = atoi(nvalue);
            else
               printf("something\n");
            break; /* added */
         case 'd':
            dvalue = optarg;
            if (!strcmp(dvalue, "FCFS")   || !strcmp(dvalue, "SSTF") ||
                !strcmp(dvalue, "C-SCAN") || !strcmp(dvalue, "LOOK"))
               ;
            else
               printf("Invalid type of disk scheduling policy entered.\n");
            break; /* added */
         case 'i':
            input = optarg;
            strcpy(inputfilename, optarg);
            printf("Filename :%s\n", inputfilename);
            break;
      }
   /* ... */
}

So on the command line if I input:

./foobar -i hello

then I should be able to read the file with:

FILE *file = fopen(inputfilename, "r" );

any suggestions? answers? thanks!


Solution

  • There are a number of problems with your code. I'm ignoring the absence of header files (assuming your code uses the correct ones so all functions have a prototype in scope before use). I'm also reformatting your code ruthlessly but without further comment.

    char *nvalue = NULL;
    char *dvalue = NULL;
    char *input = NULL;
    char inputfilename[] = "\"";
    

    This allocated an array of two bytes as inputfilename. I hate to think what's going to happen when you use it.

    int ar;
    

    There is every reason why this variable should be local to the main function and no reason visible for it to be a global variable. Unless you have a header declaring them, the other variables should also be static - assuming that you need to access their values outside of main() without a convenient way to pass them as locals. Avoid global variables whenever possible.

    int main(int argc, char *argv[])
    {
        while ((ar = getopt(argc, argv, "hn:d:i:")) != -1)
        {
            switch (ar)
            {
            case 'h':
                printf("something");
    

    Oops; no break, so the code drops through to the case 'n': code. C is not Pascal.

            case 'n':
                nvalue = optarg;
                if (isdigit(nvalue))
                    stop = atoi(nvalue);
    

    You haven't shown a declaration for stop. Unless you really need the string, you can do without nvalue, avoiding a global variable, which is always desirable.

                else
                    printf("something\n");
    

    Another missing break; I'm not going to point it out again.

            case 'd':
                dvalue = optarg;
                if (strcmp(dvalue, "FCFS")   == 0 ||
                    strcmp(dvalue, "SSTF")   == 0 ||
                    strcmp(dvalue, "C-SCAN") == 0 ||
                    strcmp(dvalue, "LOOK"    == 0)
                {
    

    I'd suggest a comment such as /* Nothing - dvalue is OK */. Or inverting the condition using De Morgan's theorem:

                if (strcmp(dvalue, "FCFS")   != 0 &&
                    strcmp(dvalue, "SSTF")   != 0 &&
                    strcmp(dvalue, "C-SCAN") != 0 &&
                    strcmp(dvalue, "LOOK"    != 0)
    

    You might even decide to encapsulate that test into a function which tests the value against each element of an array of codes.

                }
                else
                    printf("Invalid type of disk scheduling policy entered.\n");
    

    It would be courteous to provide a list of the acceptable values - which suddenly becomes another reason for having an array of valid values which you can use to generate the list. Very often, error messages should be reported on stderr (using fprintf()) rather than stdout.

            case 'i':
                input = optarg;
    

    This assignment is sufficient.

                strcpy(inputfilename, optarg);
    

    Unless the user types a single-character file name, you've just overflowed the inputfilename array. You really didn't need to make a copy of the argument unless you're going to modify the name (for example, to add or change the extension on the name).

                 //strcat(inputfilename,"\"");   
                 printf("Filename :%s\n", inputfilename);
            }
    

    You didn't include a default clause. Since ar will be assigned the value ? when the user-provided option is not recognized, this is normally your cue to provide a simple usage message and exit.