0

I am solving this homework problem: Find a pair of adjacent words in the text, such that both words begin in the same letter.

I understand that I need to use strtok function to solve this problem.

#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();
}

In that case I have two question:

  1. I don't understand why printf starting print from the second word?
  2. What I need to do next to find word pair, how I can get access to letters of token?
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

3 Answers3

2

You want to find two consecutive tokens which have the same initial character, right?

So you need to store the previous token when retrieving a next one, so that you can compare their initial characters and possibly print them.

Edited: your use of strtok_s seems incorrect. I fixed my mistake in the code below and replaced a wrong use of strtok_s with a correct use of 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, ", ");
    }
}

See it working at GodBolt: https://godbolt.org/z/YzjcPKrq6

This will iterate through the whole input string and print all pairs found. If you add a break; after printf() under if() then it will print the first pair only.

CiaPan
  • 9,381
  • 2
  • 21
  • 35
  • nicely done. But someone has edit my question and the task actualy is: the last letter of the second word is equal to the first letter of the first word. so may I use the following expression: if (token_next[strlen(token_next) - 1] == token_prev[0]) but nothing comes right – Кирилл Боровой Jun 01 '21 at 15:16
  • 1
    @КириллБоровой Your use of `strtok_s` seems incorrect. I fixed my mistake in the code above _and_ replaced a wrong use of `strtok_s` with a correct use of `strtok`. See it working at GodBolt. – CiaPan Jun 02 '21 at 06:39
  • 1
    @КириллБоровой What concerns the task definition, you wrote _'Find in the text a pair of words to a neighbor, the second of which begins with the same letter that the first of this pair begins with.'_ – clearly both words have to _begin_ with the same letter (as you can see [here](https://stackoverflow.com/revisions/67787703/1)). – CiaPan Jun 02 '21 at 06:45
  • 1
    @КириллБоровой As for the change you propose in your comment (the first letter of the first token and the last one of the second one must be equal) : yes, it works as desired when applied to the fixed code. Please see here: https://godbolt.org/z/zdbbcvoeq – CiaPan Jun 02 '21 at 06:49
  • YEAH!!!! That`s good, working perfectly. You are the wizard! – Кирилл Боровой Jun 02 '21 at 10:37
1
  1. printf starts printing from the second word because you never print the first token, i.e. the one you've obtained from the initial call to strtok_s before entering the loop.
  2. Token is a regular C string. Its initial letter is token[0], a char. You can store it in a separate char variable, and carry it over into the next iteration of the loop.
  3. Since the words could be in mixed case, you should probably use toupper or tolower when storing and comparing the initial characters.
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

You extracted the first word in this statement

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

but you did not print it. You are starting to print words in the while loop after the preceding call of strtok_s within the loop.

You need two pointers that will point to adjacent extracted strings and using these pointers you can compare first letters of the strings.

Here is a demonstrative program (for simplicity I am using strtok instead of 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;
}

The program output is

we <-> will

If you want to output all such pairs of words then the program can look the following way

#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;
}

The program output is

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

However instead of using strtok or strtok_s it is much better to use an approach based on the functions strspn and strcspn. In this case you can process constant strings.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335