当前位置: 首页 > article >正文

C语言之用getopt解析命令行参数

C语言之用getopt解析命令行参数

  • 开发环境为WIN10操作系统下用VMWARE17虚拟的UBUNTU LINUX 18.04LTS
  • 命令行参数的解析有两种方法,其中一种方法是用getopt或getoptlong函数,另一种方法是argp系列函数。

短命令参数处理函数getopt

  • getopt函数的定义
#include <unistd.h>

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

extern char *optarg;
extern int optind, opterr, optopt;
  • 包含头文件 unistd.h ,头文件中有四个外部定义的变量:
  • opterr 如果此变量为非零值则输出错误信息,如置零则不输出错误信息
  • optopt 保存不在处理范围内的、未知的参数字符
  • optarg 字符指针型,保存参数的值
  • optind 下一个argv的索引,默认为1
  • getopt函数的第一个参数和第二个参数直接来自main函数
  • getopt函数的第三个参数optstring为参数名的首字母,可以选择加冒号,如果参数后还需要再加一个参数,则必需加冒号,否则不必!
  • 如果optstring为"abc:d",则说明,
    ** 第一个命令行参数为-a,不必附加参数;
    ** 第二个命令行参数为-b,不必附加参数;
    ** 第三个命令行参数为-c,必须附加参数,格式为: -c foo ;
    ** 第四个命令行参数为-d不必附加参数。

简单示例,代码如下:

/* filename: opt.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>

/**/
int
main (int argc, char *argv[])
{
  int hflag = 0;
  int vflag = 0;
  char *svalue = NULL;
  int index;
  int c;

  opterr = 0;

  while ((c = getopt (argc, argv, "hvs:")) != -1)
    switch (c)
      {
      case 'h': hflag = 1; break;
      case 'v': vflag = 1; break;
      case 's': svalue = optarg; break;
      case '?':
        if (optopt == 's')
          fprintf (stderr, "Option -%c requires an argument.\n", optopt);
        else if (isprint (optopt))
          fprintf (stderr, "Unknown option `-%c'.\n", optopt);
        else
          fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
        return 1;
      default:
        abort ();
      }

  printf ("hflag = %d, vflag = %d, svalue = %s\n", hflag, vflag, svalue);

  for (index = optind; index < argc; index++)
    printf ("Non-option argument %s\n", argv[index]);

  return 0;
}

编译运行,测试输出如下:

songvm@ubuntu:~/works/xdn/boo$ gcc opt.c -o opt
songvm@ubuntu:~/works/xdn/boo$ ./opt
hflag = 0, vflag = 0, svalue = (null)
  • 以上为无命令行参数情况,标记和默认值均为0或NULL
songvm@ubuntu:~/works/xdn/boo$ ./opt -h
hflag = 1, vflag = 0, svalue = (null)
songvm@ubuntu:~/works/xdn/boo$ ./opt -v
hflag = 0, vflag = 1, svalue = (null)
songvm@ubuntu:~/works/xdn/boo$ ./opt -h -v
hflag = 1, vflag = 1, svalue = (null)
  • 以上加命令行参数-h、-v或同时相加的情况,标记置为1!!!
songvm@ubuntu:~/works/xdn/boo$ ./opt -s
Option -s requires an argument.
songvm@ubuntu:~/works/xdn/boo$ ./opt -sfoo
hflag = 0, vflag = 0, svalue = foo
songvm@ubuntu:~/works/xdn/boo$ ./opt -s bar
hflag = 0, vflag = 0, svalue = bar
  • 以上加命令行参数-s情况,svalue的值因为后续参数的变化而改变!!!
