Sscanf与多线字符串

时间:2010-11-18 17:10:39

标签: c

我有一个包含多行的字符串,我想使用sscanf来匹配它的特定部分。但它似乎只能用于匹配第一行中包含的数据。

例如,如果我有字符串:

  

“age1:x \ r \ n   age2:x“

使用sscanf:

  

sscanf(字符串,“age1:%d”,& i); - 这个工作
  sscanf(字符串,“age2:%d”,& j); - 但事实并非如此。

有什么想法吗?

5 个答案:

答案 0 :(得分:5)

正如其他人所说,sscanf不记得读取了多少数据并推进了输入数据,如scanffscanf。使用%n说明符记住读取了多少数据,并自行推进输入:

int bytesRead;
if(sscanf(string, "age 1: %d\n%n", &i, &bytesRead) == 1) &&
   sscanf(string + bytesRead, "age 2: %d", &j) == 1)
{
    // success
}
else
{
    // parsing failed
}

%n说明符说“告诉我到目前为止已读取了多少字节的输入,并将其存储在下一个参数中(必须是指向int的指针)”。通过将它放在格式字符串的末尾,我们可以计算出解析了多少输入。另请注意,我在%d之后添加了换行符,以便我们在第一个整数之后吃掉空格;否则,当我们尝试阅读"age 2"时,它会看到下一个换行符而不是字符a,并且解析会失败,因为那不匹配。

答案 1 :(得分:1)

  1. 您是否从sscanf()
  2. 检查了退货状态
  3. 您希望字符串中的'x'转换为哪个数字?
  4. 由于每次调用sscanf()都从头开始,'Age2:'与'Age1:'不匹配,因此转换失败。
  5. 请注意,格式字符串中不属于转换说明符的任何字符都必须完全匹配。因此,当扫描看到'Age2'的2时,它会在字符串中找到'Age1'中的1,并且扫描在该点处失败并且不匹配。唯一的例外是空白区域与任何白色空间序列匹配 - 请参阅下面的代码。

    示例代码:

    #include <stdio.h>
    
    int main(void)
    {
        const char string[] = "Age1: 3\r\nAge2: 5\r\n";
        const char *scan[] = { "Age1: %d", "Age2: %d", "Age1: %d Age2: %d" };
        int age1, age2;
        int rc;
    
        if ((rc = sscanf(string, scan[0], &age1)) != 1)
            printf("scan failed on '%s'\n", scan[0]);
        else
            printf("scan passed on '%s' - age %d\n", scan[0], age1);
    
        if ((rc = sscanf(string, scan[1], &age2)) != 1)
            printf("scan failed on '%s'\n", scan[1]);
        else
            printf("scan passed on '%s' - age %d\n", scan[1], age2);
    
        if ((rc = sscanf(string, scan[2], &age1, &age2)) != 2)
            printf("scan failed on '%s'\n", scan[2]);
        else
            printf("scan passed on '%s' - age1 %d, age2 %d\n", scan[2], age1, age2);
    
        return 0;
    }
    

    示例输出

    scan passed on 'Age1: %d' - age 3
    scan failed on 'Age2: %d'
    scan passed on 'Age1: %d Age2: %d' - age1 3, age2 5
    

答案 2 :(得分:1)

使用sscanf不会像流一样更改字符串,所以在sscanf的第二次调用中,它将开始将age2与age1匹配,并且由于它不匹配,因此不会读取该值。

您可以在第一次阅读内容后进行第二次阅读,也可以一次阅读:

sscanf(string, "age1: %d \n\r age2: %d", &i, &j);

答案 3 :(得分:0)

在完成阅读第一行后,字符串无法记住sscanf的位置。 (如果你想要,你可能想看一下返回值并自己记住它。)

但你可以在一个电话中完成:

sscanf(string, "age1: %d age2: %d", &i, &j);

答案 4 :(得分:-1)

如果你只限于c(即不能使用std :: getline),那么最简单的方法是一次读取一个字符的数据并自己解析。

您可以使用atoi和atof转换任何数字