嗨,
我需要计算一些纯文本文件中字母字符的用法。这就是我的意思。基本上只需运行文本文件,并将每个字符与特定搜索字符的ASCII值进行比较。
当我运行它时,我所能看到的只是第一个printf()
字符串,并且当我关闭控制台时只是终止状态的错误。
我在.exe文件所在的文件夹中有一个text.txt文件,但我看不到任何内容。
不确定我的语法是坏还是语义。
求救! : - )
#include <stdio.h>
#include <stdlib.h>
#define ASCIIstart 65
#define ASCIIend 90
void main(){
FILE *fopen(), *fp;
int c;
unsigned int sum;
fp = fopen("text.txt","r");
printf("Characters found in text: \n");
for (int i = ASCIIstart; i <= ASCIIend; i++){
sum = 0;
c = toupper(getc(fp));
while (c != EOF){
if (c == i){
sum = sum++;
}
c = toupper(getc(fp));
}
if (sum > 0){
printf("%c: %u\n",i,sum);
}
}
fclose(fp);
}
答案 0 :(得分:1)
不是为每个角色查找整个文件,而是
FILE *fp;
int c, sum[ASCIIend - ASCIIstart + 1]={0};
fp = fopen("file.txt,"r");
if(fp==NULL)
{
perror("Error");
return 1;
}
int i;
while( (c = toupper(getc(fp)))!= EOF)
{
if(c>=ASCIIstart && c<=ASCIIend)
{
sum[c-ASCIIstart]++;
}
}
for(i=ASCIIstart; i<=ASCIIend; ++i)
{
printf("\n%c: %d", i, sum[i-ASCIIstart]);
}
您必须检查fopen()
的返回值,以确保文件已成功打开。
有一个数组sum
,它保存了用ASCIIend
和ASCIIstart
宏表示的范围内每个字符的出现次数。
数组的大小就是要计算出现次数的字符数。
使用 sum[c-ASCIIstart]
是因为c
和ASCIIstart
的ASCII值(如果编码确实是ASCII)之间的差异将给出与c
相关联的索引。 / p>
我不知道您对FILE *fopen(), fp;
的意思,但fopen()
是用于打开文件的C函数的名称。
并通过
FILE *fopen(), *fp;
你给了一个函数原型fopen()
。
但在stdio.h
中,已经有fopen()
的原型
FILE *fopen(const char *path, const char *mode);
但是没有显示错误(如果是这样),因为fopen()
表示该函数可以包含任意数量的参数。看看here。
如果FILE *fopen();
的返回类型不是FILE *
,或者如果它显示给int
等其他参数类型,则肯定会出错。
并且,void main()
不被视为良好做法。请改用int main()
。看here。
答案 1 :(得分:1)
您可以使用字符数组并通过一次遍历来解析文件内容,并最终显示数组计数。
#include <stdio.h>
#include<ctype.h>
void main(){
FILE *fopen(), *fp;
int c;
fp = fopen("test.txt","r");
printf("Characters found in text: \n");
char charArr[26]= {0};
c = toupper(fgetc(fp));
while(c!=EOF) {
charArr[c-'A']=charArr[c-'A']+1;
c = toupper(fgetc(fp));
}
fclose(fp);
for(int i=0;i<26;i++){
printf("\nChar: %c | Count= %d ",i+65,charArr[i]);
}
}
希望这会有所帮助!!
答案 2 :(得分:0)
因为在你第一次结束文件之后。 你的c = toupper(getc(fp));之后返回-1。
答案 3 :(得分:0)
对于只计算一个字符,您正在读取整个文件并为每个字符重复此操作。相反,你可以这样做:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define ASCIIstart 65
#define ASCIIend 90
int main(){
FILE *fp;
int c, i;
int alphabets[26] = {0};
fp = fopen("text.txt","r");
if (fp == NULL){
fprintf (stderr, "Failed to open file\n");
return -1;
}
while ((c = toupper(fgetc(fp))) != EOF){
if (c >= ASCIIstart && c <= ASCIIend)
alphabets[c - ASCIIstart]++;
}
fclose(fp);
fprintf(stdout, "Characters found in text: \n");
for (i = 0; i < 26; i++)
fprintf (stdout, "%c: %d\n", i+ASCIIstart, alphabets[i]);
return 0;
}
答案 4 :(得分:0)
使用您的代码,您的循环是由内到外的。
我将以伪代码回答,以保持概念简单明了。
现在你正在这样做:
FOR LETTER = 'A' TO 'Z':
WHILE FILE HAS CHARACTERS
GET NEXT CHARACTER
IF CHARACTER == LETTER
ADD TO COUNT FOR CHAR
END IF
END WHILE
END FOR
问题是你正在运行带有字符A&#39; A&#39;然后到达文件的末尾,这样就不会为B&#39; ...&#39; Z&#39;
做任何事情。如果换了这个:
WHILE FILE HAS CHARACTERS
GET NEXT CHARACTER
FOR LETTER = 'A' TO 'Z'
IF LETTER = UCASE(CHARACTER)
ADD TO COUNT FOR LETTER
END IF
END FOR
END WHILE
显然,对每个字母进行26次检查太多,所以也许是一种更好的方法。
LET COUNTS = ARRAY(26)
WHILE FILE HAS CHARACTERS
CHARACTER := UCASE(CHARACTER)
IF CHARACTER >= 'A' AND CHARACTER <= 'Z'
LET INDEX = CHARACTER - 'A'
COUNTS[INDEX]++
ENDIF
END WHILE
您可以将伪代码翻译为C作为练习。
答案 5 :(得分:-1)
在for循环结束时将指针倒回到文件的开头?
之前已发布:Resetting pointer to the start of file
P.S。 - 也许使用数组作为输出值:int charactercount [pow(2,sizeof(char))]这样你就不必重复解析文件了?
编辑:缺少pow()