虽然开发了一个小程序来扫描英文单词行中的关键数据项,但我选择了sscanf()来解析该行。由于每行中存在未知数目的单词,因此必须使用请求中指定的最大可能字段数来调用sscanf()。这导致一个长而丑陋的单行语句。一种更干净的技术是使用sscanf()在编程的循环中一次获取一个单词。不幸的是,不可能知道有多少空间sscanf()跳过以获得下一个字段。因此,不可能使用一个字符串指针再次调用sscanf(),该字符串指针反映了上一次调用中sscanf()保留的确切位置。代码示例如下。两个问题:1)我在使用sscanf()时是否缺少某些东西?和2)在c中有更好的方法吗?
#include <stdio.h>
#include <string.h>
/*
* using sscanf to parse a line (null terminated string) with fields (words)
* separated by one or more spaces into an array of words (fields).
*/
void main()
{
int i,j;
int idx;
char string[100] = "word1 word2 word3 word4 word5 word6 word7\0";
char fields[20][10];
#if 1
j=sscanf (&string[0], "%s%s%s%s%s%s", &fields[0][0], &fields[1][0], &fields[2][0], &fields[3][0], &fields[4][0], &fields[5][0]);
printf("sscanf returned: %d\n",j);
#else
/*
* this would be the preferred way to parse a long line of words,
* but there is no way to know with certainty how many spaces sscanf
* skipped over to obtain the next string (word). A modified version
* of sscanf that either modified an integer pointer argument or
* updated the pointer to the input string (line) would allow
* subsequent calls to pick up where the last sscanf call left off.
*
*/
for (i=0,idx=0;i<6;i++){
j=sscanf (&string[idx], "%s", &fields[i][0]);
idx += strlen(&fields[i][0]);
printf("sscanf returned: %d\n",j);
if (j==0)
break;
}
#endif
for (i=0;i<6;i++){
printf("%s",&fields[i][0]);
}
printf("\n");
return;
}
在用作初始化程序的字符串文字中
char string[100] = "word1 word2 word3 word4 word5 word6 word7\0";
显式终止零是多余的。字符串文字与显式终止零分开,已经包含终止零。
您在这里。
#include <stdio.h>
int main(void)
{
char string[100] = "word1 word2 word3 word4 word5 word6 word7";
char s[10];
const char *p = string;
for ( int n = 0; sscanf( p, "%s%n", s, &n ) == 1; p += n )
{
puts( s );
}
return 0;
}
程序输出为
word1
word2
word3
word4
word5
word6
word7
另一种方法是使用标准功能strtok
或功能对strcspn
和strspn
。
例如
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[100] = "word1 word2 word3 word4 word5 word6 word7";
const char *delim = " \t";
const char *p = strtok( string, delim );
while ( p != NULL )
{
puts( p );
p = strtok( NULL, delim );
}
return 0;
}
程序输出与上面显示的相同。
这是一个使用标准功能strcspn
和strspn
的演示程序。
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[100] = "word1 word2 word3 word4 word5 word6 word7";
const char *delim = " \t";
for ( const char *p = string; *p; )
{
p += strspn( p, delim );
const char *q = p;
p += strcspn( p, delim );
int n = p - q;
if ( n ) printf( "%*.*s\n", n, n, q );
}
return 0;
}
再次输出将与上面显示的相同。
请注意,在这种情况下,提取的单词不以零结尾。因此,要将它们作为字符串复制到字符数组中,应使用memcpy
,然后在复制的字符后附加终止符零。