奇怪的sscanf行为

时间:2013-10-28 20:14:47

标签: c

我试图遍历字符串并除以标签分隔的单词。

if(argc == 1) {
    while (argc == 1) {
        scanf("%s", ent);
        printf("<tr>");
        while (sscanf(ent, "%[^\t]%n", piece, &n) == 1 ) {           
            printf("<td>%s</td>", piece);
            ent += n;
        }
        printf("</tr>");
    }
}

当我运行此代码而不是<tr><td>a</td><td>b</td><td>c</td></tr>时 我得<tr><td>a</td></tr><tr><td>b</td></tr><tr><td>c</td></tr>  当我给出了一个\ tb \ tc \ n的stdin 这意味着在内部while循环结束并且外部循环运行一次之后位置移位。内部while循环不应该遍历所有字符串吗?我只能使用 sscanf strtol 作为字符串遍历分隔符。

3 个答案:

答案 0 :(得分:1)

如果您要对字符串进行标记,请使用strtok(3)代替sscanf(3)

char *piece = strtok(ent, "\t");
while (piece)
{
    printf("<td>%s</td>", piece);
    piece = strtok(NULL, "\t");
}

你应该使用fgets(3)代替scanf(3)来获取字符串输入。

答案 1 :(得分:0)

scanf("%s"读取以空格分隔的字符串 - 因此在您的示例中,第一个调用读取字符串a(当它看到制表符时停止 - 空格)。如果您想要读取整行(空白和所有行),请改用fgets

答案 2 :(得分:0)

这是因为你没有跳过标签。 %[^\t]%n将跨越所有非标签字符并对其进行计数,然后ent += n将跳过这些字符,然后您将在标签处重新启动。

忽略前导空格更容易(并且使用html它根本不是坏事):

while (sscanf(ent, " %[^\t]%n", piece, &n) == 1 )
//                  ^ skip spaces
        printf("<td>%s</td>",piece);
        ent += n;
}

或者,如果由于某种原因,您必须只有一个终止选项卡,

while (sscanf(ent,"[^\t]%n", piece, &n) ==1) {
        printf("<td>%s</td>",piece);
        ent+=n;
        if (*ent) ++ent;
}

如果周围没有超临界小贩,这很有用:

int scanned=0;
while ( sscanf( ent+=scanned,"%[^\t]%n%*c%n", piece, &scanned, &scanned) > 0 )
        printf("<td>%s</td>",piece);

不要倾听那些不喜欢%n的人,他们只是%n ay-sayers: - )