簡體   English   中英

在C中的.txt文件中進行解析

[英]Parsing in .txt file in C

我試圖解析C中的.txt,然后將值返回到結構。 我試圖解析的.txt文件是

2X6 de8 dw3 ds5 g8,7 m3,4 p2,2 h2,2
8X22 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
12X15 de8 dw3 ds5 g8,7 m3,4 p2,2 h2,14

我現在擁有代碼的方式,我可以解析除第一個元素(例如)以外的所有內容。 “ 2X6”或“ 8X22”。 在我的代碼中,我使用fgets從.txt文件中讀取一行,然后使用strtok遍歷每個元素。 我想知道如何解析第一個元素並將數字設置為等於變量,然后將其發送給結構

我的代碼是:

void parser(int argc, char **argv)
{
FILE * rooms;
char * theString;
char * theToken;
int numberElements;
int side;
int k;
int x;
int placeInt;
int posX;
int posY;
char a[ROOM_STRING_LENGTH];
struct item gold;
struct item monster;
struct item potion;
struct item hero;
struct room roomInfo;
numberElements = 0;
rooms = fopen(argv[1], "r");

if(rooms == NULL)
{
    printf("error opening file\n");
}
x = 0;
while(fgets(a, ROOM_STRING_LENGTH, rooms) != NULL)
{ 
    theString = malloc((sizeof(char)*(strlen(a)+1)));
    strcpy(theString, a);

    for(theToken = strtok(theString, " "); theToken; theToken = strtok(NULL, " "))
    {
        printf("the next token: %s\n", theToken);

        if(theToken[0] == 'd')
        {
            switch(theToken[1])
            {
                case 'e':
                {
                    placeInt = theToken[2] - '0';
                    printf("the side: %d, the place: %d\n", side, placeInt);
                    break;
                }
                case 'w':
                {
                    side = 2;
                    placeInt = theToken[2] - '0';
                    printf("the side: %d, the place: %d\n", side, placeInt);
                    break;
                }
                case 's':
                {
                    side = 3;
                    placeInt = theToken[2] - '0';
                    printf("the side: %d, the place: %d\n", side, placeInt);
                    break;
                }
                case 'n':
                {
                    side = 4;
                    placeInt = theToken[2] - '0';
                    printf("the side: %d, the place: %d\n", side, placeInt);
                    break;
                }
                default:
                {
                    break;
                } 
            }       
        }

        else if(theToken[0] == 'g' || theToken[0] == 'm' || theToken[0] == 'p' || theToken[0] == 'h')
        {
             k = 0;
             while(k <= (strlen(theToken)))
             {

                 switch(theToken[k])
                 {
                     case 'g':
                     posY = theToken[1] - '0';
                     posX = theToken[3] - '0';

                     gold.Xposition = posX;
                     gold.Yposition = posY;
                     printf("the y position: %d, the x position: %d\n",  posY, posX);
                     break;

                     case 'm':
                     posY = theToken[1] - '0';
                     posX = theToken[3] - '0';

                     monster.Xposition = posX;
                     monster.Yposition = posY;
                     printf("the y position: %d, the x position: %d\n",  posY, posX);
                     break;

                     case 'p':
                     posY = theToken[1] - '0';
                     posX = theToken[3] - '0';

                     potion.Xposition = posX;
                     potion.Yposition = posY;
                     printf("the y position: %d, the x position: %d\n",  posY, posX);
                     break;

                     case 'h':
                     posY = theToken[1] - '0';
                     posX = theToken[3] - '0';

                     hero.Xposition = posX;
                     hero.Yposition = posY;
                     printf("the y position: %d, the x position: %d\n", posY, posX);                         
                     break;
                 }
                 k++;
             }
        }
        else if(theToken == NULL)
        {
            printf("end of file");
        }
        numberElements++;
    }

    if(theToken == NULL)
    {
        printf("You've reached the end of the line\n");
    }
    printf("%d\n", numberElements);
    x++;
}

free(theString);
fclose(rooms);
 }

關於代碼的兩個快速注釋:使用theToken[2] - '0'這樣的表達式,您只能處理一位數字(除非您將12編碼為'<')。 您在示例文件中的最后一個輸入行將不起作用。

另外,如果您在循環內分配了一個臨時字符串,則還應該在循環內釋放它。 否則,將僅釋放最后分配的字符串。 在您的情況下,您實際上並不需要字符串副本,因為您已經在使用從文件讀取的可變charachter緩沖區工作,可以使用strtok對其進行標記。

對於您strtok問題:可以使用strtok ,然后使用sscanf進入標記。 這是一個簡短的示例代碼,僅處理您的某些格式。 第一個標記必須是地牢尺寸,隨后的標記必須以命令字母開頭。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void aaargh(const char *msg)
{
    fprintf(stderr, "Aaargh: %s\n", msg);
    exit(1);
}

int dir(int c) {
    if (c == 'e') return 1;
    if (c == 'w') return 2;
    if (c == 's') return 3;
    if (c == 'n') return 4;
    return 0;
}

int main(int argc, char **argv)
{
    char line[] = "12X15 de8 dw3 ds5 m3,4,orc m10,8,troll m6,13,medusa";
    char *tk;

    int width, height;

    tk = strtok(line, " ");
    if (sscanf(tk, "%dX%d", &width, &height) < 2) {
        aaargh("Illegal dimension.");
    }

    printf("Dungeon size: %d x %d\n", width, height);

    tk = strtok(NULL, " ");
    while (tk) {
        switch (tk[0]) {
        case 'd': {
                int side = dir(tk[1]);
                int pos;

                if (side == 0) aaargh("Illegal side");

                if (sscanf(tk + 2, "%d", &pos) < 1) {
                    aaargh("Illegal pos");
                }
                printf("Wall side %d, pos %dn\n", side, pos);
            }
            break;

        case 'm': {
                int x, y;
                char which[20];

                if (sscanf(tk, "m%d,%d,%19s", &x, &y, which) < 1) {
                    aaargh("Illegal monster description");
                }
                printf("Monster: %s at %d, %d\n", which, x, y);

            }
            break;

        default:
            aaargh("Unknown command");
        }

        tk = strtok(NULL, " ");        
    }

    return 0;
}

錯誤跟蹤非常基本,應該真正告訴哪里出了什么問題,這樣您就可以捕獲輸入錯誤。

您的問題是連續的if

    for(theToken = strtok(theString, " "); theToken; theToken = strtok(NULL, " "))
    {
        if(theToken[0] == 'd')
        {
            /* ... */
        }
        else if(theToken[0] == 'g' || theToken[0] == 'm' || theToken[0] == 'p' || theToken[0] == 'h')
        {
            /* ... */
        }
        else if(theToken == NULL)
        {
            /* ... */
        }
    }

請注意,當theToken指向以'd''g''m''p''h'以外'd'其他字符開頭的字符串時,不會在for循環的主體中執行任何代碼(初始printf()除外) printf() ,最后增加到numberElements )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM