【问题标题】:Parse words with strtok使用 strtok 解析单词
【发布时间】:2014-11-11 21:20:00
【问题描述】:

我想对strtok() 说,除了字母数字字符之外的所有内容都用作分隔符。

我的尝试是ref的例子:

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}

但是,我将解析真实的文本文件(包含对网站的评论)。目前,我检查是否出现了其他分隔符,并增加了strtok() 的第二个参数。例如,我看到了[,所以我做了" ,.-[" 等等,但是好吧,我可能会遗漏一些东西,也许一个新的文本文件包含一个新的分隔符。

我不能做一些更聪明的事情(实际上是正确的,因为事实并非如此)吗?

例如,如果我得到:

[Hello_sir I'm George]

我想获得这些代币:

Hello
sir
I
m
George

问题是我不知道哪些是分隔符。

我想说除了字母数字字符之外的所有内容都用作分隔符。


编辑

我想逐个字符检查它是否是字母数字,但我希望有一些内置的东西,比如根据需要提供strtok()

【问题讨论】:

  • 也许你可以只使用isalpha char by char ? cplusplus.com/reference/cctype/isalpha
  • 哦,我也想过,让我更新@user2485710
  • stackoverflow.com/a/26243667/971127 因为没有所以做。
  • @BLUEPIXY,我也需要保留数字,我说 alphanumerical 有点害羞。你认为如果我将第二个参数作为第二个参数传递给你的函数isalnum() 就可以了吗?
  • @G.Samaras 会好的。

标签: c strtok


【解决方案1】:

使用strtok(不使用其他内容覆盖源字符串的非字母数字字符)的唯一方法是传递一个包含所有非字母数字字符的分隔符字符串。您可以像这样在第一次运行时构建一次:

static char delims[256]; /* this is oversized */

...

void
initdelims()
{
    int i;
    int j = 0;
    for (i = 1; i<256; i++)
    {
        if (!isalnum(i))
            delims[j++] = i;
    }
    delims[j] = 0; /* this is unnecessary as statics are initialised to zero */
}

然后使用delims 作为您的分隔符字符串。

但是,这既丑陋又低效。您最好编写一个手动解析器,如有必要,借用source to strtok

【讨论】:

  • 这正是我所想的。但是,出于可移植性的原因,您应该使用1 &lt;&lt; CHAR_BIT 而不是256。另外,为什么这会“效率低下”——我不确定它是否重要。它很可能不会。
  • strtok 将为每个字符遍历分隔符字符串的 200 多个字符。 isalpha IIRC 在固定位图中查找。所以 strtok 带有 200 多个字符的分隔符可能比手动滚动的要慢 200 倍,这并不好玩。
  • 这个不行,我刚测试过。但是,在问题的 cmets 中,我得到了一个自定义实现,它完全符合我的要求,所以我想我们也许应该删除我的问题(只有在你删除答案时才能这样做)。
  • 我认为问题在于 i=0 不是字母数字,所以 delims 为空。在源代码中修复了该问题。建议值得留给其他人(如果只是因为他们会学习手卷更有用)
【解决方案2】:

您可以在一个字符串中一次性收集非字母数字字符,然后将该字符串用作strtok() 的分隔符集:

char delims[(1 << CHAR_BIT) + 1] = { 0 };
for (int i = 0, j = 0; i < sizeof delims - 1; i++) {
    if (!isalnum(i)) {
        delims[j++] = i;
    }
}

pch = strtok(str, delims);
while (pch != NULL)
{
    printf ("%s\n",pch);
    pch = strtok(NULL, delims);
}

【讨论】:

  • 很好地使用isalnum(),但请注意CHAR_BITstackoverflow.com/questions/19708810/…。我用的是256+1,代码不行。
  • 我用了256+1,代码不行,我刚测试过。但是,在问题的 cmets 中,我得到了一个自定义实现,它完全符合我的要求,所以我想我们也许应该删除我的问题(只有在你删除答案时才能这样做)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多