{"id":4856,"date":"2021-07-10T00:01:18","date_gmt":"2021-07-10T07:01:18","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=4856"},"modified":"2021-07-17T07:14:55","modified_gmt":"2021-07-17T14:14:55","slug":"discovering-command-line-options-part-iii","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=4856","title":{"rendered":"Discovering Command Line Options, Part III"},"content":{"rendered":"<p>Continuing from <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4829\">last week&#8217;s Lesson<\/a>, to read multiple command line arguments, you must put the <em>getopt()<\/em> function in a loop. Specifically, you set the function as the looping condition. The loop&#8217;s guts evaluate the switches found.<br \/>\n<!--more--><br \/>\nHere&#8217;s how the looping condition can look:<\/p>\n<p><code>while( (r=getopt(argc,argv,\"ABC\")) != -1 )<\/code><\/p>\n<p>The <em>getopt()<\/em> function is nestled at the heart of the <em>while<\/em> loop&#8217;s condition. Its return value is saved in <em>int<\/em> variable <code>r<\/code>. This expression is enclosed in parentheses, which evaluates to the value of <code>r<\/code>. This value is compared with -1. As long as the <em>getopt()<\/em> function returns values other than -1, the loop continues. Here is the full code:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2021_07_10-Lesson-a.c\" rel=\"noopener\" target=\"_blank\">2021_07_10-Lesson-a.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;unistd.h&gt;\r\n\r\nint main(int argc, char *argv[])\r\n{\r\n    int r,count;\r\n\r\n    <span class=\"comments\">\/* suppress getopt()'s error message *\/<\/span>\r\n    opterr = 0;\r\n\r\n    <span class=\"comments\">\/* process multiple command line arguments *\/<\/span>\r\n    count = 0;\r\n    while( (r=getopt(argc,argv,\"ABC\")) != -1 )\r\n    {\r\n        if( r=='?' )\r\n            printf(\"Unknown option specified\\n\");\r\n        else\r\n            printf(\"Option '%c' found\\n\",r);\r\n        count++;\r\n    }\r\n    printf(\"%d arguments processed\\n\",count);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The program digests command line arguments <code>-A<\/code>, <code>-B<\/code>, and <code>-C<\/code> in any combination. Invalid arguments are output as such. Here is a sample run with all the arguments specified:<\/p>\n<p><code>$ .\/a.out -A -B -C<br \/>\nOption 'A' found<br \/>\nOption 'B' found<br \/>\nOption 'C' found<br \/>\n3 arguments processed<\/code><\/p>\n<p>Here is a sample run specifying legitimate argument <code>-B<\/code> and a bogus argument <code>-Z<\/code>:<\/p>\n<p><code>$ .\/a.out -B -Z<br \/>\nOption 'B' found<br \/>\nUnknown option specified<br \/>\n2 arguments processed<\/code><\/p>\n<p>To further examine the unknown option, use the global <code>optind<\/code> variable. This variable is an index used by the <em>getopt()<\/em> function as it churns through the command line arguments. The <code>optind<\/code> &#8220;options index&#8221; value is one greater than the element number in the <code>argv[]<\/code> array.<\/p>\n<p>The following code presents a modification that spits out invalid arguments by name:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2021_07_10-Lesson-b.c\" rel=\"noopener\" target=\"_blank\">2021_07_10-Lesson-b.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;unistd.h&gt;\r\n\r\nint main(int argc, char *argv[])\r\n{\r\n    int r,count;\r\n\r\n    <span class=\"comments\">\/* suppress getopt()'s error message *\/<\/span>\r\n    opterr = 0;\r\n\r\n    <span class=\"comments\">\/* process multiple command line arguments *\/<\/span>\r\n    count = 0;\r\n    while( (r=getopt(argc,argv,\"ABC\")) != -1 )\r\n    {\r\n        if( r=='?' )\r\n            printf(\"Unknown option '%s' specified\\n\",\r\n                    argv[optind-1]\r\n                  );\r\n        else\r\n            printf(\"Option '%c' found\\n\",r);\r\n        count++;\r\n    }\r\n    printf(\"%d arguments processed\\n\",count);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>Here&#8217;s a sample run:<\/p>\n<p><code>$ .\/a.out -A -O -B<br \/>\nOption 'A' found<br \/>\nUnknown option '-O' specified<br \/>\nOption 'B' found<br \/>\n3 arguments processed<\/code><\/p>\n<p>Easier than using the <code>optind<\/code> value, global variable <code>optopt<\/code> holds the character value (decimal) of the invalid switch. To update the code, replace <code>argv[optind-1]<\/code> with <code>optopt<\/code>, and change the <em>printf()<\/em> format string placeholder from <code>%s<\/code> to <code>%c<\/code>, as is done in this code:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2021_07_10-Lesson-c.c\" rel=\"noopener\" target=\"_blank\">2021_07_10-Lesson-c.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;unistd.h&gt;\r\n\r\nint main(int argc, char *argv[])\r\n{\r\n    int r,count;\r\n\r\n    <span class=\"comments\">\/* suppress getopt()'s error message *\/<\/span>\r\n    opterr = 0;\r\n\r\n    <span class=\"comments\">\/* process multiple command line arguments *\/<\/span>\r\n    count = 0;\r\n    while( (r=getopt(argc,argv,\"ABC\")) != -1 )\r\n    {\r\n        if( r=='?' )\r\n            printf(\"Unknown option '%c' specified\\n\",\r\n                    optopt\r\n                  );\r\n        else\r\n            printf(\"Option '%c' found\\n\",r);\r\n        count++;\r\n    }\r\n    printf(\"%d arguments processed\\n\",count);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The output from the above code&#8217;s program and the preceding program are identical.<\/p>\n<p>Remember that both <code>optind<\/code> and <code>optopt<\/code> are external variables defined in the <code>unistd.h<\/code> header file.<\/p>\n<p>In <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4867\">next week&#8217;s Lesson<\/a>, I cover how the <em>getopt()<\/em> function read&#8217;s option values. For example: <code>-a 177<\/code>, where <code>-a<\/code> is the switch and <code>177<\/code> is specified as the switch&#8217;s value (or string).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Once you know how it works, it&#8217;s possible to use the <em>getopt()<\/em> function to process multiple command line arguments. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4856\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-4856","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4856","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4856"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4856\/revisions"}],"predecessor-version":[{"id":4884,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4856\/revisions\/4884"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4856"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4856"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4856"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}