int n = sscanf("string", "%s %[^, ]%*[, ]%s", word1, word2, word3);
n
中的返回值告诉您成功完成了多少分配。 %[^, ]
是一个否定的字符类匹配,可以找到一个不包含逗号或空格的单词(如果你喜欢,可以添加标签)。 %*[, ]
是找到逗号或空格但禁止分配的匹配项。
我不确定我会在实践中使用它,但它应该可以工作。但是,它没有经过测试。
也许更紧密的说明书是:
int n = sscanf("string", "%s %[^, ]%*[,]%s", word1, word2, word3);
不同的是,该非分配字符类只接受一个逗号。 sscanf()
在word2
后停止在任何空间(或EOS,字符串末尾),并在分配给word3
之前跳过空格。前一版允许第二个和第三个单词之间的空格代替逗号,这个问题并不严格允许。
由于pmg建议在评论中,分配转换规范应给予一个长度,以防止缓冲区溢出。请注意,长度不包含空终止符,因此格式字符串中的值必须小于数组大小(以字节为单位)。还请注意,printf()
允许您使用*
,sscanf()
等使用*
来动态指定大小来抑制分配。这意味着你手头专门创建的字符串任务:
char word1[20], word2[32], word3[64];
int n = sscanf("string", "%19s %31[^, ]%*[,]%63s", word1, word2, word3);
(Kernighan的&派克建议他们(优秀)的书'The Practice of Programming'动态格式格式字符串)
刚发现一个问题:给出"word1 word2 ,word3"
,它不会读取word3
。有治愈吗?
是的,这有一种治疗方法,它实际上也是微不足道的。在非赋值逗号匹配转换规范之前,在格式字符串中添加一个空格。因此:
#include <stdio.h>
static void tester(const char *data)
{
char word1[20], word2[32], word3[64];
int n = sscanf(data, "%19s %31[^, ] %*[,]%63s", word1, word2, word3);
printf("Test data: <<%s>>\n", data);
printf("n = %d; w1 = <<%s>>, w2 = <<%s>>, w3 = <<%s>>\n", n, word1, word2, word3);
}
int main(void)
{
const char *data[] =
{
"word1 word2 , word3",
"word1 word2 ,word3",
"word1 word2, word3",
"word1 word2,word3",
"word1 word2 , word3",
};
enum { DATA_SIZE = sizeof(data)/sizeof(data[0]) };
size_t i;
for (i = 0; i < DATA_SIZE; i++)
tester(data[i]);
return(0);
}
输出示例:
Test data: <<word1 word2 , word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2 ,word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2, word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2,word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
Test data: <<word1 word2 , word3>>
n = 3; w1 = <<word1>>, w2 = <<word2>>, w3 = <<word3>>
一旦“非分配字符类”只接受一个逗号,可以缩写,为在格式字符串文字逗号:
int n = sscanf(data, "%19s %31[^, ] , %63s", word1, word2, word3);
将其插入测试设备中会产生与以前相同的结果。请注意,所有代码均可从审阅中受益它可以经常(基本上总是)在其工作之后得到改进。
输入行是单个字符串吗?所以你必须从字符串中提取令牌(分隔符是空格和逗号),对不对? – vulkanino 2012-03-02 16:50:33
3个字符串,第一个分隔符是空格第二个分隔符逗号 – Nahum 2012-03-02 16:53:22
使用'sscanf'(以及所有'scanf'-family函数)的最正确方法就是不要使用它们..当然,也有例外,scanf的奇怪'恰好符合你的需求,但通常你最终不得不写一些黑客来解决它的行为,在这种情况下,你最好先编写自己的清理解析器。 – 2012-03-02 16:59:56