sscanf()无法正确识别格式

时间:2010-11-05 12:54:31

标签: c++ scanf

当我在下面的代码中使用sscanf()时,由于某种原因它占用了整行并将它放在第一个字符串中,我没有看到任何问题。 Msg()的输出就像PatchVersion=1.1.1.5 = °?¦§-

一样

该文件看起来像这样(除了每一行都是一个新行,不确定为什么它在StackOverflow上显示为一个)

PatchVersion=1.1.1.5
ProductName=tf
appID=440

代码:

bool ParseSteamFile()
{
    FileHandle_t file;
    file = filesystem->Open("steam.inf", "r", "MOD");

    if(file)
    {
        int size = filesystem->Size(file);
        char *line = new char[size + 1];

        while(!filesystem->EndOfFile(file))
        {
            char *subLine = filesystem->ReadLine(line, size, file);

            if(strstr(subLine, "PatchVersion"))
            {
                char *name = new char[32];
                char *value = new char[32];
                sscanf(subLine, "%s=%s", name, value);

                Msg("%s = %s\n", name, value);
            }
            else if(strstr(subLine, "ProductName"))
            {
                char *name = new char[32];
                char *value = new char[32];
                sscanf(subLine, "%s=%s", name, value);

                Msg("%s = %s\n", name, value);
            }
        }

        return true;
    }
    else
    {
        Msg("Failed to find the Steam Information File (steam.inf)\n");
        filesystem->Close(file);
        return false;
    }

    filesystem->Close(file);
    return false;
}

5 个答案:

答案 0 :(得分:4)

一种解决方案是使用(在我看来,未充分利用的)字符组格式说明符:

sscanf(subLine, "%[^=]=%s", name, value);

此外,在依赖它们之前,您应该使用sscanf()的返回值来验证您确实获得了两个值。

答案 1 :(得分:2)

%s是“贪婪的”,即它一直在阅读,直到它到达whitspace(或换行符或EOF)。 '='字符不属于这些字符,因此sscanf只会继续,匹配第一个%s的整行。

您可能最好使用(例如)strtok()或简单的逐字符解析器。

答案 2 :(得分:0)

来自scanf的联机帮助页,关于%s:

匹配一系列非空白字符;下一个指针必须是一个指向字符数组的指针,该指针足够长以容纳输入序列和终止空字符('\ 0'),这是自动添加的。输入字符串在空格或最大字段宽度处停止,以先到者为准。

答案 3 :(得分:0)

%s将读取字符,直到遇到空格。由于在'='符号之前/之后没有空格,因此读取整个字符串。

答案 4 :(得分:0)

你使用数组是非常差的C ++技术。您可以使用流,但如果您坚持使用sscanf和数组,那么至少使用vector来管理您的内存。

您可能会准确打印出subLine中的内容以及Msg所执行的操作。这是你自己的代码,因为我从未听说过FileHandle_t。我知道它有一个返回char *的方法,可能你需要管理它。

正则表达式是boost库的一部分,很快就会出现在标准库中。它们是相当“标准”的,你可以用它来解析你的行。

(如果你有,可以使用boost :: regex或tr1 :: regex,VS2008有它)