C_and_CPP 板


LINE

原文在这 #1DyUBD7Q (C_and_CPP) http://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1307697869.A.1DA.html 都翻起旧文了,给个机会,澄清一下。 我先自首件事,这篇文当初我只有小提 fread + strchr 可以达成 较稳定的需求,会这麽说是有个专案 BUF_SIZE 设 32767 , 结果 fgets 档案有一行真的 overflow。 我必须强调,当初讲的 fgets / fread + strchr / fgetc 等方式, 其实都没考虑到档案编码、多国语系问题,然後 fread + strchr 只 是小提一下,当时实作上是顺手写的,这次将它完善。 ※ 引述《gary8520 (元丁)》之铭言: : 小弟学C不久,非资工人, : 正在写一个小程式需要读数十行,每行字元十个左右的资料。 : 想了解BUF_size大约要怎麽取, : 小小测试了一下, : 我使用动态记忆体配制决定BUF_SIZE的大小(用for回圈跑), : 并算出line_cut。 : ※ 引述《tropical72 (蓝影)》之铭言: <............恕删............> : : ---------- : : step 4: 用 fread 进行 : 计算结果输出为line_cnt4 : 这似乎就要看BUF_SIZE的大小… <............恕删............> : 只要bufsize一改,这个方法算出来的结果就会不同? : 说实在话我不知道为什麽,也想不出来为什麽"Orz : 所以,若要像我读小笔资料,step3的方法似乎是比较适当的。 ^^^^^^^^^^^^ 就是 fgets 一般而言,不论档案大小,大多做法都是用 fgets 去做,因很少有机会会遇到 存文字档,一行很长的(正确的说,很少情况会遇到纯文字档会写很大的,写大 的话到後来都是用 binary mode 写入),所以 buf_size 设大一点就没事了, 一般我是直接给 BUFSIZ * 4 ,我手边 compiler BUFSIZ 是给 512 。 --------------------- 原 source code 有问题的 重点如下 while(BUF_SIZE==fread(buf, 1, BUF_SIZE, fp)){ ptr = (char*)strchr(buf, '\n'); /* 这里还有个 issue 要修正 */ while(ptr!=NULL){ ++line_cnt; ptr = (char*)strchr(ptr+1, '\n'); } } 关键其实在於 fread 传回值 ,代表成功从档案读取了几个 bytes , 原本是只考虑成功读取了 BUF_SIZE bytes 时才继续往下做 , 想一下 如果档案有 351 bytes, 每次读 100 bytes , 最後会有 51 bytes 会 被丢掉,所以判断式不该那麽下 [Lemma],要简单的话是只要 fread 传回值是非 0 就直接往下做。 然後考虑一下最後一次 fread 的情况,假设 BUF_SIZE = 100 , 但只读 了 51 bytes , 这时候 buf 後面的 49 bytes 都不会被清 0 , 意思是说 如果 buf 後 49 bytes 里面有 '\n' 的话就会被重覆计算, 所以在做 string search 之前要再塞个结束字元。 整个可以 run 的 code 如下。 #include <stdio.h> #include <stdlib.h> #include <string.h> enum {LINE_CNT = 150, BUF_SIZE = 20}; const char * FILENAME = "tst.txt"; int main() { FILE * fp ; char * ptr; char buf[BUF_SIZE+1] ; // +1 : 加上结束字元 size_t read_bytes , line_cnt = 0; fp = fopen(FILENAME, "rb"); // no error defect while(read_bytes = fread(buf, 1, BUF_SIZE, fp)) { // read_bytes==0 时结束 buf[read_bytes] = '\0'; ptr = (char*)strchr(buf, '\n'); while(ptr!=NULL) { ++line_cnt; ptr = (char*)strchr(ptr+1, '\n'); } } fclose(fp); printf("line_cnt = %d\n", line_cnt); return 0; } 然後整个 fread + strchr , 其实可用 fread + memchr 做 , memchr 速度应会比 strchr 还快一点点 , 这里就不再示范。 [Lemma] 当初之所以会用 while(BUF_SIZE==fread(buf, 1, BUF_SIZE, fp)) , 是因为不想在 while loop 里面做很多事,想单纯化,最後没读满 BUF_SIZE 的是跳出 loop 之後再独立做,速度估会较快。 -- ~ 这辈子与神手无缘 我只好当神兽了 ~ 卡卡兽 --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 180.177.74.188
1F:→ Feis:个人认为可以的话应该还是不要用 fgets 02/02 20:20
2F:→ Feis:此外 gary8520 的 code 应该跟原本的 code 也不同~ 02/02 20:23
3F:→ EdisonX:个人认为 fgets 是在 c-style 开发下的捷径,要正确的话当 02/02 20:48
4F:→ EdisonX:然它不会是首选,ifstream 比它正确,但相对的速度慢,不好用 02/02 20:49
5F:→ Feis:喔. 没有. 是我刚想错了 :P 02/02 20:57
6F:→ Feis:我想表达的是如果有极小的机率造成错误就别用 02/02 20:59
7F:→ Feis:不是 fgets 本身的问题. 而是原文的用法 02/02 21:01
8F:→ EdisonX:了解, 谢谢 :D 02/02 21:01
9F:推 gary8520:其实我那个code基本上是复制t大的,只是加了一些宣告之类 02/02 21:12
10F:→ gary8520:忘了谢谢E大大 02/02 21:14
11F:→ EdisonX:嗯,所以可能你没了解 bufsize 的含意吧,导致 fgets 有问题 02/02 21:14
12F:推 gary8520:我自认为我应该知道fgets那个方法,只要bufsize够大,能 02/02 21:18
13F:→ gary8520:读完一整行,其实fgets应该就可以跑出正确的结果。 02/02 21:18
14F:→ EdisonX:嗯,那是我误会你了. 附一提, edisonx==tropical72 . 02/02 21:21
15F:→ Feis:@gary8520: 你的 code 我觉得一定有什麽神秘力量. 建议贴一下 02/02 21:25
16F:→ purincess:t大魂魄不散 (? 02/02 22:14
17F:→ EdisonX:嗯... 还剩一口气 Orz 02/02 22:18
18F:→ freaky:如果只给Windows用,CreateFile/ReadFile是你的好朋友。 02/02 22:43
19F:→ freaky:先GetFileSizeEx()再看你要怎麽分段或一次读完都可以。 02/02 22:45
20F:→ freaky:可以从32Kb buffer大小开始测读取速度。 02/02 22:51
21F:→ freaky:读大档案memory-mapped file更快。 02/02 22:52







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:iOS站内搜寻

TOP