在C中解析.txt文件

我试图通过C中的.txt文件进行解析。这是我到目前为止所拥有的

void parser() { FILE * rooms; char * theString; char * theToken; char a[ROOM_STRING_LENGTH]; rooms = fopen("assets/rooms.txt", "r"); if(rooms == NULL) { printf("error opening file\n"); } while(fgets(a, ROOM_STRING_LENGTH, rooms) != NULL) { theString = malloc((sizeof(char)*(strlen(a)+1))); strcpy(theString, a); theToken = strtok(theString, " "); while (theToken != NULL) { printf("the next token: %s\n", theToken); theToken = strtok(NULL, " "); if(theToken[0] == 'd') { doorParser(theToken); } else if(theToken[0] == 'g' || theToken[0] == 'm' || theToken[0] == 'p' || theToken[0] == 'h') { iconParser(theToken); } } if(theToken == NULL) { } } free(theString); fclose(rooms); } void iconParser(char * theToken) { int k; int item; char posX; char posY; while(k <= (strlen(theToken))) { switch(theToken[k]) { case 'g': item = 1; posY = theToken[1]; posX = theToken[3]; printf("the item: %d, the y position: %c, the x position: %c\n", item, posY, posX); break; case 'm': item = 2; posY = theToken[1]; posX = theToken[3]; break; case 'p': item = 3; posY = theToken[1]; posX = theToken[3]; break; case 'h': item = 4; posY = theToken[1]; posX = theToken[3]; break; } k++; } } void doorParser(char * theToken) { int side; char place; switch(theToken[1]) { case 'e': { side = 1; place = theToken[2]; printf("the side: %d, the place: %c\n", side, place); break; } case 'w': { side = 2; place = theToken[2]; break; } case 's': { side = 3; place = theToken[2]; break; } case 'n': { side = 4; place = theToken[2]; break; } default: { } } } 

这是我的.txt文件:

 12X6 de8 dw3 ds5 g8,7 m3,4 p2,2 h2,2 12X6 de8 dw3 ds5 g8,7 m3,4 p2,2 h2,4 12X6 de8 dw3 ds5 g8,7 m3,4 p2,2 h2,6 12X6 de8 dw3 ds5 g8,7 m3,4 p2,2 h2,10 12X6 de8 dw3 ds5 g8,7 m3,4 p2,2 h2,12 12X6 de8 dw3 ds5 g8,7 m3,4 p2,2 h2,14 

我现在遇到的问题是,在它运行一行或然后运行.txt文件然后我得到一个分段错误,我也想知道如何转换字符串的某个值(即一个char)成一个int值

首先,你的循环结构没有任何意义:

 while (theToken != NULL) { printf("the next token: %s\n", theToken); theToken = strtok(NULL, " "); if(theToken[0] == 'd') <<< This is dereferencing NULL after last token! 

您正在使用while条件检查theToken是否为NULL ,然后您获得下一个标记并立即使用它(通过尝试查找其第0个字符),即使它是NULL

使用strtok的惯用方法是

 for (tok = strtok(str, " "); tok; tok = strtok(NULL, " ")) { // Process the token here. 

对于第二部分 – 将字符串转换为int – 您可以google for ato函数实现。 例如, http://www.geeksforgeeks.org/write-your-own-atoi/ int atoi(char * str) – 确实如此将“1998”转换为1998年

在这种情况下看起来也像:

 while(fgets(a, ROOM_STRING_LENGTH, rooms) != NULL) { while((c=fgetc(rooms))!='\n') { roomString[i] = c; i++; } ...etc 

你最终错过了第一行(和所有其他奇数行)beacuse fgets读取第一行(并且你不使用这个结果),然后“while((c = fgetc(rooms))!=’\ n’) “在这里阅读第二行……

所以,我认为你需要做的是用“fgets(a,ROOM_STRING_LENGTH,rooms)”来解析你读到的“a”。 我可能错了,但我认为“strlen(a)”会给你实际的行长 – 而不是缓冲区的大小。 所以你可以开始解析“a”而不是将所有内容复制到roomString中

哦,我可能会看到Seg故障的潜在原因 – 在循环中

 while((c=fgetc(rooms))!='\n') { roomString[i] = c; i++; } 

“i”增加而你永远不会“冲洗”它,在每个这样的循环之前应该有i = 0,否则你的“i”会随着每次迭代的更大而继续增加“while(fgets(a,ROOM_STRING_LENGTH,rooms)!= NULL)“循环 – 这是你可以越过你的”char roomString [ROOM_STRING_LENGTH];“ 缓冲 …

正如Gene在评论中建议的那样,即使在最内部的while循环中ti为NULL,也尝试访问theToken [0]元素,尝试替换代码:

 theToken = strtok(theString, " "); while (theToken != NULL) { printf("the next token: %s\n", theToken); theToken = strtok(NULL, " "); if(theToken[0] == 'd') { doorParser(theToken); } else if(theToken[0] == 'g' || theToken[0] == 'm' || theToken[0] == 'p' || theToken[0] == 'h') { iconParser(theToken); } } if(theToken == NULL) { } 

有以下一个:

 theToken = strtok(theString, " "); while (theToken != NULL) { printf("the next token: %s\n", theToken); if(theToken[0] == 'd') { doorParser(theToken); } else if(theToken[0] == 'g' || theToken[0] == 'm' || theToken[0] == 'p' || theToken[0] == 'h') { iconParser(theToken); } /* invoking strtok here is "safe" because you check if't NULL right after in the while loop condition */ theToken = strtok(NULL, " "); } if(theToken == NULL) { printf("string is over no more tokens! next line ..."); }