我想从字符串中提取单词。
我不想使用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] = ' ';
}
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);
...