C 将strtok的缓冲区转换为字符数组

C 将strtok的缓冲区转换为字符数组,c,arrays,system-calls,C,Arrays,System Calls,我在C语言中使用系统调用时遇到了一些问题。我试图使用read从stdin读取一些输入,然后使用strtok在数组中加载值,但我似乎做得不正确(我不断得到segfault) 以下是我开始使用的代码: void read_input() { char* c; read(0, c, 128); printf("%s", c); } 这很好,我可以打印输出。然而,我下一步尝试了一些方法,但都没有奏效。我试过: 创建一个数组char-arr[128],然后使用不同的strcpy、

我在C语言中使用系统调用时遇到了一些问题。我试图使用
read
stdin
读取一些输入,然后使用strtok在数组中加载值,但我似乎做得不正确(我不断得到segfault)

以下是我开始使用的代码:

void read_input()
{
    char* c;
    read(0, c, 128);
    printf("%s", c);
}
这很好,我可以打印输出。然而,我下一步尝试了一些方法,但都没有奏效。我试过:

  • 创建一个数组
    char-arr[128]
    ,然后使用不同的
    strcpy
    strncpy
    memcpy
    c
    复制到
    arr
    ,但它们都不起作用,我得到了一个错误
  • 事实上,这就是我所尝试的。我不确定如何将
    c
    复制到
    arr
    中,以便使用
    strtok
    。有人能解释一下吗

    谢谢

    编辑:

    好的,这是我的新代码:

    void
    read_input()
    {
        char arr[129];
        int r = read(0, arr, 129);
        printf("%s", arr);
    
        arr[r] = '\0';
    
        char* pch;
    
        pch = strtok(arr, " \n");
    
        while(pch != NULL)
        {
            printf("%s\n", pch);
            pch = strtok(NULL, " \n");
        }
    }
    
    我试着从标准输入中读出“嗨,我的名字是约翰”。这是我从printfs获得的输出:

    hi my name is john
    �����hi
    my
    name
    is
    john
    

    为什么第一个标记看起来像那样?我注意到,如果我不添加
    arr[r]='\0'
    ,那么“john”将类似于“hi”。对于第一个字符,与最后一个字符类似,我需要做些什么吗?

    您可以直接执行以下操作:

    void read_input()
    {
        char arr[128];
        read(0, arr, 128);
        printf("%s", arr);
    }
    
    或动态内存分配路由:

    char *arr = malloc((sizeof(*arr) * 128) + 1);
    if (arr == NULL)
    {
        // handle error
    }
    int r = read(0, arr, 128);
    arr[r] = '\0';
    printf("%s", arr);
    

    第二个程序无法运行,因为在调用
    printf
    后放置了
    NUL
    终止符。您需要在打印前执行以下操作:

    char arr[129];              // 128 + 1 for the NUL terminator
    int r = read(0, arr, 128);
    arr[r] = '\0';
    printf("%s\n", arr);        // \n for better readbility of the output
    
    您还需要为
    NUL
    终止符再增加一个字节,因此需要
    129

    带有
    %s
    格式说明符的
    printf
    打印
    NUL
    终止字符串。由于您没有将
    NUL
    放在
    printf
    之前,后者会显示所有字符,直到遇到
    NUL
    ,因此您会得到以下输出:

    hi my name is john
    �����
    ...
    
    此输出可能会有所不同,这取决于
    arr
    缓冲区先前的内容


    第一个版本是错误的,因为
    c
    指针没有初始化,它没有指向任何地方。在这种情况下,程序可能看起来工作正常,但这就是所谓的“未定义的行为”,请记住,“未定义的行为”包括“显然工作正常”。

    这是行不通的。您的
    c
    未初始化。“这工作正常”-您确定吗
    read
    必须将数据写入指针指向的内存,但实际上它并不指向任何东西。你应该分配一些内存first@EugeneSh. @ForceBru就其本身而言,我并不“确定”它是否工作良好。我所知道的是,
    printf
    打印
    c
    的内容。即使您解决了这个问题,字符数组中填充的任何读取都不可能以0结尾。
    malloc(129)
    -您还需要一个额外的字节来存储NUL终止符,您还需要添加哪些代码?@EugeneSh。对不起,这是一个拼写错误,谢谢您指出这一点out@JohnLexus这个问题实际上是针对利奥的:)上面的两个代码是不等价的。@EugeneSh。哦,在我的编辑中,我犯了一个类似的错误。我也从中受益,哈哈!可以我还有最后一个问题!我现在正在使用129(或128)。但是我实际上不知道我正在读取的
    nbytes
    (这是read中的第三个参数)。处理这个问题的常规方法是什么?如果它读取129字节,则最后会将0写入数组末尾。@ChrisTurner当然,感谢您指出这一点,编辑-@JohnLexus这是另一个问题。答案并非微不足道。