我应该得到一个输入行,可以是以下任何格式:
如何分离1,2和3个单词的情况并将数据放入正确的变量?
word1
word1 word2
word1 word2 , word3
word1 word2,word3
Run Code Online (Sandbox Code Playgroud)
我想到了类似的东西:
sscanf("string", "%s %s,%s", word1, word2, word3);
Run Code Online (Sandbox Code Playgroud)
但它似乎没有用.
我使用严格的C89.
Jon*_*ler 23
int n = sscanf("string", "%s %[^, ]%*[, ]%s", word1, word2, word3);
Run Code Online (Sandbox Code Playgroud)
返回值n告诉您已成功完成了多少个分配.这%[^, ]是一个否定的字符类匹配,它找到一个不包括逗号或空格的单词(如果你愿意,可以添加标签).该%*[, ]匹配的是找到一个逗号或空间,但抑制的分配.
我不确定我是否会在实践中使用它,但它应该可行.但是,它未经测试.
也许更严格的规范是:
int n = sscanf("string", "%s %[^, ]%*[,]%s", word1, word2, word3);
Run Code Online (Sandbox Code Playgroud)
不同之处在于非赋值字符类只接受逗号. sscanf()在任何空格(或EOS,字符串末尾)之后停止word2,并在分配之前跳过空格word3.上一版允许在第二个和第三个单词之间留一个空格来代替逗号,这个问题并不严格允许.
正如pmg在注释中所建议的那样,分配转换规范应该给出一个长度以防止缓冲区溢出.请注意,长度不包括空终止符,因此格式字符串中的值必须小于数组的大小(以字节为单位).另请注意,while printf()允许您动态指定大小*,sscanf()等*用于抑制赋值.这意味着您必须专门为手头的任务创建字符串:
char word1[20], word2[32], word3[64];
int n = sscanf("string", "%19s %31[^, ]%*[,]%63s", word1, word2, word3);
Run Code Online (Sandbox Code Playgroud)
(Kernighan&Pike建议在他们的(优秀的)"编程实践"或亚马逊编程实践 1999中动态格式化格式字符串.)
刚发现一个问题:给定
"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);
}
Run Code Online (Sandbox Code Playgroud)
示例输出:
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>>
Run Code Online (Sandbox Code Playgroud)
一旦'非赋值字符类'只接受逗号,您可以将其缩写为格式字符串中的文字逗号:
int n = sscanf(data, "%19s %31[^, ] , %63s", word1, word2, word3);
Run Code Online (Sandbox Code Playgroud)
将其插入测试安全带会产生与之前相同的结果.请注意,所有代码都受益于审核; 即使在工作之后,它也经常(基本上总是)得到改善.