从字符串中获取第二个单词

Get second word from string

我正在尝试使用 strtok:

从 C 中的字符串中获取第二个单词
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

char* GetFirstToken(char str[])
{
    const char delim[] = " ";
    char inputCopy [255];
    strcpy(inputCopy, str);
    return strtok(inputCopy, delim);        
}

char* GetSecondToken(char str[])
{
    const char delim[] = " ";
    char inputCopy [255];
    strcpy(inputCopy, str);
    char * ptr = strtok(inputCopy, delim);    
    return strtok(NULL, delim); 
}

int main(void){
    char my_str[100] ="hello world";
    char *first = GetFirstToken(my_str);
    char *second = GetSecondToken(my_str);

    printf("first:%s\n", first);
    printf("second:%s\n", second);

    return 0;
}

输出为:

first: hello

second: wo

为什么 "world" 不是 second 的值?

函数 return 无效指针,因为它们指向局部数组,这些数组在退出函数后将不存在。因此使用指针可以调用未定义的行为。

您可以只定义一个函数,再定义一个参数来指定要提取的子字符串。

这是一个演示程序。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char * GetToken( const char str[], size_t pos )
{
    const char delim[] = " \t";

    char *inputCopy = malloc( ( strlen( str ) + 1 ) );

    char *p = NULL;

    if ( inputCopy != NULL )
    {
        strcpy( inputCopy, str );

        p = strtok( inputCopy, delim );

        while ( p != NULL && pos -- != 0 )
        {
            p = strtok( NULL, delim );
        }

        if ( p != NULL )
        {
            size_t n = strlen( p );
            memmove( inputCopy, p, n + 1 );

            p = realloc( inputCopy, n + 1 );
        }           

        if ( p == NULL )
        {
            free( inputCopy );
        }
    }

    return p;
}


int main(void) 
{
    char my_str[100] ="hello world";
    char *first = GetToken(my_str, 0);
    char *second = GetToken( my_str, 1 );

    if ( first ) printf("first:%s\n", first);
    if ( second ) printf("second:%s\n", second);

    free( first );
    free( second );
    return 0;
}

您在每个函数内部声明 char inputCopy[255],然后 return 指向它的指针。但是,该数组仅存在于函数范围内,导致 未定义的行为

您可以通过在 main 中创建数组并将其作为参数传递给函数来避免这种情况。此外,使用 malloc 为数组动态分配内存。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

char* GetFirstToken(char str[], char inputCopy[], const char delim[])
{
    strcpy(inputCopy, str);
    return strtok(inputCopy, delim);        
}

char* GetSecondToken(char str[], char inputCopy[], const char delim[])
{
    strcpy(inputCopy, str);
    char * ptr = strtok(inputCopy, delim);    
    return strtok(NULL, delim); 
}

int main(void){
    char my_str[100] ="hello world";
    char *inputCopy = malloc(255 * sizeof(char));
    const char delim[] = " ";
    char *first = GetFirstToken(my_str, inputCopy, delim);
    char *second = GetSecondToken(my_str, inputCopy, delim);

    printf("first:%s\n", first);
    printf("second:%s\n", second);

    free(inputCopy);

    return 0;
}

输出:

first:hello
second:world

您可以在 C here, and about malloc here.

中阅读有关 scopes 的更多信息

另外,请注意 GetFirstTokenGetSecondToken 具有相似的功能。因此,最好有一个函数 returns 给定字符串中的第 n 个单词。这是基本思想:

#include <stdio.h>
#include <string.h>


int main()
{
    char my_str[] ="hello world i am a string";
    char* word;

    /* get the first word from the message, seperated by
     * space character */
    word = strtok(my_str, " ");
    printf("1st word: %s\n", word);

    /* the following loop gets the rest of the words until the
     * end of the message */
    int i=2;
    while ((word = strtok(NULL, " ")) != NULL)
    {
        printf("%d word: %s\n", i, word);
        i++;
    }
    return 0;
}

您可以阅读有关此类解决方案的更多信息here and also in