在C中解析.text文件

时间:2014-03-13 22:28:30

标签: c parsing

我正在尝试解析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值

2 个答案:

答案 0 :(得分:2)

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

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

您正在检查theToken不是NULL while条件,然后您获得下一个令牌并立即使用它(通过尝试查找其0&#39; th即使它是NULL

使用strtok的惯用方法是

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

答案 1 :(得分:0)

对于第二部分 - 将字符串转换为int - 您可以google for ato函数实现。例如http://www.geeksforgeeks.org/write-your-own-atoi/ int atoi(char * str) - 确切地说它转换了#34; 1998&#34;到1998年

在这种情况下看起来也是这样:

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

你最终错过了第一行(以及所有其他奇数行)beacuse fgets读取第一行(并且你不使用此结果),然后&#34; while((c = fgetc(rooms) )=&#39;!\ n&#39;)&#34;在这里阅读第二行......

所以,相反,我认为你需要做的是解析&#34; a&#34;你用&#34; fgets(a,ROOM_STRING_LENGTH,rooms)&#34;阅读。我可能错了,但我认为&#34; strlen(a)&#34;会给你实际的线长 - 而不是缓冲区的大小。所以你可以开始解析&#34; a&#34;而不是将所有内容复制到roomString

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

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

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

正如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 ...");
}