C 使用strtok发出比较strtok函数嵌套结果中两个单词的问题

C 使用strtok发出比较strtok函数嵌套结果中两个单词的问题,c,C,我正在寻找将一个数组中的单词与另一个数组中字典中的单词进行比较,以查找找到的最大单词数 我使用strtok,因为两者中的单词都用空格分隔,但它不起作用。我需要你的帮助 void chercherScoreMotDansDico(char msgBootforce [], int* maxCorrepondance, char* mot, char* dicoActuel, char* bonResultatBootforce) { int i = 0; char*

我正在寻找将一个数组中的单词与另一个数组中字典中的单词进行比较,以查找找到的最大单词数

我使用strtok,因为两者中的单词都用空格分隔,但它不起作用。我需要你的帮助

 void chercherScoreMotDansDico(char msgBootforce [], int* 
 maxCorrepondance, char* mot, char* dicoActuel, char* 
 bonResultatBootforce) {
     int i = 0;
     char* motdico = NULL;
     char tmpMsgBootForce [3000] = {0};

     strcpy(tmpMsgBootForce, msgBootforce);

     mot = strtok (tmpMsgBootForce, " ");

     while (mot != NULL) {
          motdico = strtok (dicoActuel, " ");

          while (motdico != NULL) {
              if (strcmp(mot,motdico) == 0)   ++i;
              motdico = strtok (NULL, " ");
          }

          mot = strtok (NULL," ");  
    }

    if (i > *(maxCorrepondance)) {
        *(maxCorrepondance) = i;
        strcat(bonResultatBootforce, msgBootforce);
    }   
 }

不能在两个不同的字符串上同时使用
strtok()
strtok()
有一个内部指针,用于存储正在处理的当前字符串的地址。如果使用字符串调用strtok(),然后使用不同的字符串调用strtok(),则执行strtok(NULL,delim)时,它将继续使用指定的最后一个字符串

此函数具有破坏性:它将“\0”字符写入 字符串str的元素。特别是,不能使用字符串文本 用作strtok的第一个参数。对strtok的每次调用都会修改 静态变量:不是线程安全的。与大多数其他标记化者不同, strtok中的分隔符对于每个后续标记都可能不同, 甚至可以依赖于前面标记的内容。这个 strtok_s函数与POSIX strtok_r函数的不同之处在于保护 防止存储在被标记的字符串之外,并通过检查 运行时约束


有一个新版本的
strtok()
函数
strtok_()
,它有一个指针变量地址的附加参数,以代替
strtok()
使用的内部指针变量。

不能同时对两个不同的字符串使用
strtok

strtok(string,delim)
在内部存储其在字符串中的位置,以便将来调用
strtok(NULL,delim)
。它一次只能记住一个
strtok(tmpMsgBootForce,“”)
表示要查看
tmpMsgBootForce
,然后
motdico=strtok(dicoActuel,“”””)
dicoActuel
覆盖它


改为使用什么取决于编译器。是的,但这是2011年的标准,大多数Unix编译器都会理解这一点。最后

它们的工作方式基本相同。在迭代的每个字符串中手动存储位置

这里使用的是
strtok\u r
next_tmpMsgBootforce
next_dicoActuel
分别保持解析
tmpMsgBootforce
dicoActuel
的位置

 char *next_tmpMsgBootforce;
 char *next_dicoActuel;

 strcpy(tmpMsgBootForce, msgBootforce);

 mot = strtok_r(tmpMsgBootForce, " ", &next_tmpMsgBootforce);

 while (mot != NULL) {
      motdico = strtok_r(dicoActuel, " ", &next_dicoActuel);

      while (motdico != NULL) {
          if (strcmp(mot,motdico) == 0)   ++i;
          motdico = strtok_r(NULL, " ", &next_dicoActuel);
      }

      mot = strtok_r(NULL," ", &next_tmpMsgBootforce);  
}
因为这一切都是一团糟,所以我建议使用诸如之类的库来消除这些不兼容和不安全的函数


作为旁注,
strcpy
strcat
不安全。如果它们的目标没有足够的空间,它将尝试在其内存边界之外写入。与strtok一样,安全地执行此操作的情况也是一团糟。还有非标准但无处不在的
strlcpy
strlcat
。有标准,但不是普遍存在的。值得庆幸的是,VisualStudio遵循了这一标准

在POSIX系统上,您可以使用
strdup
复制字符串。它将为您处理内存分配

char *tmpMsgBootForce = strdup(msgBootForce);
需要注意的是,您必须在函数结束时
释放
此内存

安全地执行strcat会变得复杂。让我们通过将其拆分为两个函数来简化它。一个人做搜索

int theSearching(
    const char *msgBootforce,
    const char *dicoActuel
) {
     int i = 0;
     char *next_tmpMsgBootforce;
     char *next_dicoActuel;

     char *tmpMsgBootForce = strdup(msgBootforce);
     char *tmpDicoActuel = strdup(dicoActuel);

     char *mot = strtok_r(tmpMsgBootForce, " ", &next_tmpMsgBootforce);

     while (mot != NULL) {
          char *motdico = strtok_r(tmpDicoActuel, " ", &next_dicoActuel);

          while (motdico != NULL) {
              if (strcmp(mot,motdico) == 0) {
                  ++i;
              }
              motdico = strtok_r(NULL, " ", &next_dicoActuel);
          }

          mot = strtok_r(NULL," ", &next_tmpMsgBootforce);  
    }

    return i;
}
还有一个做附加。此函数确保有足够的空间进行串联

char *tryAppend( char *dest, const char *src, int *maxCorrepondance, const int numFound ) {
    char *new_dest = dest;

    if (numFound > *maxCorrepondance) {
        *(maxCorrepondance) = numFound;

        // Allocate enough memory for the concatenation.
        // Don't forget space for the null byte.
        new_dest = realloc( dest, strlen(dest) + strlen(src) + 1 );
        strcat( new_dest, src);
    }

    // Return a pointer to the reallocated memory,
    // or just the old one if no reallocation was necessary.   
    return new_dest;
}
然后一起使用它们

int numFound = theSearching(msgBootforce, dicoActuel);
bonResultatBootforce = tryAppend(bonResultatBootforce, msgBootforce, &maxCorrepondance, numFound);

进一步回答,为了安全起见,使用msgBootforce进行strcpy,应该对dicoActuel进行同样的操作。或者,由于使用一对指针和一个简单的调用
strchr
就可以将每个单词括起来。(或使用strcspn/strspn
)。这两个函数都可以安全地用于字符串文本。我的编译器不可能:警告:函数“strtok_r”的隐式声明;你是说“斯特克”吗?[-Wimplicit function declaration]你知道如何从msgBootforce[]中找到一个出现在数组*dicoActuel中的单词,而不使用strtok_s或strtok_r,因为它不能与我的编译器一起工作吗?@H_B是的,使用Glib的g_strsplit。我强烈建议在产品C代码中使用GLib或类似的库。它解决了C语言的许多问题,并提供了许多缺少的功能。@H_B这是什么编译器?奇怪的是,编译器两者都没有。您是否在编译时使用了迫使它使用旧版本C的标志?@Schwen gcc-Wall-pedantic-std=c11-lm-O2