【发布时间】:2021-08-03 02:34:49
【问题描述】:
我刚开始学习 C 很抱歉,如果我错过了一些明显的东西。作为一种实践,我想编写自己的 posix cat 并且几乎可以正常工作,但是当没有参数时,它不会从 stdin 读取多个文件。
这是预期的行为(忽略这个,因为这是我不知道的 Zsh 功能):
$ cat < hello.txt < world.txt
hello
world
$
但是我的cat 因“分段错误”而崩溃(我有一个没有崩溃但也没有输出任何内容的版本)
代码如下:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
char opt;
while ((opt = getopt(argc, argv, "u")) != EOF) {
switch(opt) {
case 'u':
/* Make the output un-buffered */
setbuf(stdout, NULL);
break;
default:
break;
}
}
argc -= optind;
argv += optind;
int i = 0, fildes, fs = 0;
do {
/* Check for operands, if none or operand = "-". Read from stdin */
if (argc == 0 || !strcmp(argv[i], "-")) {
fildes = STDIN_FILENO;
} else {
fildes = open(argv[i], O_RDONLY);
}
/* Check for directories */
struct stat fb;
if (!fstat(fildes, &fb) && S_ISDIR(fb.st_mode)) {
fprintf(stderr, "cat: %s: Is a directory\n", argv[i]);
i++;
continue;
}
/* Get file size */
fs = fb.st_size;
/* If bytes are read, write them to stdout */
char buf[fs];
while ((read(fildes, buf, fs)) > 0)
write(STDOUT_FILENO, buf, fs);
/* Close file if it's not stdin */
if (fildes != STDIN_FILENO)
close(fildes);
i++;
} while (argv[i] != NULL || argc == 0);
return 0;
}
【问题讨论】:
-
您没有传递任何参数。
'<'字符从文件重定向标准输入。 shell 不会将其作为命令行参数传递。 -
hello.txtworld.txt文件的内容是什么? -
那么
cat < hello.txt < world.txt不可能打印hello world。它应该只打印world。 -
@KamilCuk 然后 GNU cat 是 magick 或 idk imgur.com/a/S99dFkj
-
@stark 猜测一下,shell 是 zsh,其中(除非
multiosoption 关闭)foo <a <b相当于cat a b | foo,foo >a >b相当于foo | tee a b >/dev/null。
标签: c linux segmentation-fault stdin do-while