| 会飞的猪 |
 |
| 等级: |
| 权限:贵宾 |
| 积分:-1119 |
| 金钱:-980 |
| 声望:-16 |
| 经验:-1254 |
| 发帖数:907 |
| 注册:2006年10月1日 |
|
资料 短消息 | 2007-10-24 16:29:46 |
|
|
◆ 比如从第10行开始读?
谢谢
◆ ◆ C里面不是有一个对文件进行移位的涵数吗?
如果再不行就要笨一点用fgets(), 因为这个涵数是每次读取一行.
你设的buffer要足够的大.
for(10次)
{
fgets(放入buffer);
清空buffer;
}
◆ ◆ fgets 可以指定最大行长。
◆ ◆ LZ提出的问题也是常见滴....看看还有那些伙们弄个运行时间短一点的方法....
◆ ◆
QUOTE:原帖由 linuxcici 于 2007-4-7 09:54 发表
C里面不是有一个对文件进行移位的涵数吗?
如果再不行就要笨一点用fgets(), 因为这个涵数是每次读取一行.
你设的buffer要足够的大.
for(10次)
{
fgets(放入buffer);
清空buffer;
}
◆ ◆ 不如直接 getchar() 并判断,这样还可以省栈空间。
那个检索函数不能判断行数。
◆ ◆
QUOTE:原帖由 soul_of_moon 于 2007-4-7 10:17 发表
这位大哥.小弟菜嘛...
fgets()每次读入一行就会指向下一行. 所以把前面10行读进去了就清除. 然后下一次fgets()就是第十一行了.
你有更好的办法么? 请贴出来可以么? 嘻嘻~~
◆ ◆
QUOTE:原帖由 linuxcici 于 2007-4-7 10:21 发表
这位大哥.小弟菜嘛...
fgets()每次读入一行就会指向下一行. 所以把前面10行读进去了就清除. 然后下一次fgets()就是第十一行了.
你有更好的办法么? 请贴出来可以么? 嘻嘻~~ fgets()怎么每次都是读一行?你怎么设定?
◆ ◆
QUOTE:原帖由 soul_of_moon 于 2007-4-7 10:23 发表
fgets()怎么每次都是读一行?你怎么设定? 把fgets() 里的buffer设得足够大不就OK了? 我半年前做过是这样子的呢.
半年没有写过C代码和看书了,书还在学校......哎...那请问你是怎么搞的呢?
◆ ◆
QUOTE:原帖由 linuxcici 于 2007-4-7 10:36 发表
把fgets() 里的buffer设得足够大不就OK了? 我半年前做过是这样子的呢.
半年没有写过C代码和看书了,书还在学校......哎...那请问你是怎么搞的呢? buffer设得足够大
------------------------
这不是好习惯
◆ ◆ ◆ 窃以为用getchar就不错了, 缓冲的事都有系统干了.
◆ ◆
QUOTE:原帖由 soul_of_moon 于 2007-4-7 11:03 发表
buffer设得足够大
------------------------
这不是好习惯 那请问大侠你说该怎么办?
还有位同志说用getch().本来就是读入一个字符....速度可以知道能多快
◆ ◆
QUOTE:原帖由 linuxcici 于 2007-4-7 11:36 发表
那请问大侠你说该怎么办?
还有位同志说用getch().本来就是读入一个字符....速度可以知道能多快 是说 getchar() 吧,一般都是有缓冲的。getch() 不是 ANSI C 的库函数。
◆ ◆
QUOTE:原帖由 bGFuZ3Vl 于 2007-4-7 11:44 发表
是说 getchar() 吧,一般都是有缓冲的。getch() 不是 ANSI C 的库函数。 你的意思是说用getchar来解决?
◆ ◆
QUOTE:原帖由 linuxcici 于 2007-4-7 11:48 发表
你的意思是说用getchar来解决? fgetc()
--
◆ ◆
QUOTE: The getchar() function is equivalent to getc() with the argument stdin.man 3 getchar
P.S. 个人认为这里 getc() 应该写成 fgetc()
OpenBSD
--
[ 本帖最后由 bGFuZ3Vl 于 2007-4-7 11:54 编辑 ]
◆ ◆
QUOTE:原帖由 bGFuZ3Vl 于 2007-4-7 11:53 发表
man 3 getchar
P.S. 个人认为这里 getc() 应该写成 fgetc()
OpenBSD
--
好。 找天有空试几行来看看运行速度。
◆ ◆ 缓冲区足够大是错的,足够大只能针对一个已知的文件,比如(如果你告诉我一行是一个名字,而且告诉我世界上最长的名字是20个字节)
否则没有足够大,只有更大。
肯定不能用fgets,要用还要判断是不是真的一行了,应该是fgetc,应该没有更好的方法。
◆ ◆
QUOTE:原帖由 flw2 于 2007-4-7 12:21 发表
缓冲区足够大是错的,足够大只能针对一个已知的文件,比如(如果你告诉我一行是一个名字,而且告诉我世界上最长的名字是20个字节)
否则没有足够大,只有更大。
肯定不能用fgets,要用还要判断是不是真的一行 ... 那是啊。 我的只是判断一个已知的文件滴。 这位大哥你能100%确定是用你的方法么?
◆ ◆ 用fgetc是比较直观的方法。
但用fgets是比较快速的方法。
虽然标准C库有缓冲,但用fgetc毕竟会比fgets多N倍的函数调用,速度慢是正常的。
用fgets,设置大的buffer思路是错误的。
正确的做法应该是读取到buffer后,查找'\n'。每找到一次,标志着读取到了一行。
◆ ◆ ◆
QUOTE:原帖由 assiss 于 2007-4-7 13:39 发表
用fgetc是比较直观的方法。
但用fgets是比较快速的方法。
虽然标准C库有缓冲,但用fgetc毕竟会比fgets多N倍的函数调用,速度慢是正常的。
用fgets,设置大的buffer思路是错误的。
正确的做法应该是读取到 ... 这位大哥每行是\n 啊? 但我有时读取的是什么LF之类的(line feed)
◆ ◆
QUOTE:原帖由 linuxcici 于 2007-4-7 13:44 发表
这位大哥每行是\n 啊? 但我有时读取的是什么LF之类的(line feed) 有时候看你的头像就觉得恶心啊,提两点意见:
1、能不能换个头像?
2、能不能不要这么死板教条?谁告诉你一定、只能比较'\n'?查查strpbrk() 函数是干什么的。
◆ ◆
QUOTE:原帖由 assiss 于 2007-4-7 13:50 发表
有时候看你的头像就觉得恶心啊,提两点意见:
1、能不能换个头像?
2、能不能不要这么死板教条?谁告诉你一定、只能比较'\n'?查查strpbrk() 函数是干什么的。 不喜欢看没人叫你留意我喔。。。。
◆ ◆ 晕~为一个 fgets 的细节讨论半天,至于嘛。
for i = 1 to 9:
while( fgets( buffer, sizeof(buffer), fp ) && buffer[strlen(buffer)-1] != '\n' );
// 现在就位于第十行开始处了。
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 14:06 发表
晕~为一个 fgets 的细节讨论半天,至于嘛。
for i = 1 to 9:
while( fgets( buffer, sizeof(buffer), fp ) && buffer[strlen(buffer)-1] != '\n' );
// 现在就位于第十行开始处了。 版主是偶像,好厉害!
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 14:06 发表
晕~为一个 fgets 的细节讨论半天,至于嘛。
for i = 1 to 9:
while( fgets( buffer, sizeof(buffer), fp ) && buffer[strlen(buffer)-1] != '\n' );
// 现在就位于第十行开始处了。 还是市长姐姐牛呢。。。我已把你列入牛人名单了嘻嘻~~~
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 14:06 发表
晕~为一个 fgets 的细节讨论半天,至于嘛。
for i = 1 to 9:
while( fgets( buffer, sizeof(buffer), fp ) && buffer[strlen(buffer)-1] != '\n' );
// 现在就位于第十行开始处了。 for (i=0; i<3; i++)
fgets( buffer, sizeof(buffer), fp);
这样好像也行,要判断那个回车干啥?
◆ ◆
QUOTE:原帖由 samuel1004 于 2007-4-7 14:36 发表
for (i=0; i<3; i++)
fgets( buffer, sizeof(buffer), fp);
这样好像也行,要判断那个回车干啥? flw,看到没?前面的细节讨论马上就显示出重要性来了。
◆ ◆
QUOTE:原帖由 samuel1004 于 2007-4-7 14:36 发表
for (i=0; i<3; i++)
fgets( buffer, sizeof(buffer), fp);
这样好像也行,要判断那个回车干啥? 这位兄弟没看前几贴有人说。 你这样写那buffer要一定的大才行呢。
而且不能是动态滴。 小那个市长小姐写的while里面要不断的fgets()直到
遇到/n。目的是buffer可以任意value
◆ ◆
QUOTE:原帖由 linuxcici 于 2007-4-7 14:40 发表
这位兄弟没看前几贴有人说。 你这样写那buffer要一定的大才行呢。
而且不能是动态滴。 小那个市长小姐写的while里面要不断的fgets()直到
遇到/n。目的是buffer可以任意value Thanks,市长姐姐 so 强啊。
◆ ◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 14:06 发表
晕~为一个 fgets 的细节讨论半天,至于嘛。
for i = 1 to 9:
while( fgets( buffer, sizeof(buffer), fp ) && buffer[strlen(buffer)-1] != '\n' );
// 现在就位于第十行开始处了。 挑个毛病,别介意。
strlen是个隐患
◆ ◆
QUOTE:原帖由 soul_of_moon 于 2007-4-7 15:17 发表
挑个毛病,别介意。
strlen是个隐患 strlen("") -1 = -1?
呵呵,那应该特殊处理一下。
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 15:19 发表
strlen("") -1 = -1?
呵呵,那应该特殊处理一下。 怎么怎么看不懂。。。。。?汗。。
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 15:19 发表
strlen("") -1 = -1?
呵呵,那应该特殊处理一下。 刚试了一下,不会呀!
你说的隐患到底是指什么呢?
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 15:26 发表
刚试了一下,不会呀!
你说的隐患到底是指什么呢? 文件里有0x00的字符
◆ ◆ 就是查找第N次'\n'的出现位置,具体使用哪个库函数我不好说,对这个没有研究.
◆ ◆
QUOTE:原帖由 soul_of_moon 于 2007-4-7 15:27 发表
文件里有0x00的字符 哦,这种文件就不应该用 fgets 来读取了吧?
QUOTE:NAME
fgetc, fgets, getc, getchar, gets, ungetc - input of characters and strings
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 15:31 发表
哦,这种文件就不应该用 fgets 来读取了吧?
这个就不一定了。像你如果要分析log文件,很有可能在log文件的某个地方存了个0x00
◆ ◆
QUOTE:原帖由 soul_of_moon 于 2007-4-7 15:34 发表
这个就不一定了。像你如果要分析log文件,很有可能在log文件的某个地方存了个0x00 那是写 log 的人的问题
呵呵,有点强词夺理了。
其实我的意思是说,我写程序很注重“语义”。用合适的函数去做合适的事。
像 fgets,就没法读取中间包含有 '\0' 的行——它不是 fread,它返回的只能是字符串,而不是 byte 流。
既然用了 fgets,那么你就不应该说后续的 strlen 有问题了。
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 15:39 发表
那是些 log 的人的问题
呵呵,有点强词夺理了。
其实我的意思是说,我写程序很注重“语义”。用合适的函数去做合适的事。
像 fgets,就没法读取中间包含有 '\0' 的行——它不是 fread,它返回的只能是字 ... 我只是举个例子。
因为以前写过一个测试程序,就因为文档改了,把'0'->NULL,结果导致我的测试程序老是down
◆ ◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 15:39 发表
那是写 log 的人的问题
呵呵,有点强词夺理了。
其实我的意思是说,我写程序很注重“语义”。用合适的函数去做合适的事。
像 fgets,就没法读取中间包含有 '\0' 的行——它不是 fread,它返回的只能是字 ... 市长姐。 那到底你写的能否正确呢?如果文中包含0x00的确是有可能。
fgets()读到0x00那里会停了? 应该是吧。 但多不影响吧。 最多是多了一次while.
啊。 你判断的是\n才结束啊。 应该没错吧?
◆ ◆ flw好像不务正业哈
身为perl版的版主
我一般都在这个版看到她
◆ ◆
QUOTE:原帖由 linuxcici 于 2007-4-7 15:54 发表
市长姐。 那到底你写的能否正确呢?如果文中包含0x00的确是有可能。
fgets()读到0x00那里会停了? 应该是吧。 但多不影响吧。 最多是多了一次while.
啊。 你判断的是\n才结束啊。 应该没错吧? fgets 在包含 '\0' 的时候不能正确工作(虽然它能读出一行,但是它无法告诉你它究竟读了几个字节)。
因此可能包含有 '\0' 时用 fgets 本来就是错误的选择。
◆ ◆
QUOTE:原帖由 yecheng_110 于 2007-4-7 15:58 发表
flw好像不务正业哈
身为perl版的版主
我一般都在这个版看到她 我都说了flw是本版的老版主,感情深厚啊
◆ ◆
QUOTE:原帖由 soul_of_moon 于 2007-4-7 16:04 发表
我都说了flw是本版的老版主,感情深厚啊 关键是 Perl 版的帖子太少,不够我看的。
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 16:03 发表
fgets 在包含 '\0' 的时候不能正确工作(虽然它能读出一行,但是它无法告诉你它究竟读了几个字节)。
因此可能包含有 '\0' 时用 fgets 本来就是错误的选择。 abcdef\0ijk\n
sdfedfesse\n
.
.
.
如果用fgets() 怎么不行呢?遇到\0的话只会使while()多运行一次吧。但就不能用 && strlen...
&& buffer[strlen(buffer)-1]!='\n' || buffer[strlen(buffer)-1]=='\0')不就行了?
[ 本帖最后由 linuxcici 于 2007-4-7 16:17 编辑 ]
◆ ◆ 这个可以减少很多IO操作
CODE: char *p,*pp;
stat st;
int fd;
stat("..",&st);
p =(char *)malloc(sizeof(char)*st.st_size);
fd = open("...",...);
read(fd,p,st.st_size);
int i = 1;
pp=strtok(p,"\n");
while( pp != NULL )
{
pp=strtok(NULL,"\n")
if( ++i == 10 )
{
.....
}
}
free(p);
close(fd);
◆ ◆
QUOTE:原帖由 C_C 于 2007-4-7 16:19 发表
这个可以减少很多IO操作
[code]
char *p,*pp;
stat st;
int fd;
stat("..",&st);
p =(char *)malloc(sizeof(char)*st.st_size);
fd = open("...",...);
read(fd,p,st.st_size) ... read 不行,得 fread。
◆ ◆
QUOTE:原帖由 linuxcici 于 2007-4-7 16:14 发表
abcdef\0ijk\n
sdfedfesse\n
.
.
.
如果用fgets() 怎么不行呢?遇到\0的话只会使while()多运行一次吧。但就不能用 && strlen...
&& buffer[strlen(buffer)-1]!='\n' || buffer[ ... 第二次循环的话,就从第下一行开始了,fgets 会把 '\0' 连同它后面的东西都吃进来,但就是不告诉你它吃了多少。
◆ ◆
QUOTE:原帖由 C_C 于 2007-4-7 16:19 发表
这个可以减少很多IO操作
[code]
char *p,*pp;
stat st;
int fd;
stat("..",&st);
p =(char *)malloc(sizeof(char)*st.st_size);
fd = open("...",...);
read(fd,p,st.st_size) ... 你也太狠了些吧。一下子全读进来?
那还不如用mmap呢。
◆ ◆ ◆
QUOTE:原帖由 assiss 于 2007-4-7 16:21 发表
你也太狠了些吧。一下子全读进来?
那还不如用mmap呢。 一下子都读进来也不算很狠吧?一般的文本文件如配置文件之类的都没多大的,日志除外。
不过“那还不如用mmap”倒是真的。
◆ ◆
QUOTE:原帖由 assiss 于 2007-4-7 16:21 发表
你也太狠了些吧。一下子全读进来?
那还不如用mmap呢。 这只是个例子,如果文件有一定格式的话可以分段读的
◆ ◆
QUOTE:原帖由 C_C 于 2007-4-7 16:24 发表
这只是个例子,如果文件有一定格式的话可以分段读的 问题是你用 read 能保证全读进来吗?
我记得 read 是不保证的哦。
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 16:20 发表
read 不行,得 fread。 为什么?
◆ ◆
QUOTE:原帖由 C_C 于 2007-4-7 16:25 发表
为什么? fread 是库缓冲的,如果读不到,那肯定是没有了。
read 是系统调用,有时候会没读完就返回,比如收到信号。
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 16:27 发表
fread 是库缓冲的,如果读不到,那肯定是没有了。
read 是系统调用,有时候会没读完就返回,比如收到信号。 一直没注意这个问题,谢谢提醒
◆ ◆
QUOTE:原帖由 C_C 于 2007-4-7 16:30 发表
一直没注意这个问题,谢谢提醒 搞网络编程的都知道,read/write 一般都要配合循环使用才保险的。普通的文件设备要比网络稳定得多,但是如果要符合 read 的语义,那么还是 while 一下比较好,因为 read 的 man 手册里没有提到一定会读取指定数量的字节。
◆ ◆
QUOTE:原帖由 flw 于 2007-4-7 16:33 发表
搞网络编程的都知道,read/write 一般都要配合循环使用才保险的。普通的文件设备要比网络稳定得多,但是如果要符合 read 的语义,那么还是 while 一下比较好,因为 read 的 man 手册里没有提到一定会读取指定数 ... 在网络上我一直都用while,读文件我还真没想到
◆ ◆ to > flw
《unix 高级环境编程》第4。2的说明在读常规文件时不会出现这个问题
◆ ◆
QUOTE:原帖由 C_C 于 2007-4-7 16:45 发表
to > flw
《unix 高级环境编程》第4。2的说明在读常规文件时不会出现这个问题 你看的是哪一版?
我这里有一份电子的,我看了一下,第 4.2 节讲的是 stat fstat 和 lstat 啊。没有说 read。
考虑到你有可能是 4.20 节的手误,我还特意看了一下,讲的是 mkdir。
◆ ◆ ◆ 我刚才把书说错了,是《unix 高级编程》,书上是这么说的:
read( int fd,void *buf,size_t nbytes )
在某些读环境,可能受到的字节数少于nbytes参数请求字节数。
从常规文件读时,当尝试满足计数到达了文件尾时,就可能发生
这种情况。在其他情况下,当从常规文件读时,保证直到nbytes
返回时,函数不会返回。
我对红字部分的理解是:当文件的字节没有nbytes这么大时,读到了文件尾函数便会返回,
但这时已经确保的文件已经可以完整的读入buf中。
[ 本帖最后由 C_C 于 2007-4-7 18:35 编辑 ]
◆ ◆ 用 getline吧 每次读一行
◆ ◆ 我想起来了. 第三版好象有说这样的问题.......汗..不年多没看了
◆ ◆ C里面有个函数叫fseek(),用来移动文件位置的,你可以用他来移到需要读取的行好,在调用read()
◆ ◆ 1,第九行结束之后,就是第十行。
2,记住前一个新行位置,到10的时候,回去。
3,如果遇到'\0'呢?
[ 本帖最后由 yuanchengjun 于 2007-4-10 23:20 编辑 ]
◆ ◆
QUOTE:原帖由 pianoguy 于 2007-4-10 21:28 发表
C里面有个函数叫fseek(),用来移动文件位置的,你可以用他来移到需要读取的行好,在调用read() 那只能用来移动字节,不是行。
◆ ◆
◆ ◆
QUOTE:原帖由 tianxiaogang12 于 2007-4-7 21:01 发表
用 getline吧 每次读一行 这个的移植性不太好。
QUOTE:Both getline() and getdelim() are GNU extensions. They are available since libc 4.6.27.
◆
|
|
|
|
|
|