【问题标题】:How to Search for New Lines while Reading from a File in C/C++如何在 C/C++ 中读取文件时搜索新行
【发布时间】:2011-11-05 10:00:26
【问题描述】:

我正在 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) 标志。因此,我期待在我正在阅读的文件的每一行的开头写下行号。

【问题讨论】:

  • cat-ing 时不需要定位空格和换行符。
  • 我正在实现 (-n) 和 (-b) 标志。我需要在文件中的每个新行之后提示行号。
  • 为什么是 C++ 标签?我只看到 C 代码。
  • 这是因为 C++ 程序员知道如何阅读 C 代码。
  • 使用 memchr 是在缓冲区中搜索特定字符的有效方法。

标签: c unix file-io


【解决方案1】:

虽然在 C 中有一个函数可以进行基于行的文件输入(称为 fgets),但你不能真正将它用于 cat,因为:

  • 无法事先知道行的最大长度;
  • 如果输入包含空字节,您将丢失部分输入。

读取缓冲区后,您必须在缓冲区中查找换行符,一旦找到,打印缓冲区的前缀,然后是换行符、行号和缓冲区的其余部分(附加处理当然是剩余的换行符)。

一个更简单的解决方案是切换到一次处理一个字节的输入;您可以使用 FILE* 和 fgetc 来使用 CRT 提供的缓冲,这样您实际上就不会像现在一样为每个读/写执行系统调用,也不会像现在一样读取块中的文件,而是在循环内进行字节处理。然后就是写一个状态机的问题——如果之前读取的字符是换行符,那么输出一个行号,除非这个字符是换行符并且使用了 -b 选项,等等。

这仍然会导致效率较低的解决方案,因此您可能希望专门处理不带参数的 cat - 即仅在需要时才切换到逐字节处理。事实上,这正是至少一个实际的 cat 实现所做的。

【讨论】:

  • 感谢您的准确回答!我真的很感激 :) 我按照你告诉我的方式做了,现在它工作得很好。
【解决方案2】:

我记得读过 cat 内存映射文件以快速执行。使用 mmap(2)。 http://kernel.org/doc/man-pages/online/pages/man2/munmap.2.html 我找到了这个例子:http://ladweb.net/src/map-cat.c 我知道这并不能回答您关于换行符的问题。我猜 memchr() 可以解决问题。

【讨论】:

  • 理论上 mmap() 比较慢。它需要另外两次系统调用,并且分配和设置页表条目也不是免费的。从程序员的角度来看,它可以更优雅
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-18
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 2018-12-10
相关资源
最近更新 更多