getopt_long长选项(--)的optarg无法赋值问题求助
getopt_long长选项解析时optarg无法赋值的解决方法
我写了一个用getopt_long解析短选项(-)和长选项(--)的C程序,但解析长选项时,optarg没法给程序里的变量正常赋值。请问怎么在解析长选项时把optarg的值正确赋给对应变量?
#include <stdbool.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <getopt.h> #include "file_handle.c" //#include "songs.c" #include "getoptions.c" //Mix_Music *music = NULL; int main(int argc, char *argv[]) { //init(); int f = 0; int d = 0; char *file = NULL; char *directory = NULL; const struct option long_options[] = { /* {"verbose",no_argument,&verbose_flag,1} */ {"help", no_argument, 0, 'h'}, {"file", required_argument, &f, 'f'}, {"directory", required_argument, &d, 'd'}, {0, 0, 0, 0} }; int opt; if (argc <= 1) { fprintf(stderr, "No arguments provided!\nTry 'cplay --help' for more information.\n"); } else { while ((opt = getopt_long(argc, argv, "d:f:h", long_options, NULL)) != -1) { printf("optarg %s\n",optarg); switch(opt){ case 'h': //print_help(); break; case 'f': puts("test f"); file = optarg; break; case 'd': directory = optarg; break; default: break; } } } if(f && d){ printf("OPTION -f, --file and -d, --directory are given\n"); printf("%s\n",directory); int valid = 0; char response; while(!valid) { printf("Enter one option [f\\d]: "); scanf(" %c",&response); if(response == 'd' || response == 'f'){ valid = 1; } else printf("Wrong Input given press f for single file and d for directory option\n"); } } printf("%d\n %d",f,d); }
问题原因
你的核心问题出在struct option的定义逻辑上:
- 当
struct option中的flag成员不为NULL时(比如你代码里的&f和&d),getopt_long不会返回val字段的字符值,而是会把val的值直接写入flag指向的变量中,然后返回0。 - 这就导致你的
switch(opt)分支里的case 'f'和case 'd'永远不会被触发,自然file和directory变量无法通过optarg完成赋值。
修正方案
把struct option里file和directory对应的flag设为NULL,保留val为对应的短选项字符,这样getopt_long就会返回val的值,进入对应的case分支,optarg就能正常赋值给目标变量。同时手动在分支里设置f和d的标记值,保证后续判断逻辑正常工作。
修正后的关键代码片段:
const struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"file", required_argument, NULL, 'f'}, // 将flag设为NULL {"directory", required_argument, NULL, 'd'}, // 将flag设为NULL {0, 0, 0, 0} }; // ... while ((opt = getopt_long(argc, argv, "d:f:h", long_options, NULL)) != -1) { printf("optarg %s\n",optarg); switch(opt){ case 'h': //print_help(); break; case 'f': puts("test f"); file = optarg; f = 1; // 手动标记该选项已被设置 break; case 'd': directory = optarg; d = 1; // 手动标记该选项已被设置 break; default: break; } }
补充说明
- 当
flag为NULL时,getopt_long会返回val字段的字符,让switch能正确匹配到对应的选项分支。 - 手动设置
f和d为1,是为了保证后续if(f && d)的分支判断逻辑能正常触发。
内容的提问来源于stack exchange,提问作者devMe
相关产品推荐
相关产品推荐

