【问题标题】:Is there a way to mmap a stdin?有没有办法映射标准输入?
【发布时间】:2013-11-28 17:00:42
【问题描述】:

我有以下问题:

我的工作是编写一个程序,该程序接受通过标准输入传递给它的无符号整数,并仅打印出超过 2 位设置为 1 的数字。我应该如何有效地做到这一点?我做了一个程序版本,我使用 mmap 从文件中读取数字,而且速度非常快。我读它就像一个非常大的 *char 缓冲区并使用 strtol 我“擦掉”每个数字并进行检查等等。

有没有办法以同样的方式对通过标准输入的字符串进行操作?我虽然关于使用 fread 进行缓冲,但是有一个问题,缓冲区会切断数字(这意味着如果我通过“1024 35”并且我有一个 6 字节的缓冲区,我将得到“1024 3”),我不禁想到如何解决这个问题。

来源:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h> /* mmap() is defined in this header */
#include <fcntl.h>
#include<string.h>
#include"apue.h"
int main (int argc, char *argv[])
{
 int fdin, fdout;
 char *src, *dst;
 struct stat statbuf;


 /* open the input file */
 if ((fdin = open (argv[1], O_RDONLY)) < 0)
   {printf("can't open %s for reading", argv[1]);return 1;}



 /* find size of input file */
 if (fstat (fdin,&statbuf) < 0)
    {printf("fstat error");return 1;}





 /* mmap the input file */
 if ((src = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, fdin, 0))
   == (caddr_t) -1)
   {printf("mmap error for input");return 1;}

  char* beg=src;
  long x;
  char* end=&src[statbuf.st_size-1];
  while(src<end)
  {     
        beg=src;
        x = strtol (src,&src,10);
        if(!((x != 0) && ((x & (~x + 1)) == x)))
            fwrite(beg, 1, (int)(src-beg), stdout);    
  }
  return 0;
}

http://pastebin.com/EVhG3x79

【问题讨论】:

  • 这些数字是作为文本传递的,还是直接以unsigned int 形式写入流中?
  • 为什么选择mmap?除非您有某种方法可以检测到数字何时中断。一个在你停止阅读标准输入的地方自然结束的数字,你仍然在同一条船上。例如如果您传递 1 2 3 并且标准输入中的任何内容都在两者之后结束。你怎么知道 2 已经完成,实际上不应该是1 23456 3
  • 它们作为文本传递。
  • 那么您可能会花费更多时间将文本转换为数字,而不是使用mmap 获得的时间。保持简单。
  • 意思是我应该如何解决这个问题?我正确的思维方式是完全错误的吗?有没有办法像使用 mmap 操作文件一样舒适地从标准输入读取字符串?

标签: c unix


【解决方案1】:

我认为预期的解决方案是如何计数而不是如何从标准输入读取。

int count_ones(int n);

意味着问题是如何有效地实现 count_ones。 你的主要应该是这样的:

int main()
{
  int x;
  cin>>x;
  if( count_ones(x)>2){
    cout<<x<<endl;
  }
  return 0;
}

我认为预期的答案是:

  1. 使用数组大小​​ 256

  2. 对于放入数组中的每个字节(=unsigned char),将其计数(可以是:从 0 到 8)

  3. 将每个数字拆分为其字节并将每个字节上的数字相加。

  4. 返回结果

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多