实现linux上类似wc -l -w -c + 文本文件的函数

#include <apue.h>


#define LINE_AVA    1
#define WORD_AVA    2       //用一个变量可以表示三个信息
#define CHAR_AVA    4


#define ONE_MAX     10    //一次能读的最多的字节数


void do_work(int,char **);
void do_count(char *,int);


void do_work(int ac,char **av)
{
    int rst = -1;
    int how = 0;
    int loop=0;
    int index=0;


    if(1 >= ac || NULL == av){     //如果参数小于等于1,即没有参数,或av 指向不合法,退出
        return ;
    }
    for(loop=1;loop<ac;++loop){
        if('-' == av[loop][0]){        //判断是否有参数前面的 " - "
            index = 1;
            while('\0' != av[loop][index]){      //判断" - "后面的参数是否为 "w","l","c"等
                switch(av[loop][index]){         //注意switch 后面只能跟字符常量或整型常量
                   case 'w':
                       how |= WORD_AVA ;    //用位运算操作节省了变量     how = 2   ,2就是权重
                       break;
                   case 'l':
                       how |= LINE_AVA;      //1
                       break;
                   case 'c':
                       how |= CHAR_AVA;     //4
                       break;
                   default:
                       printf("Usage : %s <-w|c|l> <filename>\n",av[0]);
                       return ;
                       break;
                }//end switch
                ++index;
            }//end while
        }//end if
    }//end for


    if(0 == how){
        how = WORD_AVA | LINE_AVA | CHAR_AVA ;
    }


    for(loop=1;loop<ac;++loop){
        if('-' != av[loop][0]){
            do_count(av[loop],how);
        }
    }
    return;
}


void do_count(char *filename,int how)
{
    int fd = -1;
    int word=0;
    int line=0;     //多少行
    int character=0;   //多少个字符
    int fsize=0;       //文件总大小
    int msize=0;        //每次读的大小
    int loopcnt = 0;      //如果每次读的大小小于总大小,要读的次数
    int index = 0;
    int flag = 0;
    struct stat statbuf;      //定义一个结构体statbuf,而它声明的结构体原型stat则在 sys/stat.h 中声明 
    char *fbuf = NULL;


    if(NULL == filename){
        return ;
    }
    fd = open(filename,O_RDONLY,0600);  //打开文件,并给于权限
    if(0 > fd){                     //若打开失败,则返回
        logerr("open");
        return ;
    }
    if(fstat(fd,&statbuf)){    //获取到已打开文件描述符的所有信息
        //printf("fstat error [%s]\n",strerror(errno));
        logerr("fstat");
        return;
    }
    fsize = character = statbuf.st_size;       //文件的总大小
    msize = ONE_MAX > fsize ? fsize : ONE_MAX ;//每次读的大小,情况1:如果每次读的大小 > 总大小,则每次缓存fbuf[]的长度设为
                                                //总大小,情况2:如果每次读的大小 < 总大小,则每次缓存fbuf[]的长度设为
                                                //每次读的大小
    loopcnt = fsize / msize + (fsize%msize > 0);//如果是情况1,则一次读完,如果是情况2,必须计算读多少次
    fbuf = (char *)malloc(msize+1);    //缓存其实就是数组,
    if(NULL == fbuf){
        printf("malloc error [%s]\n",strerror(errno));
        return;
    }
    fbuf[msize] = '\0';
/*
 *                    计算fbuf[]里面 单词数量的的算法
 *    _______hello____word_____liusenlin__      这里单词不包括换行时候 例如liusen-lin    开头有"_"   -1
 *    +1          2       3             4
 *
 *   liusenlin_______nihao__________good__        无   不用-
 *             1          2             3
 *
 *   liusenlin_______nihao__________good    当出现这种          算法出现bug
 *
 *   然而本次选取的fbuf长度足够大,所以并未出现意外
 *
 * */
    while(loopcnt){                   //循环读
        memset(fbuf,'\0',msize);         //每次读必须清除缓存
        read(fd,fbuf,msize);
        index = 0;
        while(index < msize){
            if(' ' == fbuf[index] || '\t' == fbuf[index] || '\n' == fbuf[index]){   //如果每次开始就有特殊字符则单词
                if(!flag){                                            //加1,并且
                    word += 1;
                    flag = 1;
                }
            }else{
                flag = 0;
            }
            if('\n' == fbuf[index]){
                  line += 1;
            }
            index++;
        }
        loopcnt--;
        if(' ' == fbuf[0] || '\t' == fbuf[0] || '\n' == fbuf[0]){    //如果每次开始就有特殊字符,则进行减一
            word -= 1;
        }
    }//end while
    free(fbuf);      //释放


    if(LINE_AVA & how){       //相等  与运算    ,则执行对应的
        printf(" %d ",line);
    }
    if(WORD_AVA & how){        //
        printf(" %d ",word);
    }
    if(CHAR_AVA & how){        //
        printf(" %d ",character);
    }
    printf("%s\n",filename);     //


    return;
}


int main(int ac,char **av)
{
    int fd = -1;         //初始文件描述符一般为非法值,因为文件描述符为大于零的数


    do_work(ac,av);      //传入命令行的参数
    return 0;

}


附上代码片段:



