如何跳过NULL文件?C语言命令行工具代码修改咨询
问题:处理命令行文件参数时跳过NULL文件继续执行
我的代码会遍历命令行参数,把alice.txt存入nameArray[0],把anh.txt存入nameArray[1]。执行./wc alice.txt anh.txt时能正常统计两个文件的行数、单词数和字符数,但执行./wc anh.txt时会弹出"NULL FILE"提示并退出程序,推测是nameArray[0]为NULL导致的。希望修改代码,让程序不退出,而是跳过NULL的索引继续执行。
现有代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <stdbool.h> // 假设print_counts函数已实现 void print_counts(int *argArray, int *counts, char *filename); int main(int argc, char **argv) { int argArray[argc]; char *nameArray[argc]; for (int i = 1; i < argc; i ++) { if (strcmp(argv[i], "-l") == 0) { argArray[0] = 1; } if (strcmp(argv[i], "-w") == 0) { argArray[1] = 1; } if (strcmp(argv[i], "-c") == 0) { argArray[2] = 1; } if (strcmp(argv[i], "alice.txt") == 0) { nameArray[0] = "alice.txt"; } if (strcmp(argv[i], "anh.txt") == 0) { nameArray[1] = "anh.txt"; } if ((strcmp(argv[i], "-l") != 0) && (strcmp(argv[i], "-c") != 0 ) && (strcmp(argv[i], "-w") != 0 ) && (strcmp(argv[i], "-w") != 0) && (strcmp(argv[i], "alice.txt") != 0) && (strcmp(argv[i], "anh.txt") != 0)) { printf("%s is an invalid argument or file\n", argv[i]); } } if ((argArray[0] != 1) && (argArray[1] != 1) && (argArray[2] != 1)) { argArray[0] = 1; argArray[1] = 1; argArray[2] = 1; } int *myArrayAlice = get_counts2(nameArray[0]); print_counts(argArray, myArrayAlice, *nameArray); printf(" alice.txt\n"); int *myArrayAnh = get_counts(nameArray[1]); print_counts(argArray,myArrayAnh, *nameArray); printf(" anh.txt\n"); int *myArrayTotal2 = get_counts2(nameArray[1]); print_counts(argArray, myArrayTotal2, *nameArray); printf(" total\n"); return 0; } int *get_counts(char *filename) { FILE *file = fopen(filename, "r"); if (file == NULL) { printf("NULL FILE"); //exit(1); } int c; bool whitespace = true; int *arr = calloc(3,sizeof(int)); for(;;) { c = fgetc(file); if (c == EOF) { break; } else if (c == '\n') { arr[0]++; } else if (whitespace && !isspace(c)) { arr[1]++; whitespace = false; } else if (!whitespace && isspace(c)) { whitespace = true; } arr[2]++; } fclose(file); return arr; } int *get_counts2(char *filename) { FILE *file = fopen(filename, "r"); if (file == NULL) { printf("NULL FILE"); //exit(1); } int c; bool whitespace = true; static int arr[3] = {0,0,0}; for(;;) { c = fgetc(file); if (c == EOF) { break; } else if (c == '\n') { arr[0]++; } else if (whitespace && !isspace(c)) { arr[1]++; whitespace = false; } else if (!whitespace && isspace(c)) { whitespace = true; } arr[2]++; } fclose(file); return arr; }
修改方案
1. 初始化数组,消除未定义行为
原代码中argArray和nameArray未初始化,会产生随机值,改为固定大小并初始化:
// 只处理-l/-w/-c三个选项,固定大小3并初始化为0 int argArray[3] = {0}; // 只存两个目标文件,固定大小2并初始化为NULL char *nameArray[2] = {NULL};
2. 跳过NULL文件,不执行统计逻辑
在调用统计函数前,先判断文件名是否为NULL,仅非NULL时才执行统计和打印,同时修复print_counts的参数错误:
// 处理alice.txt if (nameArray[0] != NULL) { int *myArrayAlice = get_counts2(nameArray[0]); if (myArrayAlice != NULL) { print_counts(argArray, myArrayAlice, nameArray[0]); printf(" alice.txt\n"); free(myArrayAlice); // 释放动态分配的内存 } } // 处理anh.txt if (nameArray[1] != NULL) { int *myArrayAnh = get_counts(nameArray[1]); if (myArrayAnh != NULL) { print_counts(argArray, myArrayAnh, nameArray[1]); printf(" anh.txt\n"); free(myArrayAnh); // 释放get_counts中calloc的内存 } }
3. 修复统计函数的NULL处理逻辑
原函数中文件名NULL或文件打开失败时,仍会执行后续代码导致崩溃,修改后直接返回NULL并终止函数:
int *get_counts(char *filename) { // 先判断文件名是否为NULL if (filename == NULL) { return NULL; } FILE *file = fopen(filename, "r"); if (file == NULL) { printf("无法打开文件: %s\n", filename); return NULL; } int c; bool whitespace = true; int *arr = calloc(3,sizeof(int)); for(;;) { c = fgetc(file); if (c == EOF) { break; } else if (c == '\n') { arr[0]++; } else if (whitespace && !isspace(c)) { arr[1]++; whitespace = false; } else if (!whitespace && isspace(c)) { whitespace = true; } arr[2]++; } fclose(file); return arr; } // 修改get_counts2,去掉静态数组改为动态分配,避免多次调用累加错误 int *get_counts2(char *filename) { if (filename == NULL) { return NULL; } FILE *file = fopen(filename, "r"); if (file == NULL) { printf("无法打开文件: %s\n", filename); return NULL; } int c; bool whitespace = true; int *arr = calloc(3,sizeof(int)); // 改为动态分配 for(;;) { c = fgetc(file); if (c == EOF) { break; } else if (c == '\n') { arr[0]++; } else if (whitespace && !isspace(c)) { arr[1]++; whitespace = false; } else if (!whitespace && isspace(c)) { whitespace = true; } arr[2]++; } fclose(file); return arr; }
4. 修复总和统计逻辑
原代码中总和计算错误,改为累加所有有效文件的统计结果:
int total[3] = {0}; // 累加alice.txt的统计结果 if (nameArray[0] != NULL) { int *alice = get_counts2(nameArray[0]); if (alice != NULL) { total[0] += alice[0]; total[1] += alice[1]; total[2] += alice[2]; free(alice); } } // 累加anh.txt的统计结果 if (nameArray[1] != NULL) { int *anh = get_counts(nameArray[1]); if (anh != NULL) { total[0] += anh[0]; total[1] += anh[1]; total[2] += anh[2]; free(anh); } } // 只有存在有效统计结果时才打印总和 if (total[0] != 0 || total[1] != 0 || total[2] != 0) { print_counts(argArray, total, "total"); printf(" total\n"); }
内容的提问来源于stack exchange,提问作者Jason Fan
相关产品推荐
相关产品推荐

