C语言解析TXT构建规划系统时出现字符串重复错误求助
字符串解析重复错误的排查与解决
问题概述
在构建基于TXT文件的规划系统时,将文本内容转换为Event结构体的过程中出现字符串解析错误,随着程序运行错误愈发频繁,例如将"hungry"解析为"hungrygry",输出中出现大量拼接的垃圾字符。
错误原因分析
- C字符串缺少终止符:
parseLine函数使用memcpy复制子串后,未手动添加字符串终止符'\0'。C语言中字符串必须以'\0'结尾,否则printf会持续读取内存直到遇到终止符,导致输出多余的垃圾数据。 - 未处理行尾无逗号的元素:原代码仅在遇到逗号时提取子串,若行尾元素后无直接逗号(直接到换行符),会漏掉该元素(当前输入文件虽有逗号,但需兼容通用情况)。
- 变量未初始化:
main函数中Z和x未初始化,导致后续逻辑和输出出现错误值。 - 字符串比较逻辑错误:直接用
==比较字符串是无效的,必须使用strcmp函数。 - 事件索引未递增:读取事件时未增加
NbE,导致所有事件都会覆盖第一个Event元素。
修复方案
- 在
parseLine函数中,每次memcpy复制子串后立即添加'\0'终止符。 - 循环结束后,检查是否存在未处理的行尾元素,若有则提取并添加终止符。
- 初始化
main函数中的Z和x变量。 - 替换字符串比较方式为
strcmp。 - 读取事件时递增
NbE索引。
修复后的完整代码
#include <stdlib.h> #include <string.h> #include <stdio.h> typedef int bool; #define TRUE 1 #define FALSE 0 // definir string typedef char string[1024]; //Define event typedef struct{ string action[49],preconds[24],add[24],delete[24]; int NbPreconds,NbAdd,NbDelete; }Event; int parseLine(char source[], string cible[]){ int i=0, n=0; // i: source[], n: cible[] while(source[i]!=':') i++; // go until ':' i++; // avancer au debut de la premiere chaine int j=i; // point beginning of first chain with j while(source[i]!='\n' && source[i] != '\0'){ // 兼容文件末尾无换行的情况 if(source[i]==','){ memcpy(&cible[n], &source[j], i-j); // extract characters from j to i cible[n][i-j] = '\0'; // 添加字符串终止符 n++; j=i+1; // j beginning of chain } i++; } // 处理行尾没有逗号的最后一个元素 if(j < i){ memcpy(&cible[n], &source[j], i-j); cible[n][i-j] = '\0'; n++; } return n; } int main(){ Event event[49]; string start[49],finish[49]; int NbStart,NbFinish,i,k,x=0,Z=0; // 初始化x和Z char source[100]; FILE* txtfile = fopen("school.txt","r"); // insérer "monkeys.txt" / "blocs.txt" / "school.txt" pour choisir le fichier if(txtfile == NULL){ // tester le fichier s'il existe printf("Fichier inexistant.\n"); exit(0); } else{ printf("Fichier ouvert.\n"); } //Lire les Conditions de départ & de Fin fgets(source,100,txtfile); NbStart=parseLine(source,start); printf("Condition Départ:\n"); for(i=0; i<NbStart;i++){ printf(" - %s\n",start[i]); } fgets(source,100,txtfile); string tempo[]={""}; NbFinish=parseLine(source,finish); printf("Condition Fin:\n"); for(i=0;i<NbFinish;i++){ printf(" - %s\n",finish[i]); } //read action int NbE=0; while(fgets(source,100,txtfile)!=NULL){ fgets(source,100,txtfile); // 跳过****分隔行 if(feof(txtfile)) break; // 防止文件末尾多读导致错误 parseLine(source, event[NbE].action); //read preconds fgets(source,100,txtfile); event[NbE].NbPreconds=parseLine(source, event[NbE].preconds); for(i=0;i<event[NbE].NbPreconds;i++){ printf("Precond: %s\n",event[NbE].preconds[i]); } //read add fgets(source,100,txtfile); event[NbE].NbAdd=parseLine(source, event[NbE].add); for(i=0;i<event[NbE].NbAdd;i++){ printf("Add: %s\n",event[NbE].add[i]); } //read delete fgets(source,100,txtfile); event[NbE].NbDelete=parseLine(source, event[NbE].delete); for(i=0;i<event[NbE].NbDelete;i++){ printf("Delete: %s\n",event[NbE].delete[i]); } NbE++; // 递增事件索引,避免覆盖 } bool Test=0; //Not complete while(Test==0){ Test=1; Z=0; // 每次循环重置Z for(i=0;i<NbFinish;i++){ // 修正逻辑:检查finish的每个元素是否在start中 int found = 0; for(k=0;k<NbStart;k++){ if(strcmp(start[k], finish[i]) == 0){ // 使用strcmp比较字符串 found = 1; break; } } if(!found){ Test=0; break; } } x++; // 递增步骤数 // 这里需要补充规划逻辑,当前逻辑只是示例,需根据实际需求完善 } if(Test==1){ printf("Le résultat a était trouvé en %d étapes.\n",x); } fclose(txtfile); }
修复后验证结果
修复后,输出的预处理条件、添加项、删除项均为正确的字符串,无垃圾字符拼接,示例输出片段:
Fichier ouvert. Condition Départ: - at door - on floor - has ball - hungry - chair at door Condition Fin: - not hungry Precond: chair at middle room Precond: at middle room Precond: on floor Add: at bananas Add: on chair Delete: at middle room Delete: on floor Precond: chair at door Precond: at door Add: chair at middle room Add: at middle room Delete: chair at door Delete: at door ...
内容的提问来源于stack exchange,提问作者Silver Winter
相关产品推荐
相关产品推荐

