为什么这个函数不会计算文本中的字符?我在main函数中打开文件,包括countchars.also文件是从countchars之前的函数打开但是我在countchars结束时关闭它。为什么fscanf没有!= EOF只读取最后一个字母?
void countchars(FILE *p){
char ch;
int countc=0;
for(;(fscanf(p,"%c",&ch)!=EOF);countc++);
printf("%d",countc);
REST代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getchoice(void);
void inserttextfromfile();
void printtextdata(FILE *);
void countwords(FILE *);
void calculatetextstatistics();
void countchars(FILE *);
int main(){
int a;
while((a=getchoice())){
switch (a){
case 1:
break;
case 2: ;
break;
case 3: ;
break;
case 4: ;
break;
case 5:calculatetextstatistics() ;
break;
case 6: ;
break;
default: break;
}
}
return 0;
}
int getchoice(){
int a;
scanf("%d",&a);
return a;
}
void calculatetextstatistics(){
FILE *p;
p=fopen("mytext.txt","rt");
countwords(p);
countchars(p);
fclose(p);
}
void countwords(FILE *p){
int countw=0;
char wordholder[10]=" ";
char wordlist[60][10];
for (;(fscanf(p,"%s",wordholder))!= EOF;countw++);
printf("%d\n",countw);
return;
}
void countchars(FILE *p){
char ch;
int countc=0;
for(;(fscanf(p,"%c",&ch)!=EOF);countw++);
printf("%d",countw);
}
答案 0 :(得分:3)
您读取文件内容的方法效率很低但应该有效,除非流指针p
具有无效值,例如NULL
。
用于此目的的经典代码是:
#include <stdio.h>
void countchars(FILE *fp) {
int ch;
int countc = 0;
while ((c = getc(fp)) != EOF)
countc++;
printf("%d\n", countc);
}
您的功能失败,因为该流已被读取到文件末尾。您可以使用rewind(fp);
或fseek(fp, 0L, SEEK_SET);
将文件流重置为文件的开头,但并非所有流都可以通过这种方式重绕。例如,无法重新启动从控制台读取。
计算单词的功能被破坏:如果文件中的任何单词超过9个字节,则表示您有未定义的行为。您应该一次读取一个字符并计算从空格到非空格字符的转换次数:
#include <ctype.h>
#include <stdio.h>
void countwords(FILE *fp) {
int countw = 0;
int c, lastc = '\n';
while ((c = getc(fp)) != EOF) {
countw += isspace(lastc) && !isspace(c);
lastc = c;
}
printf("%d\n", countw);
}
如果您坚持使用fscanf()
,可以选择以下方法:
void countwords(FILE *fp) {
int countw = 0;
char c, lastc = '\n';
while (fscanf(fp, "%c", &c) == 1) {
countw += isspace((unsigned char)lastc) && !isspace((unsigned char)c);
lastc = c;
}
printf("%d\n", countw);
}
答案 1 :(得分:3)
你有:
FILE *p;
p=fopen("mytext.txt","rt");
countwords(p);
countchars(p);
fclose(p);
由于countwords()
读取到EOF,countchars()
会立即获得EOF。使用:
FILE *p;
p=fopen("mytext.txt","rt");
countwords(p);
rewind(p);
countchars(p);
fclose(p);
这会在countwords()
达到EOF后将文件流倒回到文件的开头,以便countchars()
可以重新读取该文件。请注意,这仅适用于常规磁盘文件;它不适用于管道,终端,插座,因为你无法寻找那些。有一些相当简单的方法可以对数据进行单次传递,以计算字符和单词,而无需重新读取数据。但是,这些超出了这个问题的直接范围。
这也完美地证明了MCVE(Minimal, Complete, Verifiable Example)的重要性。这使得解决问题变得微不足道 - 没有MCVE,就没有问题需要解决。
请注意,getchoice()
的代码和main()
中的大转换对MCVE来说并不重要。我还必须修复示例中的代码以使其编译。
这是代码的最小化版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void countwords(FILE *);
void calculatetextstatistics(void);
void countchars(FILE *);
int main(void)
{
calculatetextstatistics();
return 0;
}
void calculatetextstatistics(void)
{
FILE *p = fopen("mytext.txt", "rt");
countwords(p);
rewind(p);
countchars(p);
fclose(p);
}
void countwords(FILE *p)
{
int countw = 0;
char wordholder[80] = " ";
for ( ; (fscanf(p, "%s", wordholder)) != EOF; countw++)
;
printf("%d\n", countw);
}
void countchars(FILE *p)
{
char ch;
int countc = 0;
for ( ; (fscanf(p, "%c", &ch) != EOF); countc++)
;
printf("%d\n", countc);
}
当我将其来源链接到mytext.txt
时,它会提供输出83 695
,而wc -wc
也会给出相同的答案。
鉴于这样的MCVE:
#include <stdio.h>
static void countchars(FILE *p)
{
char ch;
int countc = 0;
for ( ; (fscanf(p, "%c", &ch) != EOF); countc++)
;
printf("%d", countc);
putchar('\n');
}
int main(void)
{
countchars(stdin);
return 0;
}
并将其编译为程序cc17
,并在其自己的源上运行:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror cc17.c -o cc17
$ ./cc17 < cc17.c
254
$
这表明您显示的代码“有效” - 问题出在您未显示的代码中。