【问题标题】:Using strtok to find pair of token使用 strtok 查找一对令牌
【发布时间】:2021-08-19 14:01:33
【问题描述】:

我正在解决这个家庭作业问题:在文本中找到一对相邻的单词,使得两个单词以同一个字母开头。

我知道我需要使用strtok函数来解决这个问题。

#include <string.h>
#include <stdio.h>
#include <conio.h>
int main(void) {
    char testString[] = "In the end, we will remember not the words of our enemies, but the silence of our friends";
    char *context = testString;
    const char *token = strtok_s(testString, ", ", &context);

    while (token) {
            token = strtok_s(NULL, ", ", &context);
            printf(" %s\n", token);
        }
    _getch();
}

在这种情况下,我有两个问题:

  1. 我不明白为什么printf从第二个单词开始打印?
  2. 接下来我需要做什么来查找单词对,如何访问令牌字母?

【问题讨论】:

    标签: c split char c-strings strtok


    【解决方案1】:

    您想找到两个连续的标记,它们具有相同的初始字符​​em>,对吧?

    因此,您需要在检索下一个令牌时存储上一个令牌,以便您可以比较它们的初始字符并可能打印它们。

    已编辑:您对strtok_s 的使用似乎不正确。我在下面的代码中修正了我的错误并且strtok_s的错误使用替换为strtok的正确使用。

    #include <string.h>
    #include <stdio.h>
    
    int main(void) {
        char testString[] = "In the end, we will remember not the words of our enemies, but the silence of our friends";
        const char *token_prev = strtok(testString, ", ");
        const char *token_next = strtok(NULL, ", ");
    
        while (token_next) {
            if (token_next[0] == token_prev[0]) {
                printf(" %s %s\n", token_prev, token_next);
                // break; // to print the first pair only
            }
            token_prev = token_next;
            token_next = strtok(NULL, ", ");
        }
    }
    

    在 GodBolt 看到它的工作:https://godbolt.org/z/YzjcPKrq6

    这将遍历整个输入字符串并打印找到的所有对。如果您在if() 下的printf() 之后添加break;,那么它将只打印第一对。

    【讨论】:

    • 做得很好。但是有人编辑了我的问题,任务实际上是:第二个单词的最后一个字母等于第一个单词的第一个字母。所以我可以使用以下表达式: if (token_next[strlen(token_next) - 1] == token_prev[0]) but nothing come right
    • @КириллБоровой 您对strtok_s 的使用似乎不正确。我在上面的代码中修正了我的错误strtok_s的错误使用替换为strtok的正确使用。看看它在 GodBolt 上的工作。
    • @КириллБоровой 关于任务定义,你写了 '在文本中找到一对给邻居的单词,第二个单词的开头与第一个单词的开头相同with.' - 显然这两个词都必须以相同的字母开始(如您所见here)。
    • @КириллБоровой 至于您在评论中提出的更改(第一个标记的第一个字母和第二个标记的最后一个字母必须相等):是的,当应用于固定代码。请看这里:godbolt.org/z/zdbbcvoeq
    • 是的!!!!这很好,完美运行。你是巫师!
    【解决方案2】:
    1. printf 从第二个单词开始打印,因为您从不打印第一个令牌,即您在进入循环之前从初始调用 strtok_s 获得的那个。
    2. Token 是一个常规的 C 字符串。它的首字母是token[0],一个char。您可以将其存储在单独的 char 变量中,并将其带到循环的下一次迭代中。
    3. 由于单词可能是混合大小写的,因此在存储和比较初始字符时可能应该使用touppertolower

    【讨论】:

      【解决方案3】:

      您提取了此语句中的第一个单词

      const char *token = strtok_s(testString, ", ", &context);
      

      但你没有打印出来。在循环中先前调用 strtok_s 之后,您开始在 while 循环中打印单词。

      您需要两个指向相邻提取字符串的指针,并使用这些指针可以比较字符串的第一个字母。

      这是一个演示程序(为简单起见,我使用 strtok 而不是 strtok_s)

      #include <stdio.h>
      #include <string.h>
      
      int main(void) 
      {
          char testString[] = "In the end, we will remember not the words "
                              "of our enemies, but the silence of our friends";
                              
          char *first_word  = NULL;
          char *second_word = NULL;
          
          const char *delim = ", ";
          
          if ( ( first_word = strtok( testString, delim ) ) != NULL )
          {
              while ( ( second_word = strtok( NULL, delim ) ) != NULL && 
                      *first_word != *second_word )
              {
                  first_word = second_word;           
              }
          }
          
          if ( second_word != NULL )
          {
              printf( "%s <-> %s\n", first_word, second_word );
          }
          
          return 0;
      }
      

      程序输出是

      we <-> will
      

      如果你想输出所有这样的单词对,那么程序可以如下所示

      #include <stdio.h>
      #include <string.h>
      
      int main(void) 
      {
          char testString[] = "In the end, we will remember not the words "
                              "of our enemies, but the silence of our friends";
                              
          char *first_word  = NULL;
          char *second_word = NULL;
          
          const char *delim = ", ";
          
          if ( ( first_word = strtok( testString, delim ) ) != NULL )
          {
              while ( ( second_word = strtok( NULL, delim ) ) != NULL )
              {
                  if ( *first_word == *second_word )
                  {
                      printf( "%s <-> %s\n", first_word, second_word );
                  }
                  first_word = second_word;           
              }
          }
      
          return 0;
      }
      

      程序输出是

      we <-> will
      of <-> our
      of <-> our
      

      但是,与其使用strtokstrtok_s,不如使用基于函数strspnstrcspn 的方法要好得多。在这种情况下,您可以处理常量字符串。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-17
        • 2015-10-06
        • 2021-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多