sscanf字符串格式说明符不适用于'\ t'

时间:2014-04-18 16:26:00

标签: c std scanf stdio cstdio

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
char *tokenstring = "first,25.5,second,15";
int result, i;
double fp;
char o[10], f[10], s[10], t[10];
void main()
{
   result = sscanf(tokenstring, "%[^','],%[^','],%[^','],%s", o, s, t, f);
   printf("%s\n %s\n %s\n %s\n", o, s, t, f);
   fp = atof(s);
   i  = atoi(f);
   printf("%s\n %lf\n %s\n %d\n", o, fp, t, i);
}

以上代码不适用于&#39; \ t&#39;,为什么?它适用于this 我使用的是vc6.0

无效

char *tokenstring = "first\t25.5\tsecond\t15";



   result = sscanf(tokenstring, "%[^'\t'],%[^'\t'],%[^'\t'],%s", o, s, t, f);

2 个答案:

答案 0 :(得分:3)

查看您的格式匹配:

"%[^'\t'],%[^'\t']
 ^     ^ ^
 \     | \- match a literal comma
  \    |
   \---+- match a sequence not containing tab or ' (single quote), up to the next
          tab or single quite.

所以第一个%[..]匹配所有内容,不包括输入中的第一个标签,然后它尝试匹配与标签不匹配的逗号,因此失败。

最简单的解决方法是用空格替换字符串中的逗号,这将跳过空格(包括制表符)。使用制表符会做同样的事情,但会让人误以为你试图匹配制表符而不是跳过空格:

sscanf(tokenstring, "%[^\t] %[^\t] %[^\t]%s", o, s, t, f);

请注意,您可能也不希望在比赛中特别处理'个字符,除非您希望它们失败。

现在,如果您只想使用分隔符选项卡(而不仅仅是任何空格),则需要使用选项卡模式:

sscanf(tokenstring, "%[^\t]%*1[\t\]%[^\t]%*1[\t]%[^\t]%s", o, s, t, f);

模式%*1[\t]将完全匹配输入中的单个选项卡,而不是将其存储在任何位置。

这导致您可能已经注意到第一个(基于逗号的)scanf的另一个问题 - 像%[^,]%[^\t]这样的模式将不匹配空字符串 - 如果下一个字符在输入是,(或第二种情况下为\t),scanf将返回而不匹配任何内容(或以下任何模式),而不是存储空字符串。

此外,如果您的任何字符串对于数组而言太长,您将溢出并崩溃(或更糟)。因此,无论何时将scanf %s%[模式用于缓冲区,都应始终指定缓冲区大小:

sscanf(tokenstring, "%9[^,],%9[^,],%9[^,],%9s", o, s, t, f);

现在,当输入太长时,sscanf调用将只匹配字段的前9个字符,而不是崩溃或损坏,而是返回该字段的其余部分尚未被读取。

答案 1 :(得分:2)

当您使用逗号分隔字段时,您必须在格式字符串中添加,以便跳过它。同样适用于\t

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

void test1()
{
   char *tokenstring = "first,25.5,second,15";
   int result, i;
   double fp;
   char o[10], f[10], s[10], t[10];

   // -----------------------------------------------------------
   // make sure you add a , between the string format specifiers
   // -----------------------------------------------------------
   result = sscanf(tokenstring, "%[^,],%[^,],%[^,],%s", o, s, t, f);
   printf("%s\n %s\n %s\n %s\n", o, s, t, f);
   fp = atof(s);
   i  = atoi(f);
   printf("%s\n %lf\n %s\n %d\n", o, fp, t, i);
}

void test2()
{
   char *tokenstring = "first\t25.5\tsecond\t15";
   int result, i;
   double fp;
   char o[10], f[10], s[10], t[10];

   // -----------------------------------------------------------
   // make sure you add a \t between the string format specifiers
   // -----------------------------------------------------------
   result = sscanf(tokenstring, "%[^\t]\t%[^\t]\t%[^\t]\t%s", o, s, t, f);
   printf("%s\n %s\n %s\n %s\n", o, s, t, f);
   fp = atof(s);
   i  = atoi(f);
   printf("%s\n %lf\n %s\n %d\n", o, fp, t, i);
}

void main()
{
   test1();
   test2();
}