7

有很多方法描述了如何使用各种方法在这个站点上打印出文本文件的行:

它们似乎都是针对特定示例量身定制的。

最好有最清晰最简洁最简单的方法:将任何文本文件的每一行打印到屏幕上。最好详细说明每行的作用。

简洁明了的要点。

4

4 回答 4

9
#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);
}

cat()功能不是绝对必要的,但我宁愿使用它。主程序逐步执行每个命令行参数并打开命名文件。如果成功,它会调用该cat()函数来打印其内容。由于调用fopen()未指定"rb",因此将其作为文本文件打开。如果文件未打开,此代码会静默忽略该问题。如果未指定文件,则根本不打印任何内容。

cat()函数一次只读取最多 4096 字节的文本块,并将它们写入标准输出(“屏幕”)。当没有更多的阅读内容时它会停止。

如果要在未指定文件时扩展代码以读取标准输入,则可以使用:

if (argc == 1)
    cat(stdin);
else
{
    ...while loop as now...
}

cat()这是编写如图所示的函数的原因之一。

此代码不直接关注换行符——或任何类型的行。如果你想一次正式地处理一行,那么你可以做几件事:

static void cat(FILE *fp)
{
    char buffer[4096];
    while (fgets(buffer, sizeof(buffer), fp) != 0)
         fputs(buffer, stdout);
}

这将一次读取和写入一行。如果任何一行超过 4095 字节,它将在两次或更多操作中读取该行,并以相同数量的操作写入。请注意,这假定文本文件以版本使用fread()fwrite()不使用的方式。在 POSIX 系统上,带有fread()and的版本fwrite()将处理数据中带有空字节 ( ) 的任意二进制文件'\0',但使用fgets()and的版本fputs()不会。到目前为止,这两个版本都是严格的标准 C(标准的任何版本),因为它们不使用任何特定于平台的扩展;它们与代码一样可移植。

或者,如果你有 POSIX 2008getline()函数,你可以使用它,但你也需要#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);
}

此版本也不会处理二进制数据(即其中包含空字节的数据)。当然,它可以升级到这样做:

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);
}

getline()函数报告它读取了多少字节(之后有一个空字节),但该fwrite()函数是唯一一个接受任意字节流并将它们全部写入给定流的函数。

于 2012-12-28T00:09:38.917 回答
2

好吧,这是我最终提出的一个非常简短的解决方案。我想它有一些根本性的错误,否则会被建议,但我想我会把它贴在这里并希望有人把它撕开:

#include <stdio.h>
main()
{
    FILE *MyFile;
    int c;
    MyFile=fopen("C:\YourFile.txt","r");
    c = fgetc(MyFile);
    while (c!=EOF)
    {
        printf("%c",c);
        c = fgetc(MyFile);
    }
}
于 2013-01-02T23:53:14.280 回答
1

@Dlinet,您正在尝试学习一些有关如何组织程序的有用课程。我不会发布代码,因为已经有一个非常好的答案;我不可能改进它。但我想向你推荐一本书。

这本书被称为Pascal 中的软件工具。语言是 Pascal,而不是 C,但是对于阅读这本书来说,这不会造成严重的困难。他们开始实现简单的工具,例如本例中的工具(在 UNIX 上称为cat),然后转向更高级的东西。他们不仅教授了有关如何组织此类程序的重要课程,而且还涵盖了语言设计问题。(Pascal 中确实存在让他们烦恼的问题,如果您了解 C,您将意识到 C 没有这些问题。)

这本书现在已经绝版,但我在学习编写代码时发现它非常有价值。直到今天,所谓的“左角设计”方法都很好地为我服务。

我鼓励你在亚马逊或其他任何地方找到一份用过的副本。亚马逊使用的副本起价为 0.02 美元,外加 4 美元的运费。

http://www.amazon.com/Software-Tools-Pascal-Brian-Kernighan/dp/0201103427

学习本书中的程序并在 C 中实现它们将是一个教育练习。任何 Linux 系统都已经拥有这些程序的更强大和完全调试的版本,但是完成这些工作不会浪费你的时间书并学习如何写这些东西。

或者,您可以在您的计算机上安装 FreePascal 并使用它来运行书中的程序。

祝你好运,愿你永远喜欢软件开发!

于 2012-12-28T01:04:03.983 回答
0

如果你想要一些预烘焙的东西,catPOSIX 系统上有。

如果你想自己写,这里是基本布局:

  1. 检查以确保文件名、权限和路径有效
  2. 在循环中读取直到换行符分隔符(在 Unix 上为 \n,在 Windows/DOS 上为 \r\n)
  3. 检查错误。如果是这样,打印错误并中止。
  4. 将行打印到屏幕。
  5. 重复

关键是,实际上并没有具体的方法来做到这一点。只需阅读,然后写,然后重复。通过一些错误检查,你又得到了 cat 。

于 2012-12-28T00:08:07.077 回答