首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >逐焦读流焦

逐焦读流焦
EN

Stack Overflow用户
提问于 2013-08-30 08:15:54
回答 3查看 4K关注 0票数 0

我使用这个函数来读取、逐字符、文本文件或stdin输入

代码语言:javascript
复制
void readLine(FILE *stream, char **string) {
    char c;
    int counter = 0;

    do {
        c = fgetc(stream);
        string[0] = (char *) realloc (string[0], (counter+1) * sizeof(char));
        string[0][counter++] = c;
    } while(c != ENTER && !feof(stream));

    string[counter-1] = '\0';
}

但是当我调用它时,我的程序崩溃了,我真的不知道为什么,因为我没有忘记0终止符,我确信我存储的字符序列是正确的。我已经核实了字符串的长度,但似乎没问题。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-08-30 08:26:45

这段代码中有几个问题:

  1. fgetc()返回int
  2. and friends, in C
  3. 避免使用sizeof (char),这只是编写1的一种非常笨拙的方法,因此乘法非常多余。
  4. 通常,缓冲器一次生长超过一个字符,realloc()可能会很昂贵。
  5. string[0]将更清楚地编写为*string,因为它不是数组,而是指向指针的指针。
  6. 文件末尾的逻辑意味着它将存储截断版本的EOF,这不是很好。
票数 1
EN

Stack Overflow用户

发布于 2013-08-30 09:03:00

这是一个错误:

代码语言:javascript
复制
do {
    c = fgetc(stream);
    // What happens here?!? 
} while(c != ENTER && !feof(stream));

“这里发生的事情”是在检查EOF之前将c添加到string,哇。

这是非常不好的:

代码语言:javascript
复制
    string[0] = (char *) realloc (string[0], (counter+1) * sizeof(char));

在一个循环中。realloc是一个潜在的昂贵调用,您可以对输入的每一个字节进行调用!请求一个指针参数(显然)没有分配任何东西也是一个愚蠢和混乱的接口--传入指针通常表示已经完成了。如果string是一个静态数组呢?相反,用块分配并返回一个指针:

代码语言:javascript
复制
char *readLine (FILE *stream) {
// A whole 4 kB!
    int chunksz = 4096;
    int counter = 0;
    char *buffer = malloc(chunksz);
    char *test;
    int c;
    if (!buffer) return NULL;

    while (c = fgetc(stream) && c != ENTER && c != EOF) {
        buffer[counter++] = (char)c;
        if (counter == chunksz) {
            chunksz *= 2;
            test = realloc(buffer, chunksz);
        // Abort on out-of-memory.
            if (!test) {
                free(buffer);
                return NULL;
            } else buffer = test;
        }
    }
// Now null terminate and resize.
    buffer[counter] = '\0';
    realloc(buffer, counter + 1);
    return buffer;
}

这是一个标准的“2的权力”分配计划(它加倍)。如果确实要提交指针,请预先分配指针,并提交“最大长度”参数:

代码语言:javascript
复制
void *readLine (FILE *stream, char *buffer, int max) {
    int counter = 0;
    int c;

    while (
        c = fgetc(stream)
        && c != ENTER
        && c != EOF
        && counter < max - 1
    ) buffer[counter++] = (char)c;
// Now null terminate.
    buffer[counter] = '\0';
}       
票数 2
EN

Stack Overflow用户

发布于 2013-08-30 08:19:47

更改这一行

代码语言:javascript
复制
string[counter-1] = '\0';

代码语言:javascript
复制
string[0][counter-1] = '\0';

您希望终止存储在string[0]中的字符串。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18528111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档