getopt() function analysis and command line analysis

When running executable programs under Linux, it is generally necessary to take specific parameters to specify the operation mode. The passed in parameter content is parsed by using getopt() function, and its header file is < unistd h>.

Let's introduce the prototype of getopt in detail:

int getopt(int argc,char * const argv[ ],const char * optstring);

The parameters argc and argv represent the number and content of parameters respectively, and the parameter optstring is an option string.

The global variables set by getopt() include:

  • extern char *optarg;
  • extern int optind, opterr, optopt;
  • optarg -- pointer to the current option parameter (if any).  
  • optind -- the index of the next argv pointer when getopt() is called again.
  • opterr -- whether to output the error information to stderr. If it is 0, it means no output.
  • optopt -- an option that is not in the option string optstring.

Concept of options and parameters:

  1. Single character, indicating options; (for example, g + + - O main main.cpp - std=c++11, where o is the option on the command line, and the following main is the parameter of the option.)
  2. A single character followed by a colon: indicates that the option must be followed by a parameter. Parameters are immediately followed by options or separated by spaces. The pointer of this parameter is assigned to optarg.
  3. A single character followed by two colons indicates that the option must be followed by a parameter. Parameters must be immediately followed by options and cannot be separated by spaces. The pointer of this parameter is assigned to optarg.

Definition of short parameters:

getopt() uses the string referred to by optstring as a short parameter list. For example, "1ac:d::" is a short parameter list. A short parameter is defined as a '-' followed by a letter or number. For example, - a, -b is a short parameter. Each number or letter defines a parameter.  

There are three types of short parameters in getopt definition:

  1. A parameter without a value is defined as the parameter itself.
  2. A parameter that must have a value is defined by adding a colon after the parameter itself.
  3. The parameter of optional value is defined by adding two colons after the parameter itself.

Take "1ac:d::" as an example, where 1,a is a parameter without value, c is a parameter with value, and d is a parameter with optional value.

In the actual call, '- 1 - A - C cvalue - D', '1 - A - C cvalue - ddvalue', '1A - ddvalue - C cvalue' are all legal. matters needing attention:

  1. Parameters without values can be concatenated. For example, 1 and a are parameters without values. They can be written separately from - 1 -a, or concatenated with - 1a or - a1.
  2. The parameters are in no order. The parsing results of '- 1a -c cvalue -ddvalue' and '- d -c cvalue -a1' are the same.
  3. Note that there can be no space between the value of the parameter of the optional value and the parameter. It must be written in the format of - ddvalue. If it is written in the format of - d dvalue, there will be a parsing error.

 

Test program 1: analyze the input ip,port and msg:

#include <iostream>
#include <unistd.h>
#include <string>

using namespace std;

//Resolve ip, port, msg
void testFun1(int argc, char *argv[])
{
    std::string ip = "127.0.0.1";
	int port = 8080;
	std::string msg = "Hello World";
	
	int opt;
    const char *str = "i:p:m:";
    while ((opt = getopt(argc, argv, str)) != -1)
    {
        switch (opt)
        {
        case 'i':
        {
            ip = optarg;
            break;
        }
        case 'p':
        {
            port = atoi(optarg);
            break;
        }
        case 'm':
        {
            msg = optarg;
            break;
        }
        default:
            break;
        }
    }
	cout<<"ip: "<<ip<<endl;
	cout<<"port: "<<port<<endl;
	cout<<"msg: "<<msg<<endl;
}

int main(int argc, char *argv[])
{
	testFun1(argc,argv);
	//testFun2(argc,argv);
    return 0;
}

Execution result:

[root@192 main Function command line parsing]# ./main
ip: 127.0.0.1
port: 8080
msg: Hello World
[root@192 main Function command line parsing]# ./main -i 10.43.33.115 -p 8888 -m Test
ip: 10.43.33.115
port: 8888
msg: Test

 

Test program 2, parse the input "abcde":

#include <iostream>
#include <unistd.h>
#include <string>

using namespace std;

//Parsing 2ab:c:de::
void testFun2(int argc, char *argv[])
{

	int opt;
    const char *str = "2ab:c:de::";
    while ((opt = getopt(argc, argv, str)) != -1)
    {
        switch (opt)
        {
            case '2':
				cout<<"HAVE option: -2"<<endl;
                break;
			case 'a':
				cout<<"HAVE option: -a"<<endl;
                break;
            case 'b':
                cout<<"HAVE option: -b"<<endl;
				cout<<"The value of -b is "<<optarg<<endl;
				break;
			case 'c':
				cout<<"HAVE option: -c"<<endl;
                cout<<"The value of -c is "<<optarg<<endl; 
                break;
            case 'd':
                cout<<"HAVE option: -d"<<endl;
				 break;
			case 'e':
				cout<<"HAVE option: -e"<<endl;
                cout<<"The value of -e is "<<optarg<<endl;
                break;
			default:
				break;
        }
    }
}


int main(int argc, char *argv[])
{
	//testFun1(argc,argv);
	testFun2(argc,argv);
    return 0;
}

Execution result:

[root@192 main Function command line parsing]# ./main -a -b 123 -c 456 -d -e 555
HAVE option: -a
HAVE option: -b
The value of -b is 123
HAVE option: -c
The value of -c is 456
HAVE option: -d
HAVE option: -e
The value of -e is [root@192 main Function command line parsing]# ./main -b 123 -c 456 -d -e555 -a2
HAVE option: -b
The value of -b is 123
HAVE option: -c
The value of -c is 456
HAVE option: -d
HAVE option: -e
The value of -e is 555
HAVE option: -a
HAVE option: -2

 

Tags: C++

Posted by alex57 on Tue, 03 May 2022 19:26:41 +0300