免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3074 | 回复: 0
打印 上一主题 下一主题

getline函数 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-01-04 21:32 |只看该作者 |倒序浏览
今天写一个小程序,统计一下一个文件中以'P'开头的行数。我用了两种方法,一种是使用sed,另一种是用c,使用了getline函数。这个函数的声明如下:

       #define _GNU_SOURCE
       #include stdio.h>
       ssize_t getline(char **lineptr, size_t *n, FILE *stream);
说明如下:

getline() reads an entire line, storing the address of the buffer containing the text into *lineptr. The buffer is null-terminated and includes the newline character, if a newline delimiter was found.
       If *lineptr is NULL, the getline() routine will allocate a buffer for containing the line, which must be freed by the user program. Alternatively, before calling getline(), *lineptr can contain a pointer to a malloc()-allocated buffer *n bytes in size. If the buffer is not large enough to hold the line read in, getline() resizes the buffer to fit with realloc(), updating *lineptr and *n as necessary. In either case, on a successfulll, *lineptr and *n will be updated to reflect the buffer address and size respectively.
On success, getline() and getdelim() return the number of characters read, including the delimiter character, but not including the terminating null character. This value can be used to handle embedded null characters in the line read.
       Both functions return -1 on failure to read a line (including end of file condition).
我觉得这个函数挺方便,可是没想到出现了一个小问题。我的程序如下:
#include stdio.h>
/*
* just for test
*
*/
int main(int ac, char **av)
{
    FILE *fp;
    char *line = NULL;
    size_t n;
    int count = 0;
    fp = fopen(av[1], "r");
    while(!feof(fp)){
        getline(&line, &n, fp);
        if(line[0] == 'P')
            count++;
        free(line);
        line = NULL;
    }
    if(line) free(line);
    printf("%d\n", count);
}
可是最后运行时,结果却时对时错。具体现象是有时统计正确,有时统计的多一个。为什么呢?我用gdb调试了一下,发现最后一行开头如果是P的话,会被统计两次。经过分析,我认为原因如下:getline每次得到一个整行,即从当前文件开始到遇到'\n'结束(此时文件的偏移量是指在'\n'的),当到最后一行时,由于往下并没有内容,line的内容没有改变(bug?),而feof()判断因为文件偏移量指在'\n'上,判断没有结束,又循环了一次,导致最后一行计算了两遍。从这些现象大概可以猜到getline()是如何实现的。理解的对不对还要请大家指正。^_^
修改后的程序如下:
#include stdio.h>
/*
* just for test
*
*/
int main(int ac, char **av)
{
    FILE *fp;
    char *line = NULL;
    size_t n;
    int count = 0;
    fp = fopen(av[1], "r");
    while(getline(&line, &n, fp) != -1){
        if(line[0] == 'P')
            count++;
        free(line);
        line = NULL;
    }
    if(line) free(line);
    printf("%d\n", count);
}
此时可以正常执行了。这是才看到man给了一个例子-_-,嗯,以后不毛糙,仔细认真。例子如下:
#define _GNU_SOURCE
       #include stdio.h>
       #include stdlib.h>
       int main(void)
       {
            FILE * fp;
            char * line = NULL;
            size_t len = 0;
            ssize_t read;
            fp = fopen("/etc/motd", "r");
            if (fp == NULL)
                 exit(EXIT_FAILURE);
            while ((read = getline(&line, &len, fp)) != -1) {
                 printf("Retrieved line of length %zu :\n", read);
                 printf("%s", line);
            }
            if (line)
                 free(line);
            return EXIT_SUCCESS;
       }
顺便说一下sed的实现:
sed -n -e '/P/p' myfile | grep -c 'P'


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/29336/showart_226411.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP