C语言读取文件生成字符串数组后,如何移除其中的空元素?
问题:C语言筛选表达式数组出现空行,导致符合条件的表达式未正常输出
文本文件中的表达式示例
X&Y X|Y !X (X|Y)|Z (X&Y)|Z (X&Y)&Z (X&Y)|Z&(A|B ((X|Y)|Z)&((A|B)|(C&D)) (X&Y)|(Z&(A|B)) (A|B)&(!C) A|(B&(C&(D|E))) ((X|Y)|(Z&(A|B)))|((C&D)&(D|E)) (A|B)|(C&D)&(D|E) !A&(B|C) (A|B)|(C|D)&(D !A|(B&C)
筛选后的异常结果(含空行)
X&Y X|Y !X (X|Y)|Z (X&Y)|Z (X&Y)&Z //此处为空行 ((X|Y)|Z)&((A|B)|(C&D)) (X&Y)|(Z&(A|B)) (A|B)&(!C) A|(B&(C&(D|E))) ((X|Y)|(Z&(A|B)))|((C&D)&(D|E)) (A|B)|(C&D)&(D|E) !A&(B|C) //此处为空行
问题代码
#include <stdio.h> #include <string.h> #define MAX 200 #define MAXLEN 100 int main() { FILE *dat; int number_of_elements; char str[MAX][MAXLEN]; int NumberOfRightBracket=0; int NumberOFLeftBracket=0; int NumberOfOperators=0; int Number=0; int i=0; char g[200][MAXLEN]; dat=fopen("dat.txt","r"); if(dat==NULL) { printf("Error"); } while(!feof(dat) && !ferror(dat)) { if(fgets(str[i],100,dat)!=NULL) str[i][strcspn(str[i],"\n")] = 0; char p[100]; strcpy(p,str[i]); for(int o=0;o<strlen(p);o++) { if(p[o]=='(') NumberOFLeftBracket++; else if(p[o]==')') NumberOfRightBracket++; else if(p[o]=='*' || p[o]=='|' || p[o]=='&' || p[o]=='!') NumberOfOperators++; } if(NumberOfRightBracket!=0 && NumberOFLeftBracket!=0 && NumberOfRightBracket==NumberOFLeftBracket) { strcpy(g[i],p); Number++; } else if(NumberOfRightBracket==0 && NumberOFLeftBracket==0 && NumberOfOperators==1) { strcpy(g[i],p); Number++; } NumberOfRightBracket=0; NumberOFLeftBracket=0; NumberOfOperators=0; i++; } for(int k=0;k<Number;k++) { printf("%s\n",g[k]; } }
问题原因及修复方案
核心问题
- 数组索引不匹配:用原文件的行索引
i给结果数组g赋值,不符合条件的行不会写入g[i],但Number计数跳过这些行,导致g数组中存在未初始化的空元素,输出时显示空行。 - 语法错误:
printf语句缺少右括号,文件打开失败后未终止程序,未关闭文件导致资源泄漏。 - 循环逻辑缺陷:
while(!feof(dat))容易多读一行,导致额外的空元素。
修复步骤
- 独立维护结果数组索引:用单独的变量
resIdx管理结果数组的写入位置,符合条件时才递增,避免空元素占位。 - 修正语法与资源问题:补全
printf括号,添加文件打开失败的返回逻辑,结束时关闭文件。 - 优化读取循环:直接用
fgets的返回值判断读取是否成功,避免多读空行。
修复后的完整代码
#include <stdio.h> #include <string.h> #define MAX 200 #define MAXLEN 100 int main() { FILE *dat = fopen("dat.txt", "r"); if (dat == NULL) { printf("Error opening file\n"); return 1; } char str[MAX][MAXLEN]; char g[MAX][MAXLEN]; int resIdx = 0; // 结果数组的独立索引 int lineIdx = 0; while (fgets(str[lineIdx], MAXLEN, dat) != NULL) { // 移除换行符 str[lineIdx][strcspn(str[lineIdx], "\n")] = '\0'; char *p = str[lineIdx]; int leftBracket = 0, rightBracket = 0, operators = 0; for (int o = 0; o < strlen(p); o++) { if (p[o] == '(') leftBracket++; else if (p[o] == ')') rightBracket++; else if (p[o] == '*' || p[o] == '|' || p[o] == '&' || p[o] == '!') operators++; } // 判断是否符合筛选条件 if ((leftBracket > 0 && rightBracket > 0 && leftBracket == rightBracket) || (leftBracket == 0 && rightBracket == 0 && operators == 1)) { strcpy(g[resIdx++], p); } lineIdx++; } // 输出所有符合条件的表达式 for (int k = 0; k < resIdx; k++) { printf("%s\n", g[k]); } fclose(dat); return 0; }
修复后效果
运行后将输出所有符合条件的表达式,无空行:
X&Y X|Y !X (X|Y)|Z (X&Y)|Z (X&Y)&Z ((X|Y)|Z)&((A|B)|(C&D)) (X&Y)|(Z&(A|B)) (A|B)&(!C) A|(B&(C&(D|E))) ((X|Y)|(Z&(A|B)))|((C&D)&(D|E)) (A|B)|(C&D)&(D|E) !A&(B|C) !A|(B&C)
内容的提问来源于stack exchange,提问作者Andew Tayloe
相关产品推荐
相关产品推荐

