多路归并| 代码已有|大量文件读入时报fscanf错误
多路归并| 代码已有|大量文件读入时失误
更新:下午在坛子里问了下 fopen支持的最大文件数。
验证了正好是这个问题,fopen换成creatfile
不过下一个问题是:fscanf 换成 逐行读取的readfile
这个细节没有想清楚。
代码对应:
if(fscanf(farray[j], "%d", &data[j]) == EOF)
-------------
昨天看了多路归并,
数据是:1000w个整数,分装到10个子文件。
思路是:排好序好,写到每个子文件,每个文件从头取出一个数,放到数组A,将最小的放进输出文件,
找到最小的那个文件,读入下一个放到数组A;
如此直到所有的数据写到输出文件为止。
调试情况:
先简单:
(总数据,每个文件数据)=(6,2 ), 轻松看到输出。
再回归正题
(总数据,每个文件数据)=(1000w ,100w ),用时40s,复杂度分析:n*logn用时2s,大部分时间用到磁盘io
扩展一下:
看看最多可以分成多少个文件,//背景:经常看到海量数据处理时,分而治之,hash到一千个文件
下面数据量从小到大
(总数据,每个文件数据)=(500,1),可以通过。
(总数据,每个文件数据)=(1000,1),报fscanf错误,错误内容stream==null
二分法找找边界:
(总数据,每个文件数据)=(508,1),可以通过。//0x1fc 对应508
(总数据,每个文件数据)=(509,1),不可以通过。报fscanf错误,错误内容stream==null////0x1fd 对应508
找问题的过程:
1)可能是vs给程序分配内存初始太小吗?
修改了reseverd memory为 10m,不然。
想一想,每个文件都只有1个整数啊,不可能内存问题。
任务管理器也检查了下。
ps:所有内存分配都通过new实现,
2)我怀疑是 文件最多打开数目 (windows文件打开描述符)的问题,
但现在不能确定,也没有查到。
3)文件buffer用完?
尝试setbuffer(stdin,null)
fflush(),依然。
3)问题机器相关吗?
//你运行了就知道了
附问题调试方法:
//修改这2个参数就是
const unsigned int count =500;
const unsigned int number_to_sort =1;
[解决办法]
兄弟:为什么要用fopen,用fstream
在博客:
这里有详细:
http://www.cnblogs.com/daoluanxiaozi/archive/2012/03/29/2423087.html
具体相关代码这里:
- C/C++ code
void merge_sort(int filecnt){ fstream * fs = new fstream[filecnt],ret("ret.txt",ios::out); int index = 1,temp[MAX_ONCE],eofcnt = 0; bool * eof_flag = new bool[filecnt]; ::memset(eof_flag,false,filecnt*sizeof(bool)); for(int i=0; i<filecnt; i++) fs[i].open(create_filename(index++),ios::in); for(int i=0; i<filecnt; i++) fs[i] >> temp[i]; while(eofcnt<filecnt) { int j = 0; // 找到第一个未结束处理的文件 while(eof_flag[j]) j++; int min = temp[j],fileindex = 0; for(int i=j+1; i<filecnt; i++) { if(temp[i]<min && !eof_flag[i]) min = temp[i],fileindex = i; }// for ret << min << " "; fs[fileindex] >> temp[fileindex]; // 末尾判断 if(fs[fileindex].peek()==EOF) eof_flag[fileindex] = true, eofcnt++; }// while delete [] fs; delete [] eof_flag; ret.close();}