c - 使用 sscanf 从字符串中提取(可能为空)单词(以 "|"分隔)

标签 c

我想从字符串中提取单词。

我不想使用 strtok 因为它会破坏我的源字符串。另一件事是,我想知道是否可以在不使用循环的情况下完成我想做的事情。

这是我的代码示例。它成功读取第一个单词,但第二个和第三个单词仍为空。

char source[] = "XXX|YYY|ZZZ";

char word1[10] = "";
char word2[10] = "";
char word3[10] = "";

sscanf( source, "%[^|]s|%[^|]s|%s", word1, word2, word3 );

真的可以使用sscanf来做到这一点还是我走错了路?

更新:

看起来 user3121023 的答案不适用于空词。

char source[] = "XXX||ZZZ";

char word1[10] = "";
char word2[10] = "";
char word3[10] = "";

sscanf( source, "%[^|]|%[^|]|%s", word1, word2, word3 );

第三个词仍然为空。这种情况我该怎么办?

最佳答案

您的 sscanf() 格式不会清空子字符串,如果目标数组小于源字符串,也不会防止潜在的缓冲区溢出。

这是一个使用 strcspn() 和实用函数 strcpy_n 的解决方案:

#include <string.h>

char *strcpy_n(char *dest, size_t size, const char *src, size_t n) {
    if (size > 0) {
        if (n >= size)
            n = size - 1;
        memcpy(dest, src, n);
        dest[n] = '\0';
    }
    return dest;
}

...

    char source[] = "XXX||ZZZ";
    char word1[10], word2[10], word3[10] = "";

    size_t pos = 0, len;

    len = strcspn(source + pos, "|");
    strcpy_n(word1, sizeof(word1), source + pos, len);
    pos = pos + len + (source[pos + len] == '|');

    len = strcspn(source + pos, "|");
    strcpy_n(word2, sizeof(word2), source + pos, len);
    pos = pos + len + (source[pos + len] == '|');

    len = strcspn(source + pos, "|");
    strcpy_n(word3, sizeof(word3), source + pos, len);
    pos = pos + len + (source[pos + len] == '|');

...

您可以将上述代码包装到另一个实用函数 getfield() 中以分解更多代码:

/* returns non zero if there are more fields to parse */
int getfield(char *dest, size_t size, const char *source, size_t *ppos) {
    int has_separator = 0;
    size_t pos = *ppos;
    size_t len = strcspn(source + pos, "|");
    strcpy_n(dest, size, source + pos, len);
    pos += len;
    has_separator = (source[pos] == '|');
    *ppos = pos + has_separator;
    return has_separator;
}

 ...

    char source[] = "XXX||ZZZ";
    char word1[10], word2[10], word3[10];

    size_t pos = 0;

    /* parse the fields, empty and missing fields are set to "" */
    getfield(word1, sizeof(word1), source, &pos);
    getfield(word2, sizeof(word2), source, &pos);
    getfield(word3, sizeof(word3), source, &pos);

...

关于c - 使用 sscanf 从字符串中提取(可能为空)单词(以 "|"分隔),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49571394/

相关文章:

c++ - 具有显式大小的可用内存

c - 我如何跟踪内存分配?

C 中的 Python 风格迭代器

c - 尝试使用链接列表运行程序并收到 "Segmentation Fault 11"

c - 我在人脸识别系统中使用了“嵌套的if”语句。显示的代码中的“嵌套”是否正确?

c - 两个矩形的 union 。编写一个程序来找到包含 2 个给定矩形的最小可能矩形

c - 为目录中的所有文件添加头文件

c - 使用 strtok 从文件读取正确的 "format"时出现问题

c - 当我运行程序时,它无限次打印 126,ch 如何取值 126?

c - 如何在 ncurses 中获得亮白色?