C 这个扫描文件并返回行数/段落数/字数的程序有什么问题?
我编写这个程序是为了接受一个文件并扫描文件中的行数、段落数和单词数 问题是,它永远不会停止扫描。它永远不会出现在while(nextChar!='\n')循环中。因此processBlank和copyText函数从未停止运行。它永远不会击中EOF 我不知道如何进行。我无法找到解决方案,因此非常感谢您的帮助:)C 这个扫描文件并返回行数/段落数/字数的程序有什么问题?,c,loops,infinite,C,Loops,Infinite,我编写这个程序是为了接受一个文件并扫描文件中的行数、段落数和单词数 问题是,它永远不会停止扫描。它永远不会出现在while(nextChar!='\n')循环中。因此processBlank和copyText函数从未停止运行。它永远不会击中EOF 我不知道如何进行。我无法找到解决方案,因此非常感谢您的帮助:) #包括 #包括 无效初始化(int*p1、int*p2、int*p3、int*p4) { *p1=0; *p2=0; *p3=0; *p4=0; } void processBlank(c
#包括
#包括
无效初始化(int*p1、int*p2、int*p3、int*p4)
{
*p1=0;
*p2=0;
*p3=0;
*p4=0;
}
void processBlank(char*nextChar,int*wordsinLine,FILE*ctPtr)
{
而(*nextChar=='')
{
printf(“%c”,*nextChar);
*nextChar=fgetc(ctPtr);
}
*wordsinLine+=1;
}
无效copyText(char*nextChar,FILE*ctPtr)
{
而(*nextChar!='')
{
printf(“%c”,*nextChar);
*nextChar=fgetc(ctPtr);
}
}
void updateCount(int*numWords,int*wordsinLine,int*numParagraphs,int*numLines)
{
*numWords+=*字行;
如果(*wordsinLine==0)
*numParagraphs+=1;
*wordsinLine=0;
*numLines+=1;
}
void printTotal(int numWords、int numLines、int numParagraphs)
{
printf(“\n\n\n\n总字数为:%d\n\n”,numWords);
printf(“总行数为:%d\n\n”,numLines);
printf(“段落总数为:%d\n\n\n\n”,numParagraphs);
}
void main()
{
int numWords、numLines、numParagraphs、wordsinLine;
初始化(&numWords,&numLines,&numParagraphs,&wordsinLine);
文件*ctPtr;
char nextChar;
if((ctPtr=fopen(“Q2read.txt”,“r”))==NULL)
printf(“无法打开文件\n”);
其他的
{
nextChar=fgetc(ctPtr);
while(nextChar!=feof(ctPtr))
{
而(nextChar!='\n')
{
processBlank(&nextChar,&wordsinLine,ctPtr);
copyText(&nextChar,ctPtr);
}
更新帐户(&numWords,&wordsinLine,&numParagraphs,&numLines);
}
printTotal(numWords、numLines、numParagraphs);
fclose(ctPtr);
}
}
fgetc()
返回一个int,而EOF
通常为-1。将nextChar声明为int并根据EOF
检查它(不是feof()
;feof()
是一个测试流的EOF的函数)
您可以改为选中
feof(stream)!=0
(比如使用if(feof(stream))
)查看您是否处于EOF,但我认为只检查fgets()
的返回值更好。与其逐字节读取文件,(速度非常慢),不如查看fgets()
函数。这将为您获得一整行文本,然后您可以从那里处理它。它确实需要一个最大字符串长度,因此如果您使用合理的值,例如1024,请始终确保检查字符串中是否有换行符,如果它不在字符串中,则需要再次读取并追加,但在执行之前,请检查您是否真的处于EOF,因为许多文件可能没有最后的\n
,或\r\n
,或者\r
,或者您正在使用的操作系统使用的任何疯狂
nextChar=feof(ctPtr)
到nextChar!=EOF
feof()
设置“
EOF
是一个负数。
两种不同的东西-不具有很好的可比性
void main()
更改为int main(void)
char-nextChar
更改为int-nextChar
(以及相关函数调用)copyText()
:在(*nextChar!=''&&*nextChar!=EOF){main()
感谢您的及时回复!我尝试了您的建议,代码的运行方式与我发布的完全相同。我假设它将看到文件的结尾,只要它能够脱离嵌套的while循环。nextChar!='\n'似乎从来都不是错误的。我还尝试添加while(nextChar!=10)(新行的ascii代码)也不退出循环不同意“check feof(stream)>0”。
feof
函数在文件末尾返回非零,不一定是正数。建议改为if(feof(stream))
@chux我同意并将更新我的答案。我试图避免匹配-1,(我的feof手册页似乎认为这可能表明存在错误),但忽略错误并继续下去并没有多大意义,因为关于fgets()
与fgetc()
的性能差异,任何支持“难以置信的慢”的基准测试?我手头没有任何基准测试,但想象一下。假设您正在读取一个非常大的文件,1兆字节,平均行长为1024个字符。这意味着您将对文件中的每行调用该函数1024次(平均),这本身似乎没什么大不了的,因为大部分文件可能都会加载到文件缓存中。但是,在C中调用函数需要时间。必须将内容推送到堆栈中,弹出,然后执行,然后返回。fgets()这是一次函数调用完成的。看到区别了吗?@chux给函数调用增加了10纳秒的开销(这是很合理的),一个字节一个字节地读取一个千兆字节会增加10秒的开销。这不是一个大问题,但不值得养成这样的习惯。还有一个更好的函数可以使用:getline()
。作为POSIX-2008标准的一部分,它真的得到了整条线,在整个过程中为它分配了足够的空间。这避免了缓冲区限制带来的许多麻烦。@chux好吧,如果fgets()
是使用fgetc()
实现的,那么该实现要么依赖于编译器内联,要么是一个普通的实现
#include <stdio.h>
#include <stdlib.h>
void initialize(int *p1,int *p2,int *p3,int *p4)
{
*p1=0;
*p2=0;
*p3=0;
*p4=0;
}
void processBlank(char *nextChar,int *wordsinLine,FILE *ctPtr)
{
while (*nextChar==' ')
{
printf("%c",*nextChar);
*nextChar=fgetc(ctPtr);
}
*wordsinLine+=1;
}
void copyText(char *nextChar,FILE *ctPtr)
{
while (*nextChar!=' ')
{
printf("%c",*nextChar);
*nextChar=fgetc(ctPtr);
}
}
void updateCount(int *numWords,int *wordsinLine,int *numParagraphs,int *numLines)
{
*numWords+=*wordsinLine;
if (*wordsinLine==0)
*numParagraphs+=1;
*wordsinLine=0;
*numLines+=1;
}
void printTotal(int numWords,int numLines,int numParagraphs)
{
printf("\n\n\n\nTotal number of words is: %d\n\n",numWords);
printf("Total number of lines is: %d\n\n",numLines);
printf("Total number of paragraphs is: %d\n\n\n\n",numParagraphs);
}
void main()
{
int numWords,numLines,numParagraphs,wordsinLine;
initialize(&numWords,&numLines,&numParagraphs,&wordsinLine);
FILE *ctPtr;
char nextChar;
if ((ctPtr=fopen("Q2read.txt", "r"))==NULL)
printf("File could not be opened\n");
else
{
nextChar=fgetc(ctPtr);
while (nextChar!=feof(ctPtr))
{
while (nextChar!='\n')
{
processBlank(&nextChar,&wordsinLine,ctPtr);
copyText(&nextChar,ctPtr);
}
updateCount(&numWords,&wordsinLine,&numParagraphs,&numLines);
}
printTotal(numWords,numLines,numParagraphs);
fclose(ctPtr);
}
}