- 论坛徽章:
- 14
|
这种虽然需求小,但边界复杂,不容易写好,很容易就藏bug
我试着写了一下,没做什么测试,所以肯定会有bug。
在gcc4.7.2(-std=c99)编译通过- #include <stdio.h>
- #include <string.h>
- // 获取二进制方式打开的文本文件file中pos位置之前的c字符所在位置加1
- fpos_t getlastlinepos( FILE* file, fpos_t pos, char c )
- {
- char buf[256+1]; // 没有memrchr这种函数,而strrchr要求字符串以零结尾,所以+1;buf的长度随便设,只是个暂时的缓存
- const size_t buflen = sizeof(buf)/sizeof(buf[0]) - 1;
- for( fpos_t fpos=pos; fpos!=0; )
- {
- size_t n = fpos>=buflen ? buflen : (size_t)fpos;
- fpos = fpos-n;
- fsetpos( file, &fpos );
- buf[ fread(buf,1,n,file) ] = '\0';
- const char* p = strrchr( buf, c );
- if( p )
- return fpos+(p-buf)+1;
- }
- return 0;
- }
- // 输出二进制方式打开的文本文件file中[pos1,pos2)位置之间的字符串
- void printfilecontent( FILE* file, fpos_t pos1, fpos_t pos2 )
- {
- fsetpos( file, &pos1 );
- char buf[256]; // buf的长度随便设,只是个暂时的缓存
- const size_t buflen = sizeof(buf)/sizeof(buf[0]);
- for( fpos_t pos=pos1; pos<pos2; pos+=(pos+buflen<pos2?buflen:pos2-pos) )
- {
- size_t n = fread( buf, 1, pos+buflen<pos2?buflen:(size_t)(pos2-pos), file );
- printf( "%.*s", n-(buf[n-1]=='\r'), buf );
- }
- }
- int main()
- {
- FILE* file = fopen( "temp.txt", "rb" ); // 若会移动文件指针,俺喜欢用二进制方式,不但速度快,而且能避开一些库函数的bug
- if( !file )
- return 1;
- fseek( file, 0, SEEK_END );
- fpos_t flen;
- fgetpos( file, &flen ); // 获得了文件长度,存于 flen 中
-
- printf( "倒数第一行是: " );
- fpos_t pos1 = getlastlinepos( file, flen, '\n' );
- printfilecontent( file, pos1, flen );
- printf( "\n" );
- if( pos1 > 1 )
- {
- printf( "倒数第二行是: " );
- fpos_t pos2 = getlastlinepos( file, pos1-1, '\n' );
- printfilecontent( file, pos2, pos1-1 );
- printf( "\n" );
- }
- fclose( file );
- return 0;
- }
复制代码 |
|