Search code examples
cgetopt

Program in C to read arguments


I started to learn C and I want to create a program which will take 2 obligatory arguments and 1 optional. ` This question may sound elementary but I have difficulty in understanding it. So basically what I want to do is to call the program like this:

myfile -n name -a age -g grade 

So when I call it this will be valid: myfile john 22 20 Name and age are obligatory. So name is a string, age is a number between 0 and 100. And grade is optional and can be a number. If it isn't defined then the value of it will be 0.

I tried to do it like this:

int main(int argc, char **argv){

    FILE *fp;
    char *filename = "student.txt";

    char name;
    int age, grade;
    if( (fp = fopen(filename, "w")) == NULL) {
        // show error 
        printf("Error."); 
     }
    if(argc!=2)
    {
        printf("Error.");
        return;
    }
    int ich = 0;
    while ((ich = getopt (argc, argv, "abc")) != -1) {
        switch (ich) {
            case 'a': 
                name = argv[1];
                break;
            case 'b': 
                age = argv[2];  
                if not (age >= 0 && age<100) {
                    printf("Error."); 
                }
                break;
            case 'c': 
                grade = argv[3];
                if (grade == NULL) {
                    grade = 0;
                }
                break;
            default: 
                break;
        }
  }

I want to use pointer optarg to have access to the arguments. I get this error warning: assignment makes integer from pointer without a cast [-Wint-conversion] I really need help. Please, can someone help me. I really need help. :(

Here is my tutorialspoint fiddle


Solution

  • After discussion etc, I created this code based on the code from the question:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    static char *arg0 = 0;
    static void usage(void)
    {
        fprintf(stderr, "Usage: %s -n name -a age [-g grade]\n", arg0);
        exit(EXIT_FAILURE);
    }
    
    int main(int argc, char **argv)
    {
        FILE *fp;
        char *filename = "student.txt";
        char *name = 0;
        int age = 0;
        int grade = 22;
    
        arg0 = argv[0];
    
        int opt;
        while ((opt = getopt(argc, argv, "n:a:g:")) != -1)
        {
            switch (opt)
            {
            case 'n':
                name = optarg;
                break;
            case 'a':
                age = atoi(optarg);
                if (age <= 0 || age >= 100)
                {
                    fprintf(stderr, "Age '%s' out of range 1..99\n", optarg);
                    usage();
                }
                break;
            case 'g':
                grade = atoi(optarg);
                break;
            default:
                break;
            }
        }
    
        if (name == 0)
        {
            fprintf(stderr, "You did not specify a name\n");
            usage();
        }
        if (age == 0)
        {
            fprintf(stderr, "You did not specify an age\n");
            usage();
        }
        if (optind != argc)
        {
            fprintf(stderr, "Extra arguments provided (starting with '%s')\n", argv[optind]);
            usage();
        }
    
        // check if file exists
        if ((fp = fopen(filename, "w")) != NULL)
        {
            printf("%s, %d, %d\n", name, age, grade);
            fprintf(fp, "%s, %d, %d\n", name, age, grade);
            fclose(fp);
        }
        else
        {
            fprintf(stderr, "Failed to open file '%s' for writing\n", filename);
            return 1;
        }
        return 0;
    }
    

    Example runs

    Program name: go59

    $ go59
    You did not specify a name
    Usage: go59 -n name -a age [-g grade]
    $ go59 -n Rita
    You did not specify an age
    Usage: go59 -n name -a age [-g grade]
    $ go59 -n Rita -a 23
    Rita, 23, 22
    $ go59 -n Andromeda -a 23 -g 97
    Andromeda, 23, 97
    $ go59 -n Andromeda -a 23 -g 97 apoplexy
    Extra arguments provided (starting with 'apoplexy')
    Usage: go59 -n name -a age [-g grade]
    $ go59 -n Andromeda -a 23 -g 97 --
    Andromeda, 23, 97
    $ go59 -n Andromeda -a -1 -g 97 --
    Age '-1' out of range 1..99
    Usage: go59 -n name -a age [-g grade]
    $ go59 -n Andromeda -a 0 -g 97 --
    Age '0' out of range 1..99
    Usage: go59 -n name -a age [-g grade]
    $
    

    Note that the code doesn't zap the student.txt file until it knows that the arguments it was given are valid enough.