【问题标题】:Why won't my file written using fputc terminate?为什么我使用 fputc 写入的文件不会终止?
【发布时间】:2014-11-02 09:07:07
【问题描述】:

我 3 天前刚开始学习 C,我正在尝试制作一个程序来接收文件,读取字符,并从中删除所有空格和制表符。我是一名初级程序员,在开始学习 C 之前只学了一点 MATLAB。我使用的是 Ubuntu 12.04。

这是我的代码:

#include <stdio.h>
int main ()
{
    FILE * pFile;
    FILE * pFile2;
    int c;
    pFile = fopen ("spaces.txt","r");
    pFile2 = fopen ("nospaces.txt","w");

    if (pFile==NULL) perror ("Error opening file");
    else
    {
       while (c != EOF)
       {
           c = fgetc (pFile);
           if (!(c == ' ' || c == ' '))
           {
               fputc (c, pFile2);
           }
       } 
       fclose (pFile2);
       fclose (pFile);
    }
    return 0;
}

当我打开新文件“nospaces.txt”时,一切都很好,只是最后有一个奇怪的字符。 Gedit 说它是红色背景的 /FF 或 /00 并抱怨我不应该编辑该文件,因为我可能会损坏它。无论我试图做什么,我都无法在最后摆脱那个奇怪的角色。以下是我尝试过的示例:

-使用 fputc (EOF , pFile2) 在 pFile2 末尾添加 EOF、'\0' 和其他随机字符 - 对 c 的值施加随机约束,使其不会选择不是字母或数字的字符(如 40

请帮忙。 谢谢。

【问题讨论】:

  • while (c != EOF){ c = fgetc (pFile); --> while ((c = fgetc (pFile)) != EOF){

标签: c file char eof


【解决方案1】:

您的读取循环错误。你读一个字太多了。

while (c != EOF)
{
    c = fgetc (pFile);
    if (!(c == ' ' || c == \t)) {   
        fputc (c, pFile2);
    }
} 

这就是说:“虽然c 不等于文件结尾的值,再读一个字符并写入它”嗯,再一个字符是EOF。您需要在检查之前提取字符:

while ((c = fgetc(pFile)) != EOF)
{
    if (c != ' ' && c != \t) {   
        fputc (c, pFile2);
    }
} 

附带说明,c 在您第一次阅读它之前是未初始化的,这会调用未定义的行为,因为它的值是不确定的。新版本也修复了这个问题。

【讨论】:

  • 谢谢,这成功了。使用 if(not this and not that) 而不是 if not (this or that) 是否有特定的“编程稳健性”原因?
  • @AAC:嗯,最重要的是,我认为它更清楚。它还具有短路评估的优点。如果第一个条件失败,则无需检查第二个条件。你的必须检查两个相等性。
  • 原版也使用短路求值。如果第一个为 false,则不评估 || 的另一侧。在这种情况下,我们可以预期大多数字符不是空格或制表符,因此== 检查可能会产生假(相反!= 检查可能会产生真)。这意味着使用|| 的原始版本将比使用&amp;&amp; 的版本更频繁地短路。所以这个版本对这两个表达式的计算都比原来的要多。
  • @slebetman:你说得对,不知道我在想什么。
【解决方案2】:

你去:

int c;
// ...
while ( c != EOF )

这使用了c uninitialized 的值,它没有明确定义的行为。

你最后得到一个假字符的原因是因为当你在到达文件末尾后调用fgetc时,c被设置为EOF,但是你继续调用fputc(c, pFile2) EOF

在不需要重复代码的情况下解决这两个问题的常用方法是在测试条件中包含读取操作:

while ( (c = fgetc(pFile)) != EOF )
{
    if ( c != ' ' )
        fputc(c, pFile2);
}

另外,这行逻辑有问题:

if (!(c == ' ' || c == '    ')) {  

第一个测试,c == ' ' 已经足够清晰了。但我不知道你想对测试的第二部分做什么(而且我确信你没有达到它的目的!)。 ' ' 中包含的内容代表一个单个字符

我突然想到,也许你的意思是水平制表符;如果是这样,那么写'\t'。您可能会发现来自&lt;ctype.h&gt; 的函数isspace 很有用,它检查空格(尽管它也将'\n' 视为空格,因此您需要为此例外)。

【讨论】:

    【解决方案3】:

    其实你的c首先是未初始化的,所以先读取,然后在while中检查条件,如下所示

    while ((c = fgetc(pFile)) != EOF)
    {
     if (c != ' ' && c != \t) 
       {   
        fputc (c, pFile2);
       }
    } 
    

    【讨论】:

      猜你喜欢
      • 2012-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-14
      • 1970-01-01
      相关资源
      最近更新 更多