解析命令行选项
-
函数getopt可以用来解析命令行选项:
-
函数原型:int getopt(int argc,char *const argv[],const char *optstring)
参数:1.argc,argv 是从main函数的参数列表中获取的。
2.optstring 指定了函数getopt应寻找的命令行选项集合,该参数由一组字符组成,每个字符标识一个选项。getopt至少应该接受62个字符[a-zA-Z0-9]作为选项;:、?、和-这几个是对getopt有着特殊意义的字符;每个选项字符后面跟着一个冒号字符(:),表示这个选项带有一个参数。
返回值:返回得到选项字符的int值,当返回值为-1时,则表示目前没有更多的选项可解析了(已到达选项列表的结尾)。
2. 函数getopt的全局变量:
2.1 optind:指向参数列表argv中未处理的下一个元素(会跳过选项带有的参数)。
2.2 optopt:返回出现错误的选项字符。
2.3 optstring:指向选项的参数。
2.4 opterr:默认值为1;当其值为0时,可用来禁止显示由getopt函数打印出来的错误消息。
3.
函数getopt错误上报的几种行为 错误上报的方法 getopt()会显示错误消息吗 针对未识别的选项产生的返回值 针对缺少参数产生的返回值 默认(opterr == 1)
Y
?
?
opterr == 0
N
?
?
在optstring中将第一个字符设为:
N
?
:
4.程序实例:
#include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<unistd.h> #include<fcntl.h> #include<errno.h> #include<string.h> #include<stdarg.h> #include<sys/stat.h> #include<ctype.h> #define printable(ch)(isprint((unsigned char)ch) ? ch : '#') #define MAX_ENAME 132 static char *ename[] = { /* 0 */ "", /* 1 */ "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO","ENXIO", /* 7 */ "E2BIG", "ENOEXEC", "EBADF", "ECHILD", /* 11 */ "EAGAIN/EWOULDBLOCK", "ENOMEM","EACCES", "EFAULT", /* 15 */ "ENOTBLK", "EBUSY", "EEXIST","EXDEV", "ENODEV", /* 20 */ "ENOTDIR", "EISDIR","EINVAL", "ENFILE", "EMFILE", /* 25 */ "ENOTTY", "ETXTBSY","EFBIG", "ENOSPC", "ESPIPE", /* 30 */ "EROFS", "EMLINK","EPIPE", "EDOM", "ERANGE", /* 35 */ "EDEADLK/EDEADLOCK", "ENAMETOOLONG", "ENOLCK", "ENOSYS", /* 39 */ "ENOTEMPTY","ELOOP", "", "ENOMSG", "EIDRM", "ECHRNG", /* 45 */ "EL2NSYNC","EL3HLT", "EL3RST", "ELNRNG", "EUNATCH", /* 50 */"ENOCSI", "EL2HLT", "EBADE", "EBADR", "EXFULL", "ENOANO", /* 56 */"EBADRQC", "EBADSLT", "", "EBFONT", "ENOSTR", "ENODATA", /* 62 */"ETIME", "ENOSR", "ENONET", "ENOPKG", "EREMOTE", /* 67 */"ENOLINK", "EADV", "ESRMNT", "ECOMM", "EPROTO", /* 72 */"EMULTIHOP", "EDOTDOT", "EBADMSG", "EOVERFLOW", /* 76 */"ENOTUNIQ", "EBADFD", "EREMCHG", "ELIBACC", "ELIBBAD", /* 81 */"ELIBSCN", "ELIBMAX", "ELIBEXEC", "EILSEQ", "ERESTART", /* 86 */"ESTRPIPE", "EUSERS", "ENOTSOCK", "EDESTADDRREQ", /* 90 */"EMSGSIZE", "EPROTOTYPE", "ENOPROTOOPT", /* 93 */"EPROTONOSUPPORT", "ESOCKTNOSUPPORT", /* 95 */"EOPNOTSUPP/ENOTSUP", "EPFNOSUPPORT", "EAFNOSUPPORT", /* 98 */"EADDRINUSE", "EADDRNOTAVAIL", "ENETDOWN", "ENETUNREACH", /* 102 */"ENETRESET", "ECONNABORTED", "ECONNRESET", "ENOBUFS", /* 106 */"EISCONN", "ENOTCONN", "ESHUTDOWN", "ETOOMANYREFS", /* 110 */"ETIMEDOUT", "ECONNREFUSED", "EHOSTDOWN", "EHOSTUNREACH", /* 114 */"EALREADY", "EINPROGRESS", "ESTALE", "EUCLEAN", /* 118 */"ENOTNAM", "ENAVAIL", "EISNAM", "EREMOTEIO", "EDQUOT", /* 123 */"ENOMEDIUM", "EMEDIUMTYPE", "ECANCELED", "ENOKEY", /* 127 */"EKEYEXPIRED", "EKEYREVOKED", "EKEYREJECTED", /* 130 */"EOWNERDEAD", "ENOTRECOVERABLE", "ERFKILL" }; typedef enum {FALSE,TRUE} Boolean; static void usageError(char *,char *,int); static void outputError(Boolean ,int ,Boolean ,const char *,va_list ); static void terminate(Boolean ); void fatal(const char *format,...); int main(int ac ,char *av[]) { int opt; char *pstr; int xfnd; xfnd = 0; pstr = NULL; while((opt = getopt(ac,av,":p:x")) != -1) { printf("opt = %3d(%c);optind = %d",opt,printable(opt),optind); if(opt == '?' || opt == ':') printf(";optopt = %3d(%c)",optopt,printable(optopt)); printf("\n"); switch(opt) { case 'p': pstr = optarg; break; case 'x': xfnd++; break; case ':': usageError(av[0],"Missing argument",optopt); case '?': usageError(av[0],"Unrecognized option",optopt); default: fatal("Unexpected case in switch()"); } } if(xfnd != 0) printf("-x was specified (count = %d)\n",xfnd); if(pstr != NULL) printf("-p was specified with the value \"%s\"\n",pstr); if(optind < ac) printf("First nonoption argument is \"%s\" at av[%d]\n",av[optind],optind); exit(EXIT_SUCCESS); } static void usageError(char *progName,char *msg,int opt) { if(msg != NULL && opt != 0) fprintf(stderr,"%s(-%c)\n",msg,printable(opt)); fprintf(stderr,"Usage: %s [-p arg] [-x]\n",progName); exit(EXIT_FAILURE); } void fatal(const char *format,...) { va_list argList; va_start(argList,format); outputError(FALSE,0,TRUE,format,argList); va_end(argList); terminate(TRUE); } static void outputError(Boolean useErr,int err,Boolean flushStdout,const char *format,va_list ap) { #define BUF_SIZE 500 char buf[BUF_SIZE],userMsg[BUF_SIZE],errText[BUF_SIZE]; vsnprintf(userMsg,BUF_SIZE,format,ap); if(useErr) snprintf(errText,BUF_SIZE,"[%s %s]",(err > 0 && err < MAX_ENAME) ? ename[err] : "?UNKNOWN?",strerror(err)); else snprintf(errText,BUF_SIZE,":"); snprintf(buf,BUF_SIZE,"ERROR %s %s\n",errText,userMsg); if(flushStdout) fflush(stdout); fputs(buf,stderr); fflush(stderr); } static void terminate(Boolean useExit3) { char *s; s = getenv("EF_DUMPCORE"); if(s != NULL && s != '\0') abort(); else if(useExit3) exit(EXIT_FAILURE); else _exit(EXIT_FAILURE); }