带有无效定界符的字符串标记化
String tokenization with nullifying delimiters
strsep()
在其手册页中的描述指出,在到达第一个分隔符时,
This token is terminated by overwriting the delimiter with a null byte ('[=11=]'
), and *stringp
is updated to point past the token.
其中 *stringp
是输入字符串。
我想知道是否有任何函数可以简单地更新 *stringp
以指向令牌而不用 '[=11=]'
替换定界符。我有 3 个可能的定界符,我可以将其作为 " \t\n"
输入到 strsep()
,所以像 strchr()
这样只会搜索单个定界符的东西将不起作用(至少效率不高) .由于我需要稍后打印出完整的字符串,否则我必须执行 memcpy()
以便稍后打印字符串。
(另外,谁能解释一下为什么这样实现..?)
下面是一个实现:
token = non_nulling_strsep(char** stringp, const char* delims);
与 strsep
非常相似,只是它将 *stringp
设置为实际终止标记的定界符,而不是后面的字符。与 strsep
不同,这意味着您可以指望 *stringp - token
是令牌的长度,这很有用,因为令牌不是空终止的,就像 strsep
一样。如果字符串中没有更多的标记,*stringp - token
将为 0,因此这是您应该测试以结束标记扫描循环的条件。
char* non_nulling_strsep (char** stringp, const char* delims) {
char* token = *stringp + strspn(*stringp, delims);
*stringp = token + strcspn(token, delims);
return token;
}
您可以像这样扫描令牌:
{
char *end = buffer;
for (char *token = non_nulling_strsep(&end, " \t\n");
end - token;
token = non_nulling_strsep(&end, " \t\n")) {
printf("Found '%.*s'\n", end - token, token);
}
}
这是另一个可能的界面,可能效果更好。这个 returns 长度(如果没有更多标记则为 0)并将字符串指针设置为下一个标记的开头(如果没有更多标记则为字符串末尾)。
size_t next_token(char** tokenp, const char* delims) {
*tokenp += strspn(*tokenp, delims);
return strcspn(*tokenp, delims);
}
有了这个,你可以像这样循环:
{
char *token = buffer;
for (size_t token_len;
(token_len = next_token(&token, " \t\n"));
token += token_len) {
printf("Found '%.*s'\n", token_len, token);
}
}
strsep()
在其手册页中的描述指出,在到达第一个分隔符时,
This token is terminated by overwriting the delimiter with a null byte (
'[=11=]'
), and*stringp
is updated to point past the token.
其中 *stringp
是输入字符串。
我想知道是否有任何函数可以简单地更新 *stringp
以指向令牌而不用 '[=11=]'
替换定界符。我有 3 个可能的定界符,我可以将其作为 " \t\n"
输入到 strsep()
,所以像 strchr()
这样只会搜索单个定界符的东西将不起作用(至少效率不高) .由于我需要稍后打印出完整的字符串,否则我必须执行 memcpy()
以便稍后打印字符串。
(另外,谁能解释一下为什么这样实现..?)
下面是一个实现:
token = non_nulling_strsep(char** stringp, const char* delims);
与 strsep
非常相似,只是它将 *stringp
设置为实际终止标记的定界符,而不是后面的字符。与 strsep
不同,这意味着您可以指望 *stringp - token
是令牌的长度,这很有用,因为令牌不是空终止的,就像 strsep
一样。如果字符串中没有更多的标记,*stringp - token
将为 0,因此这是您应该测试以结束标记扫描循环的条件。
char* non_nulling_strsep (char** stringp, const char* delims) {
char* token = *stringp + strspn(*stringp, delims);
*stringp = token + strcspn(token, delims);
return token;
}
您可以像这样扫描令牌:
{
char *end = buffer;
for (char *token = non_nulling_strsep(&end, " \t\n");
end - token;
token = non_nulling_strsep(&end, " \t\n")) {
printf("Found '%.*s'\n", end - token, token);
}
}
这是另一个可能的界面,可能效果更好。这个 returns 长度(如果没有更多标记则为 0)并将字符串指针设置为下一个标记的开头(如果没有更多标记则为字符串末尾)。
size_t next_token(char** tokenp, const char* delims) {
*tokenp += strspn(*tokenp, delims);
return strcspn(*tokenp, delims);
}
有了这个,你可以像这样循环:
{
char *token = buffer;
for (size_t token_len;
(token_len = next_token(&token, " \t\n"));
token += token_len) {
printf("Found '%.*s'\n", token_len, token);
}
}