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