今天看了第十五章《输入/输出函数》,主要是介绍的一些I/O方面的库函数的用法,习题要求写一个unix上面grep程序的实现,这个grep的思路还是比较简单的:
1、处理命令行参数,将第一个参数当成是被查找的字符串,将后面的当成是文件名;
2、错误处理,如果命令行参数少于2个,就退出,打印帮助,如果只有字符串,没有文件名,则从标准输入读取;
3、在循环从文件中查找字符串时,原子操作为:
a、设置一个FILE *的结构指向文件,并打开文件;
b、用fgets函数一行一行地读文件;
c、用strstr库函数对刚才读的一行进行查找,如果找到,就把这行写到标准输出。
这样,我从最基本的版本做起,一步步实现了完整的fgrep,以下是具体的过程:
第一步:简单地从固定的文件里查找固定的字符串,这两个元素都是写死的,不支持命令行输入
[root@bjxdurs235 20090802]# cat fgrep_v1.c
#include
#include
#define MAX_LINE_CHAR 510
int main(void)
{
char const *str_to_find = "hello";
FILE *f ;
char *line;
f = fopen( "test.txt","r" );
if ( f == NULL ){
perror( "test.txt" );
exit ( 1 );
}
char buffer[MAX_LINE_CHAR];
while ( (line = fgets( buffer, MAX_LINE_CHAR, f )) != NULL ){
if ( strstr( line, str_to_find ) != NULL ){
printf("%s:","test.txt");
fputs( buffer, stdout );
}
}
}
这个版本1是最原始,最基本的实现,以下的实现都是以这个为基本来做的扩展,在这个简单的实现里主要涉及了:
1、基本的文件操作,如fopen、fgets、fputs、peror等;
2、关键的strstr用对地方;
第二步:加入对命令行参数的简单处理
[root@bjxdurs235 20090802]# cat fgrep_v2.c
#include
#include
#define MAX_LINE_CHAR 510
void useage(void)
{
printf("error!\nuseage:\nfgrep \"str\" filename filename ... \n");
}
int main( int argc, char **argv )
{
if ( argc < 2 ){
useage();
exit ( 1 );
}
char const *str_to_find = *++argv;
FILE *f ;
char *line;
while ( *++argv != NULL ){
f = fopen( *argv,"r" );
if ( f == NULL ){
perror( *argv );
//exit ( 1 );
continue;
}
char buffer[MAX_LINE_CHAR];
while ( (line = fgets( buffer, MAX_LINE_CHAR, f )) != NULL ){
if ( strstr( line, str_to_find ) != NULL ){
printf("%s:",*argv);
fputs( buffer, stdout );
}
}
}
}
第三步:从文件中查找这个操作提炼成一个函数来做
[root@bjxdurs235 20090802]# cat fgrep_v3.c
#include
#include
#define MAX_LINE_CHAR 510
void useage(void)
{
printf("error!\nuseage:\nfgrep \"str\" filename filename ... \n");
}
void my_grep( char const *str_to_find, char const *filename )
{
FILE *f ;
char *line;
f = fopen( filename,"r" );
if ( f == NULL ){
perror( filename );
//exit ( 1 );
//continue;
return ;
}
char buffer[MAX_LINE_CHAR];
while ( (line = fgets( buffer, MAX_LINE_CHAR, f )) != NULL ){
if ( strstr( line, str_to_find ) != NULL ){
printf("%s:",filename);
fputs( buffer, stdout );
}
}
}
int main( int argc, char **argv )
{
if ( argc < 2 ){
useage();
exit ( 1 );
}
char const *str_to_find = *++argv;
if ( argc == 2 ){
/* process grep from stdin */
//my_grep( str_to_find, stdin );
}
else
{
while ( *++argv != NULL ){
my_grep( str_to_find, *argv );
}
}
}
第四步:完善功能,加入对stdin的支持
[root@bjxdurs235 20090802]# cat fgrep_v4.c
#include
#include
#define MAX_LINE_CHAR 510
void useage(void)
{
printf("error!\nuseage:\nfgrep \"str\" filename filename ... \n");
}
void my_grep( char const *str_to_find, char const *filename )
{
FILE *f ;
char *line;
if ( filename == NULL ){
f = stdin;
}
else
{
f = fopen( filename,"r" );
}
if ( f == NULL ){
perror( filename );
//exit ( 1 );
//continue;
return ;
}
char buffer[MAX_LINE_CHAR];
while ( (line = fgets( buffer, MAX_LINE_CHAR, f )) != NULL ){
if ( strstr( line, str_to_find ) != NULL ){
printf("%s:",filename);
fputs( buffer, stdout );
}
}
if ( f != NULL ){
fclose(f);
}
}
int main( int argc, char **argv )
{
if ( argc < 2 ){
useage();
exit ( 1 );
}
char const *str_to_find = *++argv;
if ( argc == 2 ){
/* process grep from stdin */
//my_grep( str_to_find, stdin );
my_grep( str_to_find, NULL );
}
else
{
while ( *++argv != NULL ){
my_grep( str_to_find, *argv );
}
}
}
最后,这四个程序的行数是:
[root@bjxdurs235 20090802]# wc -l fgrep_v*
26 fgrep_v1.c
38 fgrep_v2.c
51 fgrep_v3.c
62 fgrep_v4.c
177 total
一步步地完善了这个功能,再看看习题的答案,估计人家又比我的精简,唉,刚开始写程序,总是这么繁杂,慢慢就会越来越熟练了。
阅读(1103) | 评论(0) | 转发(0) |