<span style="font-size:18px;">#include <apue.h>

#define LINE_AVA    1
#define WORD_AVA    2       //用一个变量可以表示三个信息
#define CHAR_AVA    4

#define ONE_MAX     10    //一次能读的最多的字节数

void do_work(int,char **);
void do_count(char *,int);

void do_work(int ac,char **av)
{
    int rst = -1;
    int how = 0;
    int loop=0;
    int index=0;

    if(1 >= ac || NULL == av){     //如果参数小于等于1,即没有参数,或av 指向不合法,退出
        return ;
    }
    for(loop=1;loop<ac;++loop){
        if('-' == av[loop][0]){        //判断是否有参数前面的 " - "
            index = 1;
            while('\0' != av[loop][index]){      //判断" - "后面的参数是否为 "w","l","c"等
                switch(av[loop][index]){         //注意switch 后面只能跟字符常量或整型常量
                   case 'w':
                       how |= WORD_AVA ;    //用位运算操作节省了变量     how = 2   ,2就是权重
                       break;
                   case 'l':
                       how |= LINE_AVA;      //1
                       break;
                   case 'c':
                       how |= CHAR_AVA;     //4
                       break;
                   default:
                       printf("Usage : %s <-w|c|l> <filename>\n",av[0]);
                       return ;
                       break;
                }//end switch
                ++index;
            }//end while
        }//end if
    }//end for

    if(0 == how){
        how = WORD_AVA | LINE_AVA | CHAR_AVA ;
    }

    for(loop=1;loop<ac;++loop){
        if('-' != av[loop][0]){
            do_count(av[loop],how);
        }
    }
    return;
}

void do_count(char *filename,int how)
{
    int fd = -1;
    int word=0;
    int line=0;     //多少行
    int character=0;   //多少个字符
    int fsize=0;       //文件总大小
    int msize=0;        //每次读的大小
    int loopcnt = 0;      //如果每次读的大小小于总大小,要读的次数
    int index = 0;
    int flag = 0;
    struct stat statbuf;      //定义一个结构体statbuf,而它声明的结构体原型stat则在 sys/stat.h 中声明 
    char *fbuf = NULL;

    if(NULL == filename){
        return ;
    }
    fd = open(filename,O_RDONLY,0600);  //打开文件,并给于权限
    if(0 > fd){                     //若打开失败,则返回
        logerr("open");
        return ;
    }
    if(fstat(fd,&statbuf)){    //获取到已打开文件描述符的所有信息
        //printf("fstat error [%s]\n",strerror(errno));
        logerr("fstat");
        return;
    }
    fsize = character = statbuf.st_size;       //文件的总大小
    msize = ONE_MAX > fsize ? fsize : ONE_MAX ;//每次读的大小,情况1:如果每次读的大小 > 总大小,则每次缓存fbuf[]的长度设为
                                                //总大小,情况2:如果每次读的大小 < 总大小,则每次缓存fbuf[]的长度设为
                                                //每次读的大小
    loopcnt = fsize / msize + (fsize%msize > 0);//如果是情况1,则一次读完,如果是情况2,必须计算读多少次
    fbuf = (char *)malloc(msize+1);    //缓存其实就是数组,
    if(NULL == fbuf){
        printf("malloc error [%s]\n",strerror(errno));
        return;
    }
    fbuf[msize] = '\0';
/*
 *                    计算fbuf[]里面 单词数量的的算法
 *    _______hello____word_____liusenlin__      这里单词不包括换行时候 例如liusen-lin    开头有"_"   -1
 *    +1          2       3             4
 *
 *   liusenlin_______nihao__________good__        无   不用-
 *             1          2             3
 *
 *   liusenlin_______nihao__________good    当出现这种          算法出现bug
 *
 *   然而本次选取的fbuf长度足够大,所以并未出现意外
 *
 * */
    while(loopcnt){                   //循环读
        memset(fbuf,'\0',msize);         //每次读必须清除缓存
        read(fd,fbuf,msize);
        index = 0;
        while(index < msize){
            if(' ' == fbuf[index] || '\t' == fbuf[index] || '\n' == fbuf[index]){   //如果每次开始就有特殊字符则单词
                if(!flag){                                            //加1,并且
                    word += 1;
                    flag = 1;
                }
            }else{
                flag = 0;
            }
            if('\n' == fbuf[index]){
                  line += 1;
            }
            index++;
        }
        loopcnt--;
        if(' ' == fbuf[0] || '\t' == fbuf[0] || '\n' == fbuf[0]){    //如果每次开始就有特殊字符,则进行减一
            word -= 1;
        }
    }//end while
    free(fbuf);      //释放

    if(LINE_AVA & how){       //相等  与运算    ,则执行对应的
        printf(" %d ",line);
    }
    if(WORD_AVA & how){        //
        printf(" %d ",word);
    }
    if(CHAR_AVA & how){        //
        printf(" %d ",character);
    }
    printf("%s\n",filename);     //

    return;
}

int main(int ac,char **av)
{
    int fd = -1;         //初始文件描述符一般为非法值,因为文件描述符为大于零的数

    do_work(ac,av);      //传入命令行的参数
    return 0;
}
</span>

你可能感兴趣的:(系统编程)