用sscanf读取字符串的剩余部分

时间:2014-03-28 19:32:27

标签: c string scanf

我正在尝试读取一个字符串,该字符串由一组数字后跟一个字符串组成,并包含一些其他基本文本。

换句话说,行的格式是这样的:

Stuff<5,10,-5,8,"Test string here.">

天真地,我试过了:

sscanf(str,"Stuff<%d,%d,%d,%d,\"%s\">",&i1,&i2,&i3,&i4,str2);

但经过一些研究后,我发现%s应该在到达空白字符时停止解析。我找到this question,但没有一个答案解决了我遇到的问题:字符串中可能包含任何字符,包括换行符和正确转义的引号。后者不是问题,如果我可以让sscanf在我提供的预分配缓冲区中将第一个引号之后的所有内容放入,我可以自行删除结束。

但是我该怎么做?我不能使用%[],因为它需要一些东西来终止字符串,我唯一想要终止它的是null终止符。所以我想,“嘿,我只会使用空终结器!”但是%[\0]让编译器变得脾气暴躁:

warning: no closing ‘]’ for ‘%[’ format
warning: embedded ‘\0’ in format
warning: no closing ‘]’ for ‘%[’ format
warning: embedded ‘\0’ in format

使用像%*c这样的东西也行不通,因为我不确切知道需要采取多少个字符。我尝试传递strlen(str),因为它会小于sscanf,但是str2会返回4并且没有任何内容被放入sscanf(str,"Stuff<%d,%d,%d,%d,\"%n",&i1,&i2,&i3,&i4,&n); str2 = str+n; ,这表明可能因为长度太长而放弃并且没有'打扰。

更新:我想我可以做类似的事情:

{{1}}

3 个答案:

答案 0 :(得分:2)

您的更新似乎是一个很好的答案。在使用strchr获取sscanfi1之后,我建议i4查找第一个引号char的位置。请注意,您应始终检查sscanf的返回值,以确保转化有效。对于您建议的答案,这一点更为重要,因为如果前四次转换不成功,n将保持未初始化状态。

答案 1 :(得分:1)

扫描'\"',然后扫描所有内容'\"',然后再扫描'\"'

请务必检查sscanf()结果并限制测试字符串的长度。

char test_string[100];
int n = 0;
if (sscanf(str, "Stuff<%d,%d,%d,%d, \"%99[^\"]\"> %n",
      &i1, &i2, &i3, &i4, test_string, &n) == 5 && str[n] == '\0') Good();

"...%[\0]..."观点来看,您使用sscanf()的尝试为"...%["
<{1}} on格式的所有内容都会被忽略。

使用"\0",将int n = 0附加到格式字符串,将" %n"附加到参数并检查&n是一个巧妙的技巧str[n] == '\0'来确保整行解析正确。注意:sscanf()不会添加到"%n"结果。

答案 2 :(得分:-1)

这不是实现您想要实现的目标的唯一方法,但可能是最好的方法:您需要使用 scansets 。我不会直接用这个答案告诉你解决方案,我将解释如何使用扫描集,据我所知,你希望自己能够自己做。

在分配时,

Scansets %[...]%s类似,它们将值解释为字符并将其存储到字符数组中。 %s以空格终止,%[...]是该版本的灵活版本。

使用扫描集有两种方法,第一种方法是没有前一个插入符号^,第二种方法是使用前一个插入符号^

当您使用没有前一个插入符^的扫描集时,放在括号内的字符将是唯一将被读取,存储然后留下的字符。只要scanf遇到不匹配的字符,%[...]就会结束。例如:

// input: asdasdasdwasdasd
char s[100] = { 0 };
scanf( "%[das]", s );
printf( "%s", s );
// output: asdasdasd

将scanset与前一个插入符^一起使用时,搜索将被反转。它会读取,存储和留下每个角色,直到它到达您在前一个插入符^之后放下的任何一个角色。例如:

// input: abcdefgh^kekQ
char s[100] = { 0 };
scanf( "%[^Q^]", s );
printf( "%s", s );
// output: abcdefgh

请注意,仍然要在流内读取剩余字符,文件指针不会超出导致终止的字符。即对于第一个,getchar( );会给出'w',而对于第二个,它会给出'^'

我希望这就足够了。如果你仍然找不到出路,请你离开,我可以给你一个解决方案。