如何在C / C ++中从文件中读取时搜索新行

时间:2011-11-05 10:00:27

标签: c unix file-io

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

2 个答案:

答案 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()会做的。