【问题标题】:Custom getLine() function for cc 的自定义 getLine() 函数
【发布时间】:2012-09-21 08:28:17
【问题描述】:

我需要一个函数/方法,它将接收一个 char 数组并将其设置为从标准输入读取的字符串。它需要返回读取的最后一个字符作为它的返回类型,所以我可以确定它是到达行尾还是文件尾标记。

这是我目前所拥有的,我有点基于 here 的代码

更新:我更改了它,但现在它只是在文本后按 Enter 时崩溃。我知道这种方式效率低下,并且 char 不是 EOF 检查的最佳选择,但现在我只是想让它返回字符串。我需要它以这种方式而不是其他方式来做到这一点。我需要字符串是行的确切长度,并返回一个值,即换行符或 EOF int,我相信它仍可用于 char 值。

这个程序是 C 而不是 C++

char getLine(char **line);

int main(int argc, char *argv[])
{
    char *line;
    char returnVal = 0;

    returnVal = getLine(&line);
    printf("%s", line);

    free(line);

    system("pause");
    return 0;
}

char getLine(char **line) {
    unsigned int lengthAdder = 1, counter = 0, size = 0;
    char charRead = 0;

    *line = malloc(lengthAdder);
    while((charRead = getc(stdin)) != EOF && charRead != '\n')
    {
        *line[counter++] = charRead;
        *line = realloc(*line, counter);
    }

    *line[counter] = '\0';

    return charRead;
}

提前感谢您的帮助!

【问题讨论】:

  • 你想要 C 还是 C++? 正确的 解决方案在每种语言中是完全不同的。另请注意,比读取的最后一个字符的值更有趣的是读取的字符数。您始终可以查看读取字符串中的该位置以确定字符是什么。此外,多个realloc 可能效率低下。
  • 除了 H2CO3 所说的之外,您不是 returning 来自 getLine 的任何内容,尽管您声明它返回 char。此外,您不应该为每个字符realloc,以合理大小的块来执行此操作。而line = realloc(line, counter);表示如果realloc失败,则丢失对内存的引用,使用临时保存realloc的结果并检查是否为NULL

标签: c string getline


【解决方案1】:

您将malloc() 的结果分配给line 的本地副本,因此在getLine() 函数返回后它不会被修改(尽管您认为它是)。您要做的就是返回它(而不是使用输出参数)或传递它的地址(通过引用传递它):

void getLine(char **line)
{
    *line = malloc(length);

    // etc.
}

然后这样称呼它:

char *line;
getLine(&line);

【讨论】:

  • 我把它改成了这个,但现在它在输入数据时崩溃了。更改的代码在操作中更新。
  • @Tookie On 所以我们不会为您编写完整的解决方案,抱歉。这是您错过的基本思想——除此之外,请学习使用调试器,谷歌关于指针等的好教程。
【解决方案2】:

您使用realloc 的方式不正确。如果返回NULL,则内存块将丢失。

这样使用realloc比较好:

char *tmp;
...
tmp = realloc(line, counter);
if(tmp == NULL)
   ERROR, TRY TO SOLVE IT
line = tmp;

【讨论】:

  • 是的,但这并不能回答问题。这应该是评论,而不是答案。
【解决方案3】:

您的关键问题是 line 指针值不会传播到 getLine() 函数之外。解决方案是将 指向 line 指针 的指针作为参数传递给函数 - 像 getLine(&line); 一样调用它,而函数将被定义为采用参数 char **line .在函数中,在您现在使用 line 的所有地方,您将使用 *line 代替,即取消对指针的引用并使用ma​​in() 中指针指向的变量。希望这不会太混乱。 :-) 试着把它画在一张纸上。

(一个棘手的部分 - 您必须将 line[counter] 更改为 (*line)[counter] 因为您首先需要取消引用指向字符串的指针,并且只有 然后 才能访问字符串中的特定字符。)

您的代码还有其他几个问题:

  • 您使用 char 作为 charRead 的类型。但是,EOF 常量不能使用 char 表示,您需要使用 int - 两者都作为 charRead 的类型> 和 getLine() 的返回值,这样您就可以真正区分换行符和文件结尾。
  • 您忘记返回从 getLine() 函数读取的最后一个字符。 :-)
  • 您在每次添加字符后重新分配缓冲区。这不是非常有效,因此是一种相当丑陋的编程实践。使用另一个变量来跟踪分配的空间量并不太难,然后 (i) 从分配合理的内存块开始,例如64 字节,因此理想情况下,您永远不会重新分配 (ii) 仅当您需要基于比较计数器和分配大小跟踪器时才扩大分配。两种重新分配策略很常见 - 将分配的大小加倍或按固定步长增加分配。

【讨论】:

  • 我知道它现在效率低下,我只是想让它返回字符串 atm。当我让它返回字符串时,我会担心其他所有事情。我将参数更改为 **char,并将其传递为地址,并将其更改为函数内它通过 *line 设置所有内容的位置。现在它只是在打开时崩溃
  • 一个棘手的部分 - 您必须将 line[counter] 更改为 (*line)[counter] 因为您首先需要取消引用指向字符串的指针,并且只有 然后 访问字符串中的特定字符。这有帮助吗?如果没有,它到底在哪里崩溃?尝试在调试器中运行它。
  • 是的,我更改了它,它在输入文本后崩溃。之前,如果我在函数中放置一个 printf,它确实可以很好地获取字符串,但不会返回它。我知道我是按值传递它,所以它没有被保存到原始文件中。现在我根本无法检查。更新后的代码在上面
  • 在您更新的代码中,您仍然使用*line[counter] 而不是(*line)[counter]。评估顺序的一个简单经验法则是 (i) 首先,评估变量名称之后 的任何内容,(ii) 然后评估它之前 的任何内容。所以对于*line[counter][counter](数组查找)在之前完成*(直接指针解引用)
  • 不客气。如果对您有帮助,您可以投票赞成我的回答。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
  • 1970-01-01
  • 2012-10-18
  • 2018-05-13
相关资源
最近更新 更多