我有以下问题:
sscanf
没有以我想要的方式返回。
这是sscanf
:
sscanf(naru,
"%s[^;]%s[^;]%s[^;]%s[^;]%f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]"
"%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]"
"%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]",
&jokeri, &paiva1, &keskilampo1, &minlampo1, &maxlampo1,
&paiva2, &keskilampo2, &minlampo2, &maxlampo2, &paiva3,
&keskilampo3, &minlampo3, &maxlampo3, &paiva4, &keskilampo4,
&minlampo4, &maxlampo4, &paiva5, &keskilampo5, &minlampo5,
&maxlampo5, &paiva6, &keskilampo6, &minlampo6, &maxlampo6,
&paiva7, &keskilampo7, &minlampo7, &maxlampo7);
它正在扫描的字符串:
const char *str = "city;"
"2014-04-14;7.61;4.76;7.61;"
"2014-04-15;5.7;5.26;6.63;"
"2014-04-16;4.84;2.49;5.26;"
"2014-04-17;2.13;1.22;3.45;"
"2014-04-18;3;2.15;3.01;"
"2014-04-19;7.28;3.82;7.28;"
"2014-04-20;10.62;5.5;10.62;";
所有变量都存储为char paiva1[22]
等;但是,sscanf
并不能正确存储除城市以外的任何内容。我一直试图阻止;
处的每个变量。
任何帮助如何正确存储日期等的帮助将不胜感激。
或者,如果有更聪明的方法,我可以接受建议。
答案 0 :(得分:2)
存在多个问题,但BLUEPIXY遇到了第一个问题 - 扫描集符号不符合%s
。
格式的第一行是:
"%s[^;]%s[^;]%s[^;]%s[^;]%f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]"
就目前而言,它会查找以空格分隔的单词,然后是[
,^
,;
和]
(这是自我矛盾的;字符串后面的字符是字符串的空格或结尾。)
第一个修复方法是正确使用扫描设置:
"%[^;]%[^;]%[^;]%[^;]%f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]"
现在您遇到的问题是,第一个%[^;]
会扫描所有内容,直到字符串或第一个分号结束,第二个%[;]
不会留下任何内容。
"%[^;]; %[^;]; %[^;]; %[^;]; %f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]"
这会查找一个分号的字符串,然后是分号,然后是可选的空格,然后重复三个项目。除了增加一个长度来限制字符串的大小,防止溢出,这些都很好。 %f
没问题。以下材料再次查找奇数字符序列。
但是,当查看数据时,它似乎包含一个城市,然后是七组“日期加三个数字”。
使用结构数组(如果你已经使用过这些结构),或者一组4个并行数组和一个循环,你会做得更好:
char jokeri[30];
char paiva[7][30];
float keskilampo[7];
float minlampo[7];
float maxlampo[7];
int eoc; // End of conversion
int offset = 0;
char sep;
if (fscanf(str + offset, "%29[^;]%c%n", jokeri, &sep, &eoc) != 2 || sep != ';')
...report error...
offset += eoc;
for (int i = 0; i < 7; i++)
{
if (fscanf(str + offset, "%29[^;];%f;%f;%f%c%n", paiva[i],
&keskilampo[i], &minlampo[i], &maxlampo[i], &sep, &eoc) != 5 ||
sep != ';')
...report error...
offset += eoc;
}
另见How to use sscanf()
in loops。
现在您拥有可以管理的数据。这组29个单独命名的变量是一个可怕的想法;使用它们的代码将是可怕的。
请注意,扫描集转换规范将字符串限制为比jokeri
和paiva
数组元素的大小短的最大长度。
您可能合理地想知道代码在%c%n
之前使用&sep
和&eoc
的原因。有一个原因,但它很微妙。假设sscanf()
格式字符串是:
"%29[^;];%f;%f;%f;%n"
此外,假设数据中存在第三个数字丢失后的分号存在问题。对sscanf()
的调用会报告它已成功完成4次转换,但不会将%n
计为作业,因此您无法判断sscanf()
未找到分号,因此根本没有设置&eoc
;该值将从之前的sscanf()
调用中遗留下来,或者只是未初始化。通过使用%c
将值扫描到sep
,我们会在成功时返回5,我们可以确定%n
也是成功的。代码检查sep
中的值实际上是分号而不是其他内容。
您可能想要考虑在分号之前和%c
之前的空格。它们将允许转换一些其他数据字符串,否则将无法匹配。格式字符串中的空格(扫描集外部)表示可能出现可选空格的位置。
答案 1 :(得分:1)
我会使用strtok
函数将;
作为分隔符将字符串分解为多个部分。如此长的格式字符串可能是将来出现问题的根源。