In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)06/02 Report--
Summary: all UNIX ®programs, even those with a graphical user interface (graphical user interface,GUI), can accept and process command line options. For some programs, this is the main means of interacting with other programs or users. Having a reliable mechanism for handling complex command-line arguments will make your application better and more useful. But many developers spend their precious time writing their own command-line parsers instead of using getopt (), a library function specifically designed to ease the burden of command-line processing. Read this article to learn how to have getopt () record command parameters in the global structure so that they can be used throughout the program at any time later.
Introduction
In the early days of UNIX ®, its command line environment (the only user interface at the time) contained dozens of small text processing tools. These tools are very small and usually do a good job. These tools are linked through a long command pipeline, and the previous program passes its output to the next program as input, which is controlled by a variety of command-line options and parameters.
It is this aspect of UNIX that makes it an extremely powerful environment for processing data based on this article, which is one of its initial uses in a corporate environment. Enter some text at one end of the command pipeline and retrieve the processed output at the other end.
Command-line options and parameters control UNIX programs and tell them how to act. As a developer, you are responsible for discovering the user's intentions from the command line passed to the main () function of your program. This article demonstrates how to use the standard getopt () and getopt_long () functions to simplify command-line processing and discusses a technique for tracking command-line options.
Before we begin
The sample code included in this article (see download) was written in Eclipse 3.1 using the C development tool (C Development Tooling,CDT); the getopt_demo and getopt_long_demo projects are Managed Make projects, both built using CDT's program generation rules. Makefile is not included in the project, so if you need to compile the code outside of Eclipse, you can easily generate one yourself.
If you haven't tried Eclipse (see Resources), you should really give it a try-- it's an excellent integrated development environment (integrated development environment,IDE) with a big improvement with each new version. This is the work of "hardline" EMACS and Makefile developers.
Command Lin
One of the first obstacles encountered when writing a new program is how to deal with the command-line arguments that control its behavior. This includes a count of integers (usually called argc) and an array of pointers to strings (usually named argv) passed to your program's main () function from the command line. You can declare the annotated main () function in essentially the same way, as shown in listing 1.
Listing 1. Two ways to declare the main () function
Int main (int argc, char * argv []); int main (int argc, char * * argv)
The first way is to point to an array of char pointers, which now seems to be popular, slightly clearer than the second way, where pointers point to multiple pointers to char. For some reason, I spend more time in the second way, which may be due to my experience of struggling to learn C pointer in high school. Both methods are the same for all purposes and purposes, so you can use the one you like best.
When the program startup code of the C runtime library calls your main (), the command line has already been processed. The argc parameter contains the count values of the parameters, while the argv contains an array of pointers to those parameters. For the C runtime library, arguments is the name of the program, and anything after the program name should be separated by a space.
For example, if you run a program called foo with the parameter-v bar www.ibm.com, your argc will be set to 4Magneargv as shown in listing 2.
Listing 2. Contents of argv
Argv [0]-fooargv [1]-- vargv [2]-barargv [3]-www.ibm.com
A program has only one set of command-line arguments, so I want to store this information in the global structure of recording options and settings. Anything that is meaningful to the program to track can be recorded in this structure, and I will use the structure to help reduce the number of global variables. As I mentioned in my web service design article (see Resources), global variables are very unsuitable for threaded programming, so use them with caution.
The sample code demonstrates the command line processing of a hypothetical doc2html program. The doc2html program converts some type of document to HTML, which is controlled by user-specified command-line options. It supports the following options:
-Imure-keyword indexes are not created. -l lang-- is converted to the language specified using the language code lang. -o outfile.html-- writes the converted document to outfile.html instead of printing to standard output. -vMurt-provides details during conversion; can be specified multiple times to improve the diagnostic level. Another file name will be used as the input document.
You will also support-h and -? to print help messages to indicate the purpose of each option.
Simple command line processing: getopt ()
The getopt () function is located in the unistd.h system header file, and its prototype is shown in listing 3:
Listing 3. Getopt () prototype
Int getopt (int argc, char * const argv [], const char * optstring)
Given the number of command parameters (argc), the array pointing to them (argv), and the option string (optstring), getopt () returns the first option and sets some global variables. When the function is called again with the same parameters, it returns the next option and sets the corresponding global variable. If the identified option is no longer available,-1 is returned, and the task is complete.
The global variables set by getopt () include:
Optarg-- A pointer to the current option parameter, if any. The index of the next argv pointer when optind-- calls getopt () again. The last known option for optopt--.
For each option, the option string (optstring) contains a corresponding character. Options with parameters, such as the-l and-o options in the example, are followed by a: character. The optstring used in the example is Il:o:vh? (as mentioned earlier, the last two options for printing the program's usage messages are also supported).
You can call getopt () repeatedly until it returns-1; any remaining command-line arguments are usually treated as file names or something else corresponding to the program.
Use of getopt ()
Let's take an in-depth look at the code of the getopt_demo project; for convenience, I'll split this code into parts here, but you can get the complete code in the downloadable source code section (see downloads).
In listing 4, you can see the system header file used by the system demo program; the standard stdio.h provides the standard Icano function prototype, and stdlib.h provides EXIT_SUCCESS and EXIT_FAILURE,unistd.h provides getopt ().
Listing 4. System header file
# include # include # include
Listing 5 shows the globalArgs structure I created to store command-line options in a reasonable manner. Because this is a global variable, code anywhere in the program can access these variables to determine whether to create a keyword index, what language to generate, and so on. It's best to have code outside the main () function treat this structure as a constant, read-only store, because any part of the program can depend on its contents.
Each command line selection has an option, while other variables are used to store the output file name, the pointer to the list of input files, and the number of input files.
Listing 5. Global parameter storage and option string
Struct globalArgs_t {int noIndex; / *-I option * / char * langCode; / *-l option * / const char * outFileName; / *-o option * / FILE * outFile; int verbosity; / *-v option * / char * * inputFiles; / * input files * / int numInputFiles; / * # of input files * /} globalArgs Static const char * optString = "Il:o:vh?"
The option string optString tells getopt () which options can be processed and which options require parameters. If you encounter other options during your stay, getopt () displays an error message and the program exits after the usage message is displayed.
Listing 6 below contains some small stubs for usage message functions and document conversion functions referenced from main (). These stubs can be freely changed for more useful purposes.
Listing 6. Stub
Void display_usage (void) {puts ("doc2html-convert documents to HTML"); / *... * / exit (EXIT_FAILURE);} void convert_document (void) {/ *... * /}
Finally, as shown in listing 7, you use this structure in the main () function. Like a good developer, you need to initialize the globalArgs structure before you start working on command-line arguments. In your program, you can use this to set a reasonable default value under certain circumstances, so that it can be more easily adjusted later when there is a more appropriate default value.
Listing 7. Initialization
Int main (int argc, char * argv []) {int opt = 0; / * Initialize globalArgs before we get to work. * / globalArgs.noIndex = 0; / * false * / globalArgs.langCode = NULL; globalArgs.outFileName = NULL; globalArgs.outFile = NULL; globalArgs.verbosity = 0; globalArgs.inputFiles = NULL; globalArgs.numInputFiles = 0
The while loop and switch statement in listing 8 are part of the code for command-line processing of this program. As long as getopt () finds an option, the switch statement will determine which option is found, and you will be able to see the details in the globalArgs structure. When getopt () finally returns-1, the option processing is complete, and all that is left is your input file.
Listing 8. Use getopt () to process argc/argv
Opt = getopt (argc, argv, optString); while (opt! =-1) {switch (opt) {case'i Qing: globalArgs.noIndex = 1; / * true * / break; case'lly: globalArgs.langCode = optarg; break Case'ostasis: globalArgs.outFileName = optarg; break; case'vails: globalArgs.verbosity++; break Case'hackers: / * fall-through is intentional * / case'?': display_usage (); break; default: / * You won't actually get here. * / break;} opt = getopt (argc, argv, optString);} globalArgs.inputFiles = argv + optind; globalArgs.numInputFiles = argc-optind
Now that you have finished collecting the parameters and options, you can perform any function designed by the program (in this case, document conversion), and then exit (listing 9).
Listing 9. Get to work.
Convert_document (); return EXIT_SUCCESS;}
OK, the work is done. It's very beautiful. You can stop reading now. However, if you want your program to meet the standards of the late 1990s and support the long options that are popular in GNU applications, stay tuned for the following.
Complex command line processing: getopt_long ()
In the 1990s (if you remember correctly), UNIX applications began to support long options, that is, a pair of dashes (rather than a single dash used by a normal short option), a descriptive option name, and a parameter that connects to the option using an equal sign.
Fortunately, you can add long option support to your program by using getopt_long (). As you may have guessed, getopt_long () is a version of getopt () that supports both long and short options.
The getopt_long () function also takes other parameters, one of which is a pointer to an array of struct option objects. This structure is fairly straightforward, as shown in listing 10.
Listing 10. Options for getopt_long ()
Struct option {char * name; int has_arg; int * flag; int val;}
The name member is a pointer to the long option name (with two dashes). The has_arg member is set to one of no_argument, optional_argument, or required_argument (all defined in getopt.h) to indicate whether the option has parameters. If the flag member is not set to NULL, when this option is encountered during processing, the int value it points to is populated with the value of the val member. If the flag member is NULL, the value in val is returned when getopt_long () encounters this option; by setting val as the short parameter of the option, you can use getopt_long () without adding any other code-- existing getopt () that handles while loop and switch will automatically handle this option.
This has become more flexible because individual options can now have optional parameters. More importantly, with very little work, it can be easily put into existing code.
Let's see how to use getopt_long () to make changes to the sample program (the getopt_long_demo project is available in the download section).
Use getopt_long ()
Since getopt_long_demo is almost the same as the getopt_demo code just discussed, I will only explain the changed code. Now that you have more flexibility, support for the-- randomize option (there is no corresponding short option) will also be added.
The getopt_long () function is in the getopt.h header file (not unistd.h), so you will need to include that header file (see listing 11). I also include string.h because I will use strcmp () later to help determine which long parameter is being processed.
Listing 11. Other header files
# include # include
You have added a flag to the globalArgs for the-- randomize option (see listing 12) and created an longOpts array to store information about the long options supported by this program. With the exception of-- randomize, all parameters correspond to existing short options (for example,-- no-index equals-I). By including its short option equivalent in the option structure, you can handle the equivalent long option without adding any other code to the program.
Listing 12. Expanded parameters
Struct globalArgs_t {int noIndex; / *-I option * / char * langCode; / *-l option * / const char * outFileName; / *-o option * / FILE * outFile; int verbosity; / *-v option * / char * * inputFiles; / * input files * / int numInputFiles; / * # of input files * / int randomized / *-randomize option * /} globalArgs;static const char * optString = "Il:o:vh?" Static const struct option longOpts [] = {{"no-index", no_argument, NULL,'I'}, {"language", required_argument, NULL,'l'}, {"output", required_argument, NULL,'o'}, {"verbose", no_argument, NULL,'v'}, {"randomize", no_argument, NULL, 0}, {"help", no_argument, NULL 'h'}, {NULL, no_argument, NULL, 0}}
Listing 13 changes the getop () call to getopt_long (), which accepts an array of longOpts and an int pointer (longIndex) in addition to the parameters of getopt (). When getopt_long () returns 0, the integer pointed to by longIndex is set to the index of the long option currently found.
Listing 13. New and improved option handling
Opt = getopt_long (argc, argv, optString, longOpts, & longIndex); while (opt! =-1) {switch (opt) {case'i 'an: globalArgs.noIndex = 1; / * true * / break; case'lly: globalArgs.langCode = optarg; break Case'ostasis: globalArgs.outFileName = optarg; break; case'vails: globalArgs.verbosity++; break Case'hinge: / * fall-through is intentional * / case'?': display_usage (); break; case 0: / * long option without a short arg * / if (strcmp ("randomize", longOpts [longIndex] .name) = 0) {globalArgs.randomized = 1 } break; default: / * You won't actually get here. * / break;} opt = getopt_long (argc, argv, optString, longOpts, longIndex);}
I also added a case of 0 to handle any long options that do not match the existing short options. In this case, there is only one long option, but the code still uses strcmp () to ensure that it is the one expected.
This is all done; the program now supports long options that are more detailed (and more user-friendly).
Summary
UNIX users always rely on command-line arguments to modify the behavior of programs, especially utilities designed to be used as part of a collection of gadgets (the UNIX shell environment). The program needs to be able to process options and parameters quickly without wasting too much of the developer's time. After all, few programs are designed to handle only command-line arguments, and developers should focus more on what the program is actually doing.
The getopt () function is a standard library call that allows you to easily process command-line arguments and detection options (with or without additional arguments) one by one using direct while/switch statements. A similar getopt_long () allows more descriptive long options to be handled with little extra work, which is very popular with developers.
Now that you know how to easily handle command-line options, you can focus on improving your program's command line, adding long-option support, or adding any other options that were previously shelved because you didn't want to add additional command-line options to the program.
Don't forget to record all your options and parameters somewhere and provide some type of built-in helper to help forgetful users.
Go back to the top of the page
download
Description name size download method Sample getopt () programau-getopt_demo.zip23KBHTTPSample getopt_long () programau-getopt_long_demo.zip24KBHTTP
Information about the download method
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
Http://blog.chinaunix.net/uid-29321384-id-4344529.html
© 2024 shulou.com SLNews company. All rights reserved.