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

Linux C编程基础知识(命令行参数)

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

参数说明:

参数

作用

argc/argv

直接传入 main 函数的命令行参数(个数 + 数组)

optstring

选项规则字符串,核心规则:

- 单个字符(如 h)→ 无参数选项(-h);

- 字符 +:(如 p:)→ 必须带参数的选项(-p 8080);

- 字符 +::(GNU 扩展)→ 可选参数的选项(-p8080,不能有空格)。

关键全局变量(getopt 内置):

变量

作用

optarg

指向当前选项的参数值(如 -p 8080,optarg = "8080");

optind

下一个待解析的 argv索引(解析完选项后,可通过它获取非选项参数);

opterr

非 0 时,getopt 自动输出错误提示(如未知选项);设为 0 可关闭,自定义错误;

optopt

存储无法识别的选项字符(用于自定义错误提示)。

示例:

#include <stdio.h> #include <unistd.h> // getopt #include <stdlib.h> // atoi #include <errno.h> // errno #include <limits.h> // INT_MAX/INT_MIN #define VERSION "v1.0.0" // 打印帮助信息 void print_help(const char *prog_name) { printf("用法:%s [选项] [非选项参数]\n", prog_name); printf("选项:\n"); printf(" -h 显示帮助信息\n"); printf(" -p <端口> 指定服务端口(1-65535,必填)\n"); printf(" -v 输出版本信息\n"); } int main(int argc, char *argv[]) { int port = 0; int opt; // 关闭getopt默认错误提示,自定义更友好的错误 opterr = 0; // 循环解析选项:optstring = "hp:v"(h无参,p有参,v无参) while ((opt = getopt(argc, argv, "hp:v")) != -1) { switch (opt) { case 'h': // 帮助 print_help(argv[0]); return 0; case 'p': // 端口(带参数) // 安全转换端口(替代atoi,检测非法输入) errno = 0; long temp = strtol(optarg, NULL, 10); if (errno != 0 || temp < 1 || temp > 65535 || temp > INT_MAX) { fprintf(stderr, "错误:端口必须是1-65535的整数(输入:%s)\n", optarg); return 1; } port = (int)temp; break; case 'v': // 版本 printf("版本:%s\n", VERSION); return 0; case '?': // 未知选项/缺少参数 if (optopt == 'p') { fprintf(stderr, "错误:选项 -%c 需要传入端口参数\n", optopt); } else { fprintf(stderr, "错误:未知选项 -%c\n", optopt); } fprintf(stderr, "使用 %s -h 查看帮助\n", argv[0]); return 1; default: return 1; } } // 检查必填参数 if (port == 0) { fprintf(stderr, "错误:必须通过 -p 指定端口\n"); fprintf(stderr, "使用 %s -h 查看帮助\n", argv[0]); return 1; } // 解析非选项参数(optind 指向第一个非选项参数) if (optind < argc) { printf("\n非选项参数:\n"); for (int i = optind; i < argc; i++) { printf(" %s\n", argv[i]); } } // 业务逻辑 printf("\n程序启动:端口 = %d\n", port); return 0; }
getopt_long接口
int getopt_long(int argc, char *const argv[],const char *optstring,const struct option *longopts,int *longindex);

参数说明:

参数

作用

argc/argv

直接传入 main 函数的命令行参数(个数 + 数组)

optstring

短选项规则字符串(和 getopt 完全一致,如 "hp:v");

longopts

长选项规则结构体数组(核心),定义每个长选项的名称、参数要求等;

longindex

输出参数,存储当前解析到的长选项在 longopts 中的索引(传 NULL 则忽略);

长选项核心结构体(struct option),这是 getopt_long 的关键,每个元素对应一个长选项:

