将行拆分为单词并使用 strtok 将它们放入 char 数组中

Split line into words and put them in char array using strtok

我有这个简单的行解析器到标记函数... 但是我缺少一些东西。

int parse_line(char *line,char **words){

   int wordc=0;

   /* get the first token */
   char *word = strtok(line, " ");
   words[wordc]=(char*)malloc(256*sizeof(char));
   strcpy(words[wordc++],word );

   /* walk through other tokens */
    while( word != NULL ) {
        word = strtok(NULL, " ");
        words[wordc]=(char*)malloc(256*sizeof(char));
        strcpy(words[wordc++],word );
    }

    return wordc;
}

当我 运行 它出现分段错误! 我给出第一个参数 char[256] 行,第二个当然是 char** 字,但我有第一个 malloc 内存。像这样

  char **words = (char **)malloc(256 * sizeof(char *));
main:
.
.
.
char buffer[256];
char **words = (char **)malloc(256 * sizeof(char *));
.
.
.
n = read(stdin, buffer, 255);
if (n < 0){
   perror("ERROR");
   break;
}

parse_line(buffer,words);

当程序执行时 parse_line 它退出并出现段错误

找到段错误发生的地方。它就在那一行:

strcpy(words[wordc++],word );

特别是第一个 strcpy。在它甚至到达 while 循环之前

while( word != NULL ) {
    word = strtok(NULL, " ");
    words[wordc]=(char*)malloc(256*sizeof(char));
    strcpy(words[wordc++],word );
}

在该行的末尾,word 将始终设置为 NULL(如预期的那样),因此 strcpy(words[wordc++],word ) 将是未定义的行为(可能是崩溃)。

您需要重新组织循环,以免尝试复制 NULL 字符串。

@jxh 建议使用此解决方案解决 word 在任何一个 strcpy 中成为 NULL 的问题。

/* get the first token */
char *word = strtok(line, " ");

while( word != NULL ) {
    words[wordc]=(char*)malloc(256*sizeof(char));
    strcpy(words[wordc++],word );
    word = strtok(NULL, " ");
}

我会这样做(使用更少的内存)

/* get the first token */
char *word = strtok(line, " ");

while( word != NULL ) {
    words[wordc++] = strdup(word);
    word = strtok(NULL, " ");
}

你的答案是正确的!但是因为阅读,我又遇到了 segF!!!!!!! 我没有注意到,当我 运行 程序时,它并没有停止读取输入! 相反,它正在通过它。我所做的是将 read 更改为 fgets 并且它起作用了!!! 还有你的改变! 有人可以给我解释一下吗????为什么它不会在读取函数处停止??

以下建议代码:

  1. 干净地编译
  2. 执行所需的功能
  3. 正确检查错误
  4. 向用户显示结果
  5. 无法将所有分配的内存传递给 free(),因此存在大量内存泄漏

现在建议的代码:

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

// avoid 'magic' numbers in code
#define MAX_WORDS 256
#define MAX_LINE_LEN 256


int parse_line( char *line, char **words )
{
    int wordc=0;

    /* get the first token */
    char *token = strtok(line, " ");
    while( wordc < MAX_WORDS && token ) 
    {   
        words[wordc] = strdup( token );
        if( ! words[wordc] )
        {
            perror( "strdup failed" );
            exit( EXIT_FAILURE );
        }

        // implied else, strdup successful

        wordc++;

        // get next token
        token = strtok(NULL, " ");
    }

    return wordc;
}



int main( void )
{
    char buffer[ MAX_LINE LENGTH ];

    // fix another problem with OPs code
    char **words = calloc( MAX_WORDS, sizeof( char* ) );
    if( ! words )
    {
        perror( "calloc failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, calloc successful

    // note: would be much better to use 'fgets()' rather than 'read()'
    ssize_t n = read( 0, buffer, sizeof( buffer ) );
    if (n <= 0)
    {
       perror("read failed");
       exit( EXIT_FAILURE );
    }

    // implied else, read successful

    // note: 'read()' does not NUL terminate the data
    buffer[ n ] = '[=10=]';   

    int count = parse_line( buffer, words );

    for( int i = 0; i < count; i++ )
    {   
        printf( "%s\n", words[i] );
    } 
}

这里是一个典型的运行程序:

hello old friend  <-- user entered line
hello
old
friend