使用 strtok 查找令牌对

Using strtok to find pair of token

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

我知道我需要使用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. 接下来我需要做什么来找到单词对,我如何才能访问令牌的字母?
  1. printf 从第二个单词开始打印,因为您永远不会打印第一个标记,即您在进入循环之前从初始调用 strtok_s 获得的标记。
  2. Token 是一个普通的 C 字符串。它的首字母是token[0],一个char。您可以将其存储在单独的 char 变量中,并将其带入循环的下一次迭代。
  3. 由于单词可能是大小写混合的,因此在存储和比较初始字符时,您可能应该使用 touppertolower

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

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 的方法要好得多。在这种情况下,您可以处理常量字符串。

你想找到两个具有相同首字符的连续标记,对吗?

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

已编辑: 您对 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;,那么它将仅打印第一对。