String 拆分一行并打印它会导致核心转储

String 拆分一行并打印它会导致核心转储,string,fgets,strtok,String,Fgets,Strtok,当我试图从标准输入中读取一行并将其拆分为单词时,在删除/n字符后,我得到一个内核转储错误。谁能给我解释一下原因吗?正确的方法是什么 #include <stdio.h> #include <stdlib.h> #include <string.h> #define LINE_LEN 50 #define MAX_PARTS 50 int main () { char* token; char *str; char* arr[MAX

当我试图从标准输入中读取一行并将其拆分为单词时,在删除/n字符后,我得到一个内核转储错误。谁能给我解释一下原因吗?正确的方法是什么

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_LEN  50
#define MAX_PARTS  50

int main ()
{
    char* token;
    char *str;
    char* arr[MAX_PARTS];
    int i,j;

    printf("Write a line: \n $:");
    fgets(str, LINE_LEN, stdin);
    str = strncpy(str, str, strlen(str)-1);

    fflush(stdin);

    i=0;
    token = strtok(str, " ");
    while( token != NULL ) 
    {
        arr[i] = token;
        printf("%s",arr[i]);
        i++;
        token = strtok(NULL," ");
    }
    return 0; 
}
#包括
#包括
#包括
#定义第50行
#定义最大零件数50
int main()
{
字符*令牌;
char*str;
char*arr[最大零件数];
int i,j;
printf(“写一行:\n$:”;
fgets(str、LINE_LEN、stdin);
str=strncpy(str,str,strlen(str)-1);
fflush(stdin);
i=0;
标记=strtok(str,“”);
while(令牌!=NULL)
{
arr[i]=令牌;
printf(“%s”,arr[i]);
i++;
令牌=strtok(空,“”);
}
返回0;
}

您正在上次通过while()循环时打印空指针。您可能需要反转printf()和strtok()调用,如下所示:

while( token != NULL ) 
{
    arr[i] = token;
    printf("%s",arr[i]);         # Must come first to avoid printing a NULL on final loop
    i++;
    token = strtok(NULL," ");
}

您正在读取未分配的内存。

char *str;
这声明了一个指针
str
,它不指向任何地方。(事实上,它指向一个随机位置,但“无处”阻止了那些试图猜测未定义行为的人。)

这会写入
str
所指向的位置,该位置不存在(见上文)。这是未定义的行为。如果您的程序恰好在这一点上幸存下来(而不是在这里进行分段),那么从现在起,您就不能指望它以任何正常的方式运行

当我们这样做的时候:

fflush(stdin);

请注意,在输入流上调用时,C标准没有定义
fflush()
的行为,也就是说,虽然这在Linux下定义得很好(它定义了这种行为),但这是一种非标准、不可移植的构造,可能会在其他平台上崩溃。

Stella-这对我来说很好。我使用的是带有GCC4.6.3的Ubuntu Linux。您很可能使用了与我不同的输入字符串-您可以发布导致崩溃的特定输入吗?你知道是哪一行吗?对不起,我刚刚意识到我发错了代码段!请让我编辑我的问题。无论如何,关于while循环,你是对的。非常感谢。
fflush(stdin);