有没有一种方法可以将stdin映射到内存中?

3

我遇到了以下问题:

我的工作是编写一个程序,该程序通过stdin传递无符号整数并仅打印具有超过两个二进制位设置为1的数字。如何高效地完成这项任务?我编写了一个从文件中读取数字的版本,使用mmap非常快速。我像读取一个非常大的*char缓冲区一样读取它,并使用strtol“擦除”每个数字并进行检查等操作。

是否有一种方法可以通过stdin传递字符串并以相同的方式操作它?我考虑使用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


1
这些数字是作为文本传递还是直接以它们的unsigned int形式fwrite到流中? - Medinoc
3
为什么要使用mmap?除非你有一种方式可以检测到数字何时截止,以及数字是否自然地结束在你停止读取stdin的位置,否则你仍然处于同样的境地。例如,如果你传递了1 2 3并且任何在stdin中的东西正好在第二个数字之后结束,那么你如何知道2已经完成,并且不是实际上应该是1 23456 3 - Marc B
它们作为文本传递。 - Arek Krawczyk
2
那么你可能会花更多的时间将文本转换为数字,而不是使用mmap所能获得的时间。保持简单。 - Kninnug
我的意思是,我应该如何解决这个问题?我的思路完全错误吗?有没有一种方法可以像使用mmap操作文件一样轻松地从stdin读取字符串? - Arek Krawczyk
回答标题中的问题:如果数据源是终端或管道而不是文件,则内存映射将无法工作。 - jfs
1个回答

1
我认为期望的解决方案是如何计算1的数量,而不是如何从stdin读取。
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. 对于每个字节(=无符号字符),将其放在数组中的位置,并计算其包含的1的数量(可以是:从0到8)

  3. 将每个数字拆分为其字节,并对每个字节上的1求和。

  4. 返回结果


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接