使用sscanf解析一行中的一长行单词

问题描述 投票:2回答:1

虽然开发了一个小程序来扫描英文单词行中的关键数据项,但我选择了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;
}
c scanf extract c-strings word
1个回答
0
投票

在用作初始化程序的字符串文字中

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或功能对strcspnstrspn

例如

#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;
}

程序输出与上面显示的相同。

这是一个使用标准功能strcspnstrspn的演示程序。

#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,然后在复制的字符后附加终止符零。

© www.soinside.com 2019 - 2024. All rights reserved.