我正在尝试读取一个字符串,该字符串由一组数字后跟一个字符串组成,并包含一些其他基本文本。
换句话说,行的格式是这样的:
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}}
答案 0 :(得分:2)
您的更新似乎是一个很好的答案。在使用strchr
获取sscanf
至i1
之后,我建议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'
,而对于第二个,它会给出'^'
。
我希望这就足够了。如果你仍然找不到出路,请你离开,我可以给你一个解决方案。