我正在Unix中练习我自己的(“cat”)命令版本。在我这样做后,我开始感兴趣实现一些标志,如(-n)和(-b)。
我的问题:我正在寻找一种方法来在从我的文件中读取时找到空行和新行。我不记得我应该使用哪个库或函数。
以下是我正在处理的源代码:
#include <fcntl.h>
#include <unistd.h>
static int cat_fd(int fd)
{
char buf[4096];
ssize_t nread;
while ((nread = read(fd, buf, sizeof buf)) > 0)
{
ssize_t ntotalwritten = 0;
while (ntotalwritten < nread)
{
ssize_t nwritten = write(STDOUT_FILENO, buf + ntotalwritten, nread - ntotalwritten);
if (nwritten < 1)
{
return -1;
}
ntotalwritten += nwritten;
}
}
return (nread == 0) ? 0 : -1;
}
static int cat(const char *fname)
{
int fd, success;
if ((fd = open(fname, O_RDONLY)) == -1)
{
return -1;
}
success = cat_fd(fd);
if (close(fd) != 0)
{
return -1;
}
return success;
}
int main(int argc, char **argv)
{
int i;
if (argc == 1)
{
if (cat_fd(STDIN_FILENO) != 0)
goto error;
}
else
{
for (i = 1; i < argc; i++)
{
if (cat(argv[i]) != 0)
{
goto error;
}
}
}
return 0;
error:
write(STDOUT_FILENO, "error\n", 6);
return 1;
}
非常感谢有关我的问题的任何想法或建议。 如果您可以为我输入我将使用的完整功能原型,我将更加感激,因为我不是一位经验丰富的程序员。
提前感谢您的帮助。
P.S:我正在实现(-n)和(-b)标志。因此,我期待在我正在阅读的文件中的每一行的开头写下行号。
答案 0 :(得分:1)
虽然有一个函数可以在C中执行基于行的文件输入(它被称为fgets
),但你不能真正将它用于cat,因为:
读取后你必须在缓冲区中查找换行符号,一旦找到,就打印缓冲区的前缀,然后是换行符,行号和缓冲区的其余部分(附加处理)当然还有剩下的新行。
更简单的解决方案是一次切换到一个字节的处理输入;您可以使用FILE *和fgetc来使用CRT提供的缓冲,这样您就不会像现在那样为每个读/写或块中的读取文件实际执行系统调用,并在循环内执行字节处理。然后是编写状态机的问题 - 如果先前读取的字符是换行符,则输出行号,除非该字符是换行符并且使用-b选项等。
这仍然导致效率较低的解决方案,因此您可能希望特殊地处理不带参数的cat - 即仅在需要时切换到每字节字节处理。实际上,这正是至少有一个实际的cat实现。
答案 1 :(得分:1)
我记得读过cat内存映射文件以便快速执行。使用mmap(2)。 http://kernel.org/doc/man-pages/online/pages/man2/munmap.2.html 我找到了这个例子:http://ladweb.net/src/map-cat.c 我知道这不会回答你关于换行的问题。我猜 memchr()会做的。