Question Details

No question body available.

Tags

c linux command-line

Answers (2)

Accepted Answer Available
Accepted Answer
February 5, 2026 Score: 3 Rep: 234,218 Quality: Expert Completeness: 60%

When you call your program as ./password_checker abc -f, the -f option is missing its argument. Because your option string starts with :, this value will be returned if -f is given without an argument with optopt being set to f. You'll need to add a case for this.

Also, there's no break statement in the f case, so execution falls through to the ? case and runs that if the -f option is passed with an argument.

You'll need to add a case for : and add the break to the -f case.

while((option = getopt(argc, argv, ":hf:")) != -1){
    switch(option){
        case 'h':
            help();
            return 0;
        case 'f':
            //read file name from -f flag
            filename = optarg;
            fflag = 1;
            break;
        case ':':
            fprintf(stderr, "Missing argument for option -%c\n",optopt);
            return 1;   
        case '?':
            fprintf(stderr, "Unknown option -%c\n",optopt);
            return 1;   
    }
}

As a side note, rather than using a separate fflag variable, you could instead initialize filename to NULL and check for that.

February 5, 2026 Score: 4 Rep: 9,158 Quality: Medium Completeness: 80%

Let's start with a simple optstring. The getopt man page says:

If such a character is followed by a colon, the option requires an argument

You have the colon as the first character in your optstring. Remove that, and you'll get the error message that -f requires an argument.

The code then will complain "./a.out: option requires an argument -- 'f'" plus "Unknown option -f" when you don´t pass a file name. This is because getopt prints its own error messages. From the man page:

By default, getopt() prints an error message on standard error, places the erroneous option character in optopt, and returns '?' as the function result.

To avoid that and do your own error handling, you can set opterr = 0:

If the caller has set the global variable opterr to zero, then getopt() does not print an error message.

It may also complain "Unknown option -f" when you do pass a file name. This is because you're missing a break on the case 'f':, and without a break execution continues on the next case. This didn't matter for the other cases because you returned from the function anyway.

Here's a minimal example that accepts -h without arguments and requires an argument for -f:

#include
#include

int main(int argc, char argv[]) { int option; char filename;

opterr = 0; while ((option = getopt(argc, argv, "hf:")) != -1) { switch(option) { case 'h': printf("help"); return 0; case 'f': filename = optarg; printf("file name is %s\n", filename); break; case '?': fprintf(stderr, "Unknown option -%c\n", optopt); return 1; } }

return 0; }

Examples:

$ gcc -Wall mcve.c
$ ./a.out -f
Unknown option -f
$ ./a.out -f somefile.txt
file name is somefile.txt

"Unknown option -f" is somewhat misleading so let's fix that. This is also coming back to having a colon as the first character in optstr. The man page explains:

If the first character [...] of optstring is a colon (':'), then getopt() likewise does not print an error message. In addition, it returns ':' instead of '?' to indicate a missing option argument.

So if you don't want to set opterr, you can use the :... as optstring, but then you need to check for :, not ?. You can check whether the option is a valid one and vary the error message based on that:


#include
#include
#include

int main(int argc, char argv[]) { int option; char filename;

char* optstring = ":hf:"; while ((option = getopt(argc, argv, optstring)) != -1) { switch(option) { case 'h': printf("help"); return 0; case 'f': filename = optarg; printf("file name is %s\n", filename); break; case '?': fprintf(stderr, "Unknown option -%c\n", optopt); return 1; case ':': fprintf(stderr, "Option -%c misses an argument\n", optopt); return 1; } }

return 0; }

This is useful for custom / translated error messages.

If you're using GNU getopt, you can also use :: to indicate an optional argument to an option. Again from the man page:

Two colons mean an option takes an optional arg; if there is text in the current argv-element (i.e., in the same word as the option name itself, for example, "-oarg"), then it is returned in optarg, otherwise optarg is set to zero.

With that you could use hf:o:: as the optstring, and add this case:

            case 'o':
                printf("option o given with %s\n", optarg);
                break;

Output:

$ ./a.out -oopt
option o given with opt

That allows you to pass -oopt and retrieve "opt" as the optional argument to the -o flag.