使用 char 数组和 fgets 的用户输入,使用 write 系统调用的输出?

user input with char array and fgets, output with write system call?

出于某种原因,这段代码给了我一个损坏的最终字符——写入文件和 printf 都没有输入最后一个字符

#include <stdio.h>
#include <stdlib.h>
#include "ssem.h"

int main(){
    int sem_WF, sem_WF_key = 123456, fileID, callStatus;
    char user_input[21];
    
    /*sem_WF = sem_open(sem_WF_key);*/

    fileID = creat ("data", 384);
    if (fileID<0) {printf("Error with creat"); return 0;}

    printf("Enter up to 20 characters: ");
    
    fgets(user_input, 20, stdin);
    printf("%s\n", user_input);

    callStatus = write(fileID, user_input, 20);
    if (callStatus<0) {printf("error with write"); return 0;}

    callStatus = close(fileID);
    if (callStatus<0) {printf("error with close"); return 0;}

    return 0;
}

write你有问题,你需要在count参数中传递字符串的长度,strlen(user_input)而不是 20:

write(fileID, user_input, strlen(user_input));

否则无论存储在user_input中的字符串大小,它将写入所有20个字符。 例如 如果字符串有 8 个字符,它将写入这 8 个字符加上空终止符以及存储在 char 数组的剩余元素中的任何垃圾值,直到大小为 20。

另请注意,由于您使用 fgets 的方式,字符串的实际长度永远不会是 20,它最多包含 19 个字符 + null-byte(后面有更多详细信息),这个空字节也被写入文件。

请记住,当您从文件中读取字符串时,您需要手动终止它 ,上面的 write 不会存储空值文件中的字节。


关于fgets,它将在目标缓冲区的最后一个字符中存储空字节[=21=],因此如果您传递20的大小,它将最多存储19个字符+空字节。好的做法是使用目标缓冲区的大小:

fgets(user_input, sizeof user_input, stdin);

还要注意 fgets 存储输入流中出现的 \n 换行符。

使用 fgets 解析的字符串将如下所示:

+---+---+---+---+---+---+----+----+
|'s'|'t'|'r'|'i'|'n'|'g'|'\n'|'[=12=]'|
+---+---+---+---+---+---+----+----+

除非 \n 被存储在目标缓冲区的最后一个元素中,在这种情况下,它将留在 stdin 缓冲区中,取而代之的是 [=21= ].

如果您愿意,可以删除此 \n 字符:

user_input[strcspn(user_input, "\n")] = '[=13=]'; //#include <string.h>

这里是 Live Demo,问题已修复。