首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >strtok/strtok_r在中间停止解析

strtok/strtok_r在中间停止解析
EN

Stack Overflow用户
提问于 2015-09-04 09:27:16
回答 1查看 522关注 0票数 0

strtok_r在解析时将空字符放入输入字符串的不同位置。只有在strtok_r返回NULL之后才还原原始字符串。

如果我需要在长字符串开头的某个地方提取一个标记呢?如果我离开循环,则输入字符串仍会中断。我可以尝试手动恢复分隔符,但我不知道它是否是最后一个标记。问题是saveptr值没有文档化。

代码语言:javascript
复制
void extract_nth_token(char *res, size_t reslen, char *str, const char *delim, int n) {
  int i;
  char *token;
  char *save_ptr;

  token = strtok_r(str, delim, &save_ptr);
  for(i = 0; token != NULL; i++) {
    token = strtok_r(NULL, delim, &save_ptr);
    if (i == n) {
      snprintf(res, reslen, "%s", token);
      /* token[strlen(token)] = delim[0]; */
      /* break; */
    }
  }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-09-04 11:00:16

strtok()和strtok_r()是可怕的函数:

  • 它们修改输入字符串。
  • 它们将连续分隔符视为一个分隔符,这可能是跳过空白时使用的,但在解析.CSV (或以制表符分隔的)输入时则不打算这样做。

最好完全避免strtok()和strtok_r(),并使用strspn()和strcspn()。下面的函数就是这样做的。返回值类似于snprintf():找到的令牌中的字符数(不包括终止的NUL字节)。

  • 如果没有token#n:'\0‘被写入缓冲区并返回0
  • 如果缓冲区太小,对于找到的令牌加上终止的NUL字节,'\0‘将写入缓冲区,并返回令牌长度
  • 缓冲区是否足够大,令牌+ '\0‘被写入它,并返回strlen(令牌)。
代码语言:javascript
复制
#include <stdio.h>
#include <string.h>

size_t extract_nth_token_ohne_strtok_r(char *res, size_t maxlen, const char *str, const char *delim, int n)
{
size_t pos, len;
int itok;

for (itok=0,pos=0; str[pos]; ) {
        len = strcspn(str+pos, delim);
        if (itok++ == n) {
                if (len < maxlen) memcpy(res, str+pos, len), res[len] = 0;
                else res[0] = 0;
                return len;
                }
        pos += len;
        if (str[pos]) pos++;
        }
res[0] = 0;
return 0;
}

int main(void)
{
char * omg = "zero one\ttwo \tfour\nfive" ;
char token[80];
size_t toklen;
int ii;

printf("\n## With a large enough buffer:\n" );
for (ii=0; ii < 7; ii++) {
        toklen = extract_nth_token_ohne_strtok_r(token, sizeof token
                , omg, " \t\n", ii);
        printf("%d: res=%zu \"%s\"\n" , ii, toklen, token );
        }

printf("\n## With 4-character buffer:\n" );
for (ii=0; ii < 7; ii++) {
        toklen = extract_nth_token_ohne_strtok_r(token, 4
                , omg, " \t\n", ii);
        printf("%d: res=%zu \"%s\"\n" , ii, toklen, token );
        }

return 0;
}

注意:如果您确实希望将连续的空白视为一个空格,则可以将if (str[pos]) pos++;替换为:

代码语言:javascript
复制
pos += strspn(str+pos, delim);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32394570

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档