#include <stdio.h>
static void cat(FILE *fp)
{
char buffer[4096];
size_t nbytes;
while ((nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp)) != 0)
fwrite(buffer, sizeof(char), nbytes, stdout);
}
int main(int argc, char **argv)
{
FILE *fp;
const char *file;
while ((file = *++argv) != 0)
{
if ((fp = fopen(file, "r")) != 0)
{
cat(fp);
fclose(fp);
}
}
return(0);
}
Run Code Online (Sandbox Code Playgroud)
该cat()功能并非绝对必要,但我宁愿使用它.主程序逐步执行每个命令行参数并打开命名文件.如果成功,则调用该cat()函数来打印其内容.由于调用fopen()未指定"rb",因此将其作为文本文件打开.如果文件未打开,则此代码将无提示地忽略该问题.如果未指定文件,则根本不打印任何文件.
该cat()函数一次只读取最多4096个字节的文本块,并将它们写入标准输出("屏幕").当没有更多要阅读时它会停止.
如果要在未指定文件时将代码扩展为读取标准输入,则可以使用:
if (argc == 1)
cat(stdin);
else
{
...while loop as now...
}
Run Code Online (Sandbox Code Playgroud)
这是使cat()函数如图所示编写的原因之一.
此代码不直接关注换行符 - 或任何类型的行.如果你想一次正式处理一行,那么你可以做几件事:
static void cat(FILE *fp)
{
char buffer[4096];
while (fgets(buffer, sizeof(buffer), fp) != 0)
fputs(buffer, stdout);
}
Run Code Online (Sandbox Code Playgroud)
这将一次读写一行.如果任何行超过4095字节,它将在两个或多个操作中读取该行并将其写入相同数量的操作.请注意,这假定文本文件的版本使用fread()和fwrite()不使用.在POSIX系统上,带有fread()和fwrite()将处理'\0'数据中具有空字节()的任意二进制文件的版本,但版本使用fgets()和fputs()不会.到目前为止,这两个版本都是严格标准的C(标准的任何版本),因为它们不使用任何特定于平台的扩展; 它们和代码一样便携.
或者,如果你有POSIX 2008 getline()功能,你可以使用它,但你也需要#include <stdlib.h>(因为你最终必须释放它分配的内存):
static void cat(FILE *fp)
{
char *buffer = 0;
size_t buflen = 0;
while (getline(&buffer, &buflen, fp) != -1)
fputs(buffer, stdout);
free(buffer);
}
Run Code Online (Sandbox Code Playgroud)
此版本也不会处理二进制数据(意味着其中包含空字节的数据).当然可以升级它来这样做:
static void cat(FILE *fp)
{
char *buffer = 0;
size_t buflen = 0;
ssize_t nbytes;
while ((nbytes = getline(&buffer, &buflen, fp)) != -1)
fwrite(buffer, sizeof(char), nbytes, stdout);
free(buffer);
}
Run Code Online (Sandbox Code Playgroud)
该getline()函数报告它读取了多少字节(之后有一个空字节),但该fwrite()函数是唯一一个获取任意字节流并将它们全部写入给定流的函数.