为什么赢了';我的文件不是用fputc编写的吗?

为什么赢了';我的文件不是用fputc编写的吗?,c,file,char,eof,C,File,Char,Eof,我3天前才开始学习C语言,我正在尝试制作一个程序,它接收一个文件,读取字符,并从中删除所有空格和制表符。我是一个刚开始编程的人,在开始学习C语言之前只学了一点MATLAB。我正在使用Ubuntu12.04 这是我的密码: #include <stdio.h> int main () { FILE * pFile; FILE * pFile2; int c; pFile = fopen ("spaces.txt","r"); pFile2 = f

我3天前才开始学习C语言,我正在尝试制作一个程序,它接收一个文件,读取字符,并从中删除所有空格和制表符。我是一个刚开始编程的人,在开始学习C语言之前只学了一点MATLAB。我正在使用Ubuntu12.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;
}
#包括
int main()
{
文件*pFile;
文件*pFile2;
INTC;
pFile=fopen(“spaces.txt”,“r”);
pFile2=fopen(“nospaces.txt”,“w”);
如果(pFile==NULL)perror(“打开文件时出错”);
其他的
{
而(c!=EOF)
{
c=fgetc(pFile);
如果(!(c=''|c='')
{
fputc(c,pFile2);
}
} 
fclose(pFile2);
fclose(pFile);
}
返回0;
}
当我打开新文件“nospaces.txt”时,一切都很好,只是结尾有一个奇怪的字符。Gedit说它是带有红色背景的/FF或/00,并抱怨我不应该编辑该文件,因为我可能会损坏它。不管我怎么做,最终还是摆脱不了那个奇怪的角色。以下是我尝试过的例子:

-使用fputc(EOF,pFile2)将EOF、“\0”和其他随机字符添加到pFile2的末尾 -对c的值设置随机约束,这样它就不会选择非字母或数字的字符(比如40 请帮忙。
谢谢。

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

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
在您第一次读取它之前是未初始化的,它调用未定义的行为,因为它的值是不确定的。新版本也解决了这一问题。

您可以:

int c;
// ...
while ( c != EOF )
这将使用未初始化的
c
值,该值没有定义良好的行为

在结尾处出现伪字符的原因是,当到达文件结尾后调用
fgetc
时,
c
被设置为
EOF
,但随后使用
EOF
调用
fputc(c,pFile2)

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

while ( (c = fgetc(pFile)) != EOF )
{
    if ( c != ' ' )
        fputc(c, pFile2);
}
此外,该线路存在逻辑问题:

if (!(c == ' ' || c == '    ')) {  
第一个测试,
c=''
足够清晰。但是我不知道你在测试的第二部分想做什么(我确信你没有达到任何目标!)。
中包含的内容表示单个字符


我突然想到,也许你指的是水平标签;如果是这样,那么写
'\t'
。您可能会发现
中的函数
isspace
很有用,它可以检查空格(虽然它也将
'\n'
计算为空格,所以您需要对此进行例外)。

实际上您的
c
是未初始化的。因此,请先读取,然后在while中检查条件,如下所示

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

while(c!=EOF){c=fgetc(pFile);
-->
while((c=fgetc(pFile))!=EOF){
谢谢,这很有效。使用if(不是这个和那个)而不是if(这个或那个)有什么特别的“编程健壮性”原因吗?@AAC:嗯,最重要的是,我认为它更清楚。它还具有短路评估的优点。如果第一个条件失败,则无需检查第二个条件。您必须检查两个等式。原始版本也使用短路评估。如果第一个条件为假,则
|
的另一侧不是ev计算。在这种情况下,我们可以预期大多数字符不是空格或制表符,因此
=
检查可能会产生false(相反,
!=
检查可能会产生true)。这意味着使用
|
的原始版本比使用
&&
的版本短路的频率更高。因此,此版本对这两个表达式的求值都比原始版本高。@slebetman:你说得对,不确定我在想什么。