命令行解析模板
别人如果自己要写一个东西,不是马上打开ide开始写代码,而是去网上搜索一下看看是否已经相关的代码,如果有相同的功能代码直接复制过来用就可以了,如果是有相似的可以改改用,这样能提高开发效率。
所以在学习怎么写代码之前我先尝试了一下怎么使用别人写过的代码。我想实现的功能是一个命令行下的程序模板,能够支持对输入的命令行参数进行解析。我首先从网上进行了一下搜索,找到说在linux下有系统提供的函数getopt,但在windows下好像没有,有的说可以直接将linux下的文件拷贝过来直接使用,但好像是需要进行对文件头进行修改,代码下回来看了看不知道该怎么修改,于是又从网上直接下载了一个别人写过的代码直接拿过来使用。
网上下回来的代码是一个.c文件,主要的功能是用来分析命令行参数,函数有三个参数:前两个参数分别代表参数个数和内容,跟main()函数的命令行参数是一样的。第三个参数是选项字符串, 告知 getopt()可以处理哪个选项以及哪个选项需要参数,如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参数,全局变量optarg 即会指向此额外参数。
optstring中的指定的内容的意义补充说明: 1.单个字符,表示选项。 2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数可以紧跟在选项后也可以以空格隔开。该参数的指针将赋给optarg。 3 单个字符后跟两个冒号,表示该选项后可以跟一个参数,也可以不跟。如果跟一个参数,参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(如上例中的e::,如果没有跟参数,则optarg = NULL)
下载的getopt.c文件内容如下,由于避免篇幅过长,我省略掉了头部的部分注释信息,完整的文件信息可以在附件中查看。
#include <stdio.h> /* for EOF */ #include <string.h> /* for strchr() */ /* static (global) variables that are specified as exported by getopt() */ char *optarg = NULL; /* pointer to the start of the option argument */ int optind = 1; /* number of the next argv[] to be evaluated */ int opterr = 1; /* non-zero if a question mark should be returned when a non-valid option character is detected */ /* handle possible future character set concerns by putting this in a macro */ #define _next_char(string) (char)(*(string+1)) int getopt(int argc, char *argv[], char *opstring) { static char *pIndexPosition = NULL; /* place inside current argv string */ char *pArgString = NULL; /* where to start from next */ char *pOptString; /* the string in our program */ if (pIndexPosition != NULL) { /* we last left off inside an argv string */ if (*(++pIndexPosition)) { /* there is more to come in the most recent argv */ pArgString = pIndexPosition; } } if (pArgString == NULL) { /* we didn't leave off in the middle of an argv string */ if (optind >= argc) { /* more command-line arguments than the argument count */ pIndexPosition = NULL; /* not in the middle of anything */ return EOF; /* used up all command-line arguments */ } /*--------------------------------------------------------------------- * If the next argv[] is not an option, there can be no more options. *-------------------------------------------------------------------*/ pArgString = argv[optind++]; /* set this to the next argument ptr */ if (('/' != *pArgString) && /* doesn't start with a slash or a dash? */ ('-' != *pArgString)) { --optind; /* point to current arg once we're done */ optarg = NULL; /* no argument follows the option */ pIndexPosition = NULL; /* not in the middle of anything */ return EOF; /* used up all the command-line flags */ } /* check for special end-of-flags markers */ if ((strcmp(pArgString, "-") == 0) || (strcmp(pArgString, "--") == 0)) { optarg = NULL; /* no argument follows the option */ pIndexPosition = NULL; /* not in the middle of anything */ return EOF; /* encountered the special flag */ } pArgString++; /* look past the / or - */ } if (':' == *pArgString) { /* is it a colon? */ /*--------------------------------------------------------------------- * Rare case: if opterr is non-zero, return a question mark; * otherwise, just return the colon we're on. *-------------------------------------------------------------------*/ return (opterr ? (int)'?' : (int)':'); } else if ((pOptString = strchr(opstring, *pArgString)) == 0) { /*--------------------------------------------------------------------- * The letter on the command-line wasn't any good. *-------------------------------------------------------------------*/ optarg = NULL; /* no argument follows the option */ pIndexPosition = NULL; /* not in the middle of anything */ return (opterr ? (int)'?' : (int)*pArgString); } else { /*--------------------------------------------------------------------- * The letter on the command-line matches one we expect to see *-------------------------------------------------------------------*/ if (':' == _next_char(pOptString)) { /* is the next letter a colon? */ /* It is a colon. Look for an argument string. */ if ('\0' != _next_char(pArgString)) { /* argument in this argv? */ optarg = &pArgString[1]; /* Yes, it is */ } else { /*------------------------------------------------------------- * The argument string must be in the next argv. * But, what if there is none (bad input from the user)? * In that case, return the letter, and optarg as NULL. *-----------------------------------------------------------*/ if (optind < argc) optarg = argv[optind++]; else { optarg = NULL; return (opterr ? (int)'?' : (int)*pArgString); } } pIndexPosition = NULL; /* not in the middle of anything */ } else { /* it's not a colon, so just return the letter */ optarg = NULL; /* no argument follows the option */ pIndexPosition = pArgString; /* point to the letter we're on */ } return (int)*pArgString; /* return the letter that matched */ } }
程序主函数代码只是包含了上面的getopt.c文件,然后调用了getopt函数解析并打印了命令行参数,并没有执行其他任何操作。getopt.cpp文件代码如下:
#include "stdafx.h" #include "getopt.c" int main(int argc, char* argv[]) { int ch; //opterr = 0; while((ch = getopt(argc,argv,"a:b:c:d:"))!= -1) { switch(ch) { case 'a': printf("option a:'%s'\n",optarg); break; case 'b': printf("option b:'%s'\n",optarg); break; case 'c': printf("option c:'%s'\n",optarg); break; case 'd': printf("option d:'%s'\n",optarg); break; default: printf("other option :%c\n",ch); } } return 0; }
将代码编译后没有错误。在命令行中调用运行,得到的结果如下:
D:\cproject\getopt\Release>getopt.exe -a f -b fawef -c fawe -d fawef option a:'f' option b:'fawef' option c:'fawe' option d:'fawef' D:\cproject\getopt\Release>
btw:
代码编写使用的ide是VC++ 6.0。
相关代码的下载地址