songvm@ubuntu:~/works/xdn/boo$ ./opt -a -b -c
Unknown option `-a'.
songvm@ubuntu:~/works/xdn/boo$ ./opt a b c
hflag = 0, vflag = 0, svalue = (null)
Non-option argument a
Non-option argument b
Non-option argument c
  • 以上加的命令行参数均不在我们的代码处理范围内,故提示未知命令行参数或非可选命令行参数!!!

长命令行参数处理函数getopt_long

  • getopt_long函数的定义
#include <getopt.h>

int getopt_long(int argc, char * const argv[],
                const char *optstring,
                const struct option *longopts, int *longindex);
  • 包含在getopt.h头文件之内, #include <getopt.h>
  • 第三个参数optstring格式与getopt函数中的用法一样!!!
  • 第四个参数option结构体,struct option包含四个成员
    ** 第1个成员为长命令行参数字符串;
    ** 第2个成员为是否需要后续参数开关,no_argument表示不需要后续参数,required_argument表示需要后续参数;
    ** 第3个成员为开关标记的指针,如果命令行参数是一个标记开关,此成员值为保存标记开关的变量指针;
    ** 第4个成员为长命令行参数字符串对应的短命令行参数字符,如果命令行参数是一个标记开关,设置值为1,以便后续处理。
  • 第五个参数longindex,保存长命令行参数的索引值的变量指针!!!
  • 详细见下面示例代码中的说明。

简单示例,代码如下:

/* filename : optl.c */
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>

/**/
int
main (int argc, char **argv)
{
  int debug_flag = 0;
  struct option lopts[] =
    {
      /* 以下参数设置一个标记,也就是开关一个标记 */
      {"debug", no_argument, &debug_flag, 1},

      /* 以下参数不设置标记,通过长短参数名来区分他们 */
      {"help",    no_argument,       0, 'h'},
      {"version", no_argument,       0, 'v'},
      {"script",  required_argument, 0, 's'},
      {0, 0, 0, 0} //最后一行空值来标记结构体数组结束!!!
    };
  int c = 1;

  while (c != -1)
    {
      /* 定义optidx保存参数索引 */
      int optidx = 0;

      c = getopt_long (argc, argv, "dhvs:", lopts, &optidx);

      /* 检测到参数表结束,退出循环 */
      if (c == -1)
        break;

      switch (c)
        {
        case 0:
	  /* 如果参数设置了一个标记,此处不做其他操作 */
          if (lopts[optidx].flag != 0) break;
          printf ("option %s", lopts[optidx].name);
          if (optarg) printf (" with arg %s", optarg);
          printf ("\n");
          break;

	case 'd': // --debug -d 不需要跟随后续参数
          puts ("option -d\n");
	  debug_flag = 1; //设置debug_flag值为1
          break;

        case 'h': // --help -h 不需要跟随后续参数
          puts ("option -h\n");
	  printf ("Some help message here!\n");
          break;

        case 'v': // --version -v 不需要跟随后续参数
          puts ("option -v\n");
	  printf ("Some version message here!\n");
          break;

        case 's': //--script -s 需要跟随一个后续参数,指出脚本名称
          printf ("option -s with value `%s'\n", optarg);
          break;

        case '?': //
          /* getopt_long already printed an error message. */
          break;

        default:
          abort ();
        }
    }

  /* 输出是否设置debugflag相关信息,如果置为1(已打开开关),则显示,否则不显示 */
  if (debug_flag)
    printf ("debug flag is set!\n");

  /* 输出不在optlong控制内的非法的命令行参数 */
  if (optind < argc)
    {
      printf ("non-option ARGV-elements: ");
      while (optind < argc)
        printf ("%s ", argv[optind++]);
      putchar ('\n');
    }

  return 0;
}

编译运行,测试结果如下:

songvm@ubuntu:~/works/xdn/boo$ gcc -g optl.c -o optl
songvm@ubuntu:~/works/xdn/boo$ ./optl --version
option -v

Some version message here!
songvm@ubuntu:~/works/xdn/boo$ ./optl --help
option -h

Some help message here!
  • 以上显示长命令行参数–version与-v结果相同,–help与-h结果相同!
songvm@ubuntu:~/works/xdn/boo$ ./optl --debug
debug flag is set!
songvm@ubuntu:~/works/xdn/boo$ ./optl -d
option -d

debug flag is set!
  • 以上显示长命令行参数–debug与-d结果相同!
songvm@ubuntu:~/works/xdn/boo$ ./optl --script
./optl: option '--script' requires an argument
songvm@ubuntu:~/works/xdn/boo$ ./optl --script foo.sh
option -s with value `foo.sh'
songvm@ubuntu:~/works/xdn/boo$ ./optl -s
./optl: option requires an argument -- 's'
songvm@ubuntu:~/works/xdn/boo$ ./optl -sfoo.sh
option -s with value `foo.sh'
  • 以上显示长命令行参数–script与-s结果相同!
songvm@ubuntu:~/works/xdn/boo$ ./optl --append --file bar.txt
./optl: unrecognized option '--append'
./optl: unrecognized option '--file'
non-option ARGV-elements: bar.txt 
  • 以上加的命令行参数均不在我们的代码处理范围内,故提示信息!

有很多和系统相关的东西,不同操作系统会出现不同的结果,编码时一定要注意!!!


http://www.kler.cn/a/391768.html

相关文章:

  • 使用elementUI实现表格行拖拽改变顺序,无需引入外部库
  • idea 解决缓存损坏问题
  • 知识库管理系统:企业数字化转型的加速器
  • 实时渲染技术如何助力3D虚拟展厅?
  • git commit 校验
  • 3DTiles之i3dm介绍
  • java:使用Multi-Release Jar改造Java 1.7项目增加module-info.class以全面合规Java 9模块化规范
  • Unet++改进24:添加DualConv||轻量级深度神经网络的双卷积核
  • 无人机飞手考证,地面站培训技术详解
  • uniCloud云对象调用第三方接口,根据IP获取用户归属地的免费API接口,亲测可用
  • PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸
  • SpringBoot项目快速打包成jar项目与部署
  • 深入浅出《钉钉AI》产品体验报告
  • Spring Boot编程训练系统:架构设计精要
  • 虚拟机linux7.9下安装mysql遇到的问题
  • 计算机低能儿从0刷leetcode | 36.有效的数独
  • 【数学二】线性代数-向量-正交规范化、正交矩阵
  • 一篇文章学会ES6 Promise
  • 8 ARM-PEG-FA由八个臂状结构的聚乙二醇(PEG)核心与叶酸(FA)分子通过化学连接而成
  • 什么是大数据治理?在企业数字化转型过程中有什么用?
  • PostgreSQL存储过程-pgAdmin
  • 命令行工具进阶指南
  • 【 AI写作鹅-注册安全分析报告-无验证方式导致安全隐患】
  • Flutter下拉刷新上拉加载的简单实现方式二
  • Lucene 和 Elasticsearch 中更好的二进制量化 (BBQ)
  • 【网络安全 | 甲方建设】DDOS 防范教程