【问题标题】:String tokenization with nullifying delimiters带有无效分隔符的字符串标记化
【发布时间】:2015-10-02 00:01:23
【问题描述】:

strsep() 在其手册页中的描述指出,在到达第一个分隔符时,

通过用空字节 ('\0') 覆盖分隔符来终止此标记,并更新 *stringp 以指向该标记。

其中*stringp 是输入字符串。

我想知道是否有任何函数可以简单地更新*stringp 以指向令牌而不用'\0' 替换分隔符。我有 3 个可能的分隔符,我可以将它们作为 " \t\n" 输入到 strsep(),所以像 strchr() 这样只会搜索单个分隔符的东西不起作用(至少效率不高)。由于我需要稍后打印出完整的字符串,否则我必须执行 memcpy() 以便稍后打印字符串。

(另外,谁能解释一下为什么要这样实现..?)

【问题讨论】:

  • strchr 是您要找的吗?你的问题和你的标题有什么关系?
  • 修复了标题,它来自其他东西...至于 strtchr,这会起作用,除了我有 3 个潜在的分隔符要搜索,我可以将其输入 strsep 为" \t\n"; strchr 只搜索一个字符。我会更新问题以反映这一点。
  • @BLUEPIXY,不幸的是,如果字符串恰好以我的任何分隔符开头,它将返回长度 0;该字符串由用户输入组成,因此用户可以输入任何内容
  • 我认为返回0的长度也没有问题。因为它会被程序处理。(如strsep

标签: c tokenize c-strings


【解决方案1】:

这是一个实现:

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

这是另一个可能的界面,它可能会更好。这个返回长度(如果没有更多的标记,则为 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);
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-18
    • 2016-11-15
    • 2014-07-08
    相关资源
    最近更新 更多