使用getopt的's'选项无法输出活动文件的技术问题求助
问题排查:getopt的's'选项无输出问题
我设计了一个替代ls的
-s选项,用于列出当前目录的普通文件,但编译运行后终端无任何输出。以下是完整代码及单独的s选项代码块:
原始完整代码
#include <errno.h> #include <getopt.h> #include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <dirent.h> #define DATA_SIZE 1000 void print_help(void) { printf("Help\n"); printf(">> cast -d (deletes file)\n"); printf(">> cast -r (renames file)\n"); printf(">> cast -c (create new file)\n"); printf(">> cast -s (searches contents of file)\n"); printf("________________________________________\n"); printf("Find an error or a bug? please submit it in the issues section on github\n"); } case 's': { int main(void) { DIR *directory; struct dirent *entry; directory = opendir("."); if (directory == NULL) { printf("Error reading directory\n"); return 1; } while ((entry = readdir(directory)) != NULL) if (entry->d_type == DT_REG) { printf("file: %s\n", entry->d_name); } } if (closedir(directory) == -1) { printf("Error closing directory\n"); return 1; } return 0; } } int main(int argc, char **argv) { int option_val = 0; int opt_delete = 0; int opt_help = 0; int opt_rename = 0; int opt_create = 0; int opt_search = 0; while ((option_val = getopt(argc, argv, "dhrcs")) != -1) { switch (option_val) { case 'd': { char filename[65]; //Hope your filename isnt bigger than this printf("Filename or path to file: "); scanf("%s", filename); // checks to see if your filename isnt bigger than specified if (remove(filename) != 0) { fprintf(stderr, "Errno: %d\n", errno); perror("Error msg"); } else printf("%s, deleted.\n", filename); opt_delete = 1; break; case 'r': { char file[65], new[65]; printf("File: "); scanf("%s", file); printf("New name: "); scanf("%s", new); if (rename(file, new) != 0) { fprintf(stderr, "Errno: %d\n", errno); perror("Error msg"); } else printf("%s --> %s", file, new); opt_rename = 1; break; case 'c': { FILE *f = fopen("Castdocument.txt", "w+"); fprintf(f, "Finished with maybe no errors? Rename this file to whatever you would like and change the filename extension with ""cast -r"""); printf("File created! (Check your home directory for ""Castdocument.txt"" file and modify that to fit your needs)"); fclose(f); opt_create = 1; case 'h': { print_help(); opt_help = 1; break; default:; /* '?' */ //print_help(); } if (opt_delete) { printf("\n"); } if (opt_rename) { printf("\n"); } if (opt_help) { print_help(); } if (opt_search) { printf("\n"); } if (opt_create) { printf("\n"); } } } } } } }
单独的's'选项代码块
case 's': { int main(void) { DIR *directory; struct dirent *entry; directory = opendir("."); if (directory == NULL) { printf("Error reading directory\n"); return 1; } while ((entry = readdir(directory)) != NULL) if (entry->d_type == DT_REG) { printf("file: %s\n", entry->d_name); } } if (closedir(directory) == -1) { printf("Error closing directory\n"); return 1; } return 0; } }
错误原因分析
case 's'定义在全局作用域,不属于任何switch语句
你把s选项的代码块直接写在全局,没有放到main函数里的switch结构中,程序完全不会执行这部分逻辑。s选项代码嵌套了多余的int main(void)函数
C程序只能有一个入口main函数,分支内定义的main函数根本不会被执行。- 主switch语句缺少
case 's'分支
程序无法响应-s参数,即使修复前面的问题也不会触发逻辑。 - 部分case分支缺失
break
比如case 'c'后没有break,会导致执行完创建文件逻辑后,继续执行case 'h'的帮助打印。 opt_search变量未被赋值
主函数末尾的判断依赖该变量,但s分支没有设置它,影响后续收尾逻辑。
修复后的完整代码
#include <errno.h> #include <getopt.h> #include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <dirent.h> #define DATA_SIZE 1000 void print_help(void) { printf("Help\n"); printf(">> cast -d (deletes file)\n"); printf(">> cast -r (renames file)\n"); printf(">> cast -c (create new file)\n"); printf(">> cast -s (lists regular files in current directory)\n"); printf("________________________________________\n"); printf("Find an error or a bug? please submit it in the issues section on github\n"); } int main(int argc, char **argv) { int option_val = 0; int opt_delete = 0; int opt_help = 0; int opt_rename = 0; int opt_create = 0; int opt_search = 0; while ((option_val = getopt(argc, argv, "dhrcs")) != -1) { switch (option_val) { case 'd': { char filename[65]; printf("Filename or path to file: "); scanf("%s", filename); if (remove(filename) != 0) { fprintf(stderr, "Errno: %d\n", errno); perror("Error msg"); } else { printf("%s, deleted.\n", filename); } opt_delete = 1; break; } case 'r': { char file[65], new[65]; printf("File: "); scanf("%s", file); printf("New name: "); scanf("%s", new); if (rename(file, new) != 0) { fprintf(stderr, "Errno: %d\n", errno); perror("Error msg"); } else { printf("%s --> %s\n", file, new); } opt_rename = 1; break; } case 'c': { FILE *f = fopen("Castdocument.txt", "w+"); if (f == NULL) { perror("Failed to create file"); break; } fprintf(f, "Finished with maybe no errors? Rename this file to whatever you would like and change the filename extension with \"cast -r\""); printf("File created! (Check current directory for \"Castdocument.txt\" file and modify that to fit your needs)\n"); fclose(f); opt_create = 1; break; } case 'h': { print_help(); opt_help = 1; break; } case 's': { DIR *directory; struct dirent *entry; directory = opendir("."); if (directory == NULL) { printf("Error reading directory\n"); opt_search = 1; break; } while ((entry = readdir(directory)) != NULL) { if (entry->d_type == DT_REG) { printf("file: %s\n", entry->d_name); } } if (closedir(directory) == -1) { printf("Error closing directory\n"); } opt_search = 1; break; } default: print_help(); break; } } if (opt_delete) printf("\n"); if (opt_rename) printf("\n"); if (opt_search) printf("\n"); if (opt_create) printf("\n"); return 0; }
关键修复说明
- 将
s选项逻辑移入main函数的switch语句,作为case 's'分支 - 删除分支内多余的
main函数定义 - 为
case 'c'补上break,避免逻辑串执行 - 修正
print_help中s选项的描述(原描述与实际功能不符) - 增加
fopen失败的错误判断,增强程序健壮性 - 在
s分支中设置opt_search = 1,符合收尾逻辑要求 - 为
while循环添加大括号,避免缩进导致的逻辑歧义
内容的提问来源于stack exchange,提问作者Xenon
相关产品推荐
相关产品推荐