struct option { const char *name; // 长选项名(如 "help"、"port"); int has_arg; // 参数要求: // no_argument (0) → 无参数(如 --help); // required_argument (1) → 必须带参数(如 --port); // optional_argument (2) → 可选参数(如 --log=debug); int *flag; // 标志位: // NULL → getopt_long 返回 val 的值; // 非NULL → 将 val 赋值给 *flag,函数返回 0; int val; // 映射值: // 通常设为对应的短选项字符(如 'h'、'p'),实现长短选项联动; };

⚠️ 注意:结构体数组必须以全 0 元素结尾({0, 0, 0, 0}),否则会导致内存越界。

全局变量(和 getopt 通用):

变量

作用

optarg

指向当前选项的参数值(长短选项通用,如 --port 8080 → optarg="8080");

optind

下一个待解析的 argv 索引(解析完选项后,获取非选项参数);

opterr

非 0 时自动输出错误提示,设为 0 可自定义错误;

optopt

存储出错的短选项字符(长选项出错时 optopt=0);

示例:

#include <stdio.h> #include <unistd.h> #include <getopt.h> #include <stdlib.h> #include <errno.h> #include <limits.h> #define VERSION "v2.0.0" // 打印帮助信息 void print_help(const char *prog_name) { printf("用法:%s [选项] [非选项参数]\n", prog_name); printf("选项说明:\n"); printf(" -h, --help 显示帮助信息并退出\n"); printf(" -p, --port <端口> 指定服务端口(1-65535,必填)\n"); printf(" -v, --version 输出版本信息并退出\n"); printf(" -d, --debug 启用调试模式\n"); } int main(int argc, char *argv[]) { int port = 0; int debug_mode = 0; int opt; // 存储解析返回值(短选项字符/0/-1) int longindex = 0; // 存储长选项索引(可选) // 定义长选项结构体数组(核心) static struct option long_options[] = { {"help", no_argument, 0, 'h'}, // --help → 返回 'h' {"port", required_argument, 0, 'p'}, // --port → 返回 'p' {"version", no_argument, 0, 'v'}, // --version → 返回 'v' {"debug", no_argument, 0, 'd'}, // --debug → 返回 'd' {0, 0, 0, 0 } // 结束标志(必须) }; // 关闭默认错误提示,自定义更友好的错误 opterr = 0; // 循环解析长短选项(optstring 仍为短选项规则) while ((opt = getopt_long(argc, argv, "hp:vd", long_options, &longindex)) != -1) { switch (opt) { case 'h': // 帮助(-h/--help) print_help(argv[0]); return 0; case 'p': // 端口(-p/--port) // 安全转换端口(避免atoi的缺陷) errno = 0; long temp_port = strtol(optarg, NULL, 10); if (errno != 0 || temp_port < 1 || temp_port > 65535 || temp_port > INT_MAX) { fprintf(stderr, "错误:端口必须是1-65535的整数(输入:%s)\n", optarg); return 1; } port = (int)temp_port; break; case 'v': // 版本(-v/--version) printf("程序版本:%s\n", VERSION); return 0; case 'd': // 调试(-d/--debug) debug_mode = 1; printf("✅ 调试模式已启用\n"); break; case 0: // flag非NULL时返回0(本例未用到,仅演示) printf("长选项 %s 触发(无短选项映射)\n", long_options[longindex].name); break; case '?': // 错误:未知选项/缺少参数 if (optopt != 0) { // 短选项错误(如 -x、-p无参数) if (optopt == 'p') { fprintf(stderr, "错误:选项 -%c/--port 需要传入端口参数\n", optopt); } else { fprintf(stderr, "错误:未知短选项 -%c\n", optopt); } } else { // 长选项错误(如 --xxx) fprintf(stderr, "错误:未知长选项 %s\n", argv[optind-1]); } fprintf(stderr, "使用 %s --help 查看帮助\n", argv[0]); return 1; default: return 1; } } // 检查必填参数 if (port == 0) { fprintf(stderr, "错误:必须通过 -p/--port 指定端口\n"); fprintf(stderr, "使用 %s --help 查看帮助\n", argv[0]); return 1; } // 解析非选项参数(optind 指向第一个非选项参数) if (optind < argc) { printf("\n📁 非选项参数(待处理):\n"); for (int i = optind; i < argc; i++) { printf(" - %s\n", argv[i]); } } // 业务逻辑输出 printf("\n🚀 服务启动配置:\n"); printf(" 端口:%d\n", port); printf(" 调试模式:%s\n", debug_mode ? "开启" : "关闭"); return 0; }
http://www.jsqmd.com/news/600629/

相关文章:

  • SenseVoice-small-onnx多语种ASR效果展示:粤语戏曲唱词节奏化转写
  • 域名解析失败可能会对网站 SEO 产生什么影响
  • 嵌入式Linux牛棚养殖监护系统开发实战
  • 网页 SEO 推广的基本原理是什么_网页 SEO 推广的案例有哪些值得参考
  • uniapp车辆轨迹回放功能避坑指南:从播放卡顿到车头朝向不准,我都帮你解决了
  • 2026年评价高的折弯机数控夹具/钣金折弯机夹具/折弯机液压夹具厂家推荐与选择指南 - 行业平台推荐
  • 中科蓝讯配置工具实战:5分钟搞定可视化自定义开发(附常见配置语法详解)
  • 2026年知名的箱梁挂篮/铁路挂篮/架桥机挂篮厂家信誉综合参考 - 行业平台推荐
  • Coze-Loop快速入门:三步搞定代码优化,小白也能写出高质量代码
  • Modbus RTU通信实战:用PLC1200+CB1241搭建低成本设备监控从站
  • seo分析软件对比_seo分析软件能帮助提高网站流量吗
  • 2026年靠谱的余热回收系统设计/余热回收利用/化工余热节能改造/窑炉余热回收正规生产厂家推荐 - 行业平台推荐
  • Pixel Aurora Engine 创意写作辅助:为故事生成场景插图与角色肖像
  • pyside2 打包发布exe文件
  • Pixel Script Temple 前端交互设计:打造沉浸式Web像素画生成工坊
  • Qwen3.5-2B辅助STM32开发:基于自然语言的寄存器配置与驱动生成
  • 2026年比较好的调温电烙铁/高频焊台电烙铁/家用小型电烙铁/USB电烙铁厂家采购参考指南 - 品牌宣传支持者
  • 不同行业的SEO整站优化价格有何差异
  • 考虑气电联合需求响应的气电综合能源配网系统协调优化运行代码功能说明
  • 如何使用RTCPilot配置一个集群RTC服务
  • intv_ai_mk11实操解析:Llama中型模型在内容运营、客服应答、文档辅助中的应用
  • 保姆级教程:用Docker Compose在本地一键部署FastGPT知识库系统
  • 千问3.5-27B基础教程:图片理解API返回JSON字段含义详解
  • Vue3集成AntV G6实战:从零构建拓扑图可视化应用
  • 2026年知名的长城润滑油一级经销商/长城润滑油指定经销商用户好评厂家推荐 - 品牌宣传支持者
  • 从充电桩到电网:深度解析双向OBC(V2L/V2G)的HIL测试挑战与Vector方案
  • 2026人员充场服务推荐榜全品类人力供应优选:志愿者公司/志愿者提供/志愿者服务/扫楼派发传单/拍卖会充场/选择指南 - 优质品牌商家
  • 海康H5player错误码解析与实战排错指南
  • 清音听真快速上手:Qwen3-ASR-1.7B Docker部署教程,打造个人语音转文字服务
  • Llama-3.2V-11B-cot保姆级教学:NVIDIA SMI监控双卡负载均衡