逐行解析项目列表然后逐个字符地解析

时间:2017-10-05 01:25:17

标签: c

我必须解析具有以下格式的游戏文件:

ItemID      = 3288 # This is a comments and begins with '#' character.
Name        = "a magic sword"
Description = "It has some ancient runic inscriptions."
Flags       = {MultiUse,Take,Weapon}
Attributes  = {Weight=4200,WeaponType=1,WeaponAttackValue=48,WeaponDefendValue=35}
# A line can also begin with this character and it should be ignored.

我必须解析它的数据并将它们放入变量中。我已经尝试了很多东西,并且我被告知我必须逐行读取文件,然后逐个字符地读取每一行(所以我能够读到'#'字符)然后读取结果按照模式逐字逐句。我这样做了:

void ParseScriptFile(FILE* File) {
    char Line[1024];
    while (fgets(Line, sizeof(Line), File)) {

    }
    fclose(File);
}

我想我应该阅读while循环内部的行,但我不知道在到达#字符之前我将如何阅读,如果它不存在则继续循环直行。有一个简单的方法吗?

2 个答案:

答案 0 :(得分:0)

使用sscanf,就像我为你做了两次

 void ParseScriptFile(FILE* File) {
    char Line[1024];
    int ItemID; // variable to store ItemId
    char name[40]; // string to store Name
    while (fgets(Line, sizeof(Line), File)) {
            sscanf(Line, "ItemID = %d", &ItemID);
            sscanf(Line, "Name = %[^n]s", name); // ^n upto newline
    }       
    printf("ItemId= %d\n", ItemID);
    printf("Name= %s", name);

    fclose(File);
}

答案 1 :(得分:0)

这里或多或少可行的代码。使用fgets()读取行是正确的。然后,您可以轻松地消除空行和注释行。如果该行以注释结尾,则可以将#转换为空字节以忽略注释。然后你需要扫描条目名称字段(假设名称部分,等号左边没有空格),=和右边的值。

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

static
void ParseScriptFile(FILE *File)
{
    char Line[1024];
    while (fgets(Line, sizeof(Line), File))
    {
        if (Line[0] == '#' || Line[0] == '\n')
            continue;
        char *comment_start = strchr(Line, '#');
        if (comment_start != NULL)
            *comment_start = '\0';
        char name[64];
        char value[1024];
        if (sscanf(Line, " %63s = %1023[^\n]", name, value) == 2)
            printf("Name = [%s] Value = [%s]\n", name, value);
        else
            printf("Mal-formed line: [%s]\n", Line);
    }
    fclose(File);
}

int main(void)
{
    ParseScriptFile(stdin);
    return 0;
}

程序从标准输入读取。从您的数据文件运行的示例产生:

Name = [ItemID] Value = [3288 ]
Name = [Name] Value = ["a magic sword"]
Name = [Description] Value = ["It has some ancient runic inscriptions."]
Name = [Flags] Value = [{MultiUse,Take,Weapon}]
Name = [Attributes] Value = [{Weight=4200,WeaponType=1,WeaponAttackValue=48,WeaponDefendValue=35}]

注意ItemID值末尾的空格; #符号前面有一个空格。

如果您需要处理本身包含#符号的字符串,则必须更加努力(Curse = "You @##$%!" # Language, please!)。解析诸如Attributes的值之类的条目是单独函数的一个单独任务(可以从这个函数调用)。实际上,您应该调用一个或多个函数来处理每个名称/值对。您可能还需要将一些上下文传递给ParseScriptFile()函数,以便可以正确保存数据。您不希望用不必要的全局变量污染干净的代码,对吗?