【问题标题】:Reading file with fgetc and adding sentences into linked list使用 fgetc 读取文件并将句子添加到链表中
【发布时间】:2016-04-15 23:36:48
【问题描述】:

过去三天我有一个问题.. 我有一个包含句子的文件。

当我阅读文件时

int maxSize = 256;
int currSize = 0;
int i = 0;
char *sentence = (char*)malloc(maxSize);
char c;

currSize = maxSize;

while ((c = fgetc(input)) != EOF)
{
    sentence[i++] = c;

    while((c = fgetc(input)) != '\n')
    {
        sentence[i++] = c;

        if((c == '.') || (c == '?') || (c == '!'))
            sentence[i++] = '\n';

        if(i == currSize)
        {
            currSize = i + maxSize;
            sentence = (char*)realloc(sentence,currSize);
        }
    }
}

sentence[i] = '\0';

addSentence(sentence);

当函数 addSentence 将句子添加到链表中时,会出现问题,因为它只添加了一个由文件中所有内容组成的句子......

我是 C 初学者。谢谢。

【问题讨论】:

  • 所以基本上你的意思是问题出在addSentence,和你展示的功能无关?
  • 使用int c;而不是char c;,因为fgetc()返回一个int,它可以保存char可以保存的任何值加上一个额外的值——EOF。
  • 跟功能有关。这是关于 \n 但我不知道如何解决它:/
  • 您的问题是您只在 EOF 处调用 addSentence(),因此在您阅读整个文件之前它不会神奇地看到任何内容。据推测,您需要在检测到句子结尾时调用它(测试'.''?''!' — 您还需要在调用 addSentence 之前将字符串终止为空并重置具有新分配和正确大小的内存)以及EOF。不清楚为什么你有两个循环;您可能会错过一些换行符作为句子的结尾。只需一个循环即可返工。
  • 我有一个 while 循环,但那个循环只读取一行,所以我想读取所有行,这就是垃圾函数..

标签: c file linked-list eof fgetc


【解决方案1】:

您的问题是您只在 EOF 处调用 addSentence(),因此在您阅读整个文件之前它不会神奇地看到任何内容。据推测,您需要在检测到句子结尾时调用它(测试'.''?''!' — 您还需要在调用 addSentence 之前空终止字符串并使用新的分配和正确的大小)以及EOF。不清楚为什么你有两个循环;您可能会错过一些换行符作为句子的结尾。只需一个循环即可返工。

换行符是否标记句子的结尾并不完全清楚。本次修订假定他们这样做:

int maxSize = 256;
int currSize = maxSize;
int i = 0;
int c;
char *sentence = (char*)malloc(maxSize);
assert(sentence != 0);  // Not a production-ready error check

while ((c = fgetc(input)) != EOF)
{
    sentence[i++] = c;

    if ((c == '\n') || (c == '.') || (c == '?') || (c == '!'))
    {
        if (c != '\n')
            sentence[i++] = '\n';
        sentence[i] = '\0';
        addSentence(sentence);
        sentence = malloc(maxSize);
        assert(sentence != 0);  // Not a production-ready error check
        currSize = maxSize;
        i = 0;
    }

    if (i == currSize)
    {
        currSize = i + maxSize;
        sentence = (char*)realloc(sentence, currSize);
        assert(sentence != 0);  // Not a production-ready error check
    }
}

sentence[i] = '\0';
addSentence(sentence);

请注意,内存分配失败的错误检查不是生产质量;应该有一些适当的、无条件的错误检查。如果句末标点正好落在错误的位置,缓冲区溢出的风险很小。生产代码也应该避免这种情况,但它会更复杂。我会使用字符串数据类型和函数来进行添加。我可能还猜测大多数句子都少于 256 个字符(尤其是如果换行符标记结尾),并且会使用 64maxSize。这将导致分配更少的未使用内存。

【讨论】:

  • 它在链表中添加空语句:/
  • 好的;所以在添加之前添加对句子长度(和/或内容)的检查。例如,如果您在一行的末尾有一个句号(句号),就会发生这种情况。你可能会认为一个充满空格的句子并不有趣。你只需要通过正在发生的事情思考你的方式。并决定期望的行为是什么。如果是我的程序,我可能会用空格替换换行符,并且只在遇到合适的标点符号时添加句子。我可能还会担心“引用的短语”。其中句号后紧跟双引号(或单引号)。
  • (括号里的句子也会有问题。)更不用说……在句子中间停顿。那是骗局;这是一个 Unicode '省略号';你也可以有......(写出老式的方式)。帕斯卡先生呢?是一两句话吗?那个真的很棘手。编程的好处之一就是你可以使用你的大脑。
  • 好的,我现在修好了,我会按照你说的处理这些棘手的事情 :) 非常感谢
猜你喜欢
  • 2017-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
  • 2015-01-28
  • 2021-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多