【问题标题】:Why is this code skipping the first character and printing a special character at the end of the file为什么这段代码会跳过第一个字符并在文件末尾打印一个特殊字符
【发布时间】:2020-06-08 06:54:29
【问题描述】:
ch = getc(lname);
while (ch != EOF)
{
    ch = getc(lname);
    if (ch == '\n')
        temp++;
    //except the line to be deleted
    if (temp != delete_line)
    {
        //copy all lines in file replica.c
        putc(ch, rep);
    }
}

我有一个文件,其中包含以下数据

Aryan Verma
Vinayak Sharma
Dev Deol
Ameesh Deol

上面的代码基本上通过将行值放在delete_line中来跳过我想要的数据行。 这里, temp 被初始化为 1。现在的问题是,这段代码跳过了第一个字符,在这种情况下是“A”,并在文件末尾放置了一个特殊的字符“ÿ”。 例如,delete_line=3

ryan Verma
Vinayak Sharma
Ameesh Deol
ÿ

另外,如果 delete_line 初始化为 1,它会跳过文件中的整行,例如:


Vinayak Sharma
Dev Deol
Ameesh Deol
ÿ

请告诉我是否有办法从文件的第一行写入,即使 delete_line 已初始化为 1。

【问题讨论】:

  • 您在循环外调用getc,然后立即在循环内使用getc 将其丢弃。这就是缺少第一个字符的原因。
  • 您检查EOF 将字符写入文件之后。这就是最后一个字符无效的原因。
  • ch 还是int?如果不是,则比较 ch != EOF 没有意义。
  • 另外EOF 不是一个字符:它是一个信号。收到EOF 信号后,您不应再阅读更多字符
  • 请提供minimal reproducible example 作为解决方案代码提案的基础。

标签: c file-handling filehandle


【解决方案1】:

您的代码跳过了第一个字符,因为您在调用getc() 后再次调用它来读取第一个字母。除了使用它来决定是否进入循环之外,您没有对第一个字符做任何事情,您没有打印它。

您需要将第二次调用 getc() 移动到循环体的底部,而不是顶部:

ch = getc(lname);
while (ch != EOF)
{
    // ch = getc(lname); <-- move this...
    if (ch == '\n')
    ... 
    ch = getc(lname); // <-- ... down here instead
}

至于打印出ÿ的代码,也是因为您第二次调用getc()的位置不对。

ÿ 的数值为0xFF,当它被视为char 时,它与EOF 的值相同。在下一次循环迭代之前,您不会检查对 getc() 的第二次调用的返回值,在您已经打印 ch 而不管其值如何。

您的循环应该看起来更像这样:

ch = getc(lname);
while (ch != EOF)
{
    if (ch == '\n')
        temp++;
    //except the line to be deleted
    if (temp != delete_line)
    {
        //copy all lines in file replica.c
        putc(ch, rep);
    }
    ch = getc(lname);
}

另外,也可以这样重写:

while ((ch = getc(lname)) != EOF)
{
    if (ch == '\n')
        temp++;
    //except the line to be deleted
    if (temp != delete_line)
    {
        //copy all lines in file replica.c
        putc(ch, rep);
    }
}

至于额外的换行符,那是因为您正在打印属于“已删除”行的'\n' 字符。当您遇到'\n' 字符时,您首先增加temp,然后评估if (temp != delete_line) 以调用putc()。当temp 等于delete_line 时,你跳过putc(),但是当你到达delete_line'\n' 字符时,你首先增加temp,使if (temp != delete_line) 评估为真,所以你@987654346 @'\n' 字符。你需要颠倒这个逻辑。

您的最终循环代码应该看起来更像这样:

while ((ch = getc(lname)) != EOF)
{
    // copy all lines in file replica.c
    // except the line to be deleted
    if (temp != delete_line)
    {
        putc(ch, rep);
    }
    if (ch == '\n')
        temp++;
}

【讨论】:

  • 这确实修复了跳过第一个字符和特殊字符,但它不修复delete_line初始化为1后文件中的空白行
  • @aaks-ctrl 这是因为您正在打印“已删除”行的 '\n' 字符而不是跳过它。我已经更新了我的答案
猜你喜欢
  • 2019-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-09
  • 1970-01-01
  • 2011-05-28
  • 1970-01-01
  • 2023-03-13
相关资源
最近更新 更多