计算文本文件中的字符使用情况? C
Counting Character usage in text file? C
嗨,
我需要计算一些纯文本文件中字母字符的使用情况。这就是我带来的。基本上只是 运行 通过文本文件并将每个字符与特定搜索字符的 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);
}
在 for 循环结束时将指针倒回到文件开头?
之前发过:
P.S。 - 也许为你的输出值使用一个数组:int charactercount[pow(2,sizeof(char))] 这样你就不必重复解析文件?
编辑:缺少 pow()
因为第一次之后你就到了文件的末尾。
和你的 c = toupper(getc(fp));之后返回-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()
的 return 值以确保文件已成功打开。
有一个数组 sum
,它保存每个字符在 ASCIIend
和 ASCIIstart
宏表示的范围内出现的次数。
数组的大小就是要统计出现次数的字符个数
使用 sum[c-ASCIIstart]
是因为 c
和 ASCIIstart
的 ASCII 值(如果编码确实是 ASCII)之间的差异将给出与 c
关联的索引.
我不知道你说的 FILE *fopen(), fp;
是什么意思,但 fopen()
是 C 中用于打开文件的函数的名称。
然后
FILE *fopen(), *fp;
你给出了一个函数的原型fopen()
。
但在 stdio.h
中,已经有 fopen()
的原型,例如
FILE *fopen(const char *path, const char *mode);
但没有显示错误(如果有的话),因为 fopen()
意味着该函数可以有任意数量的参数。看看here.
如果你的 FILE *fopen();
的 return 类型不是 FILE *
或者如果它被显示给其他参数类型如 int
,你肯定会得到一个错误.
而且,void main()
不被认为是好的做法。请改用 int main()
。看here.
为了只计算一个字符,您正在读取整个文件并对每个字符重复此操作。相反,您可以这样做:
#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;
}
可以使用字符数组,遍历一次解析文件内容,最后显示数组个数。
#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]);
}
}
希望对您有所帮助!!
TLDR
使用您的代码,您的循环是由内而外的。
我将以伪代码的形式回答,以使概念简单明了。
现在你正在这样做:
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' 的文件,然后到达文件末尾,因此 'B'...'Z' 什么也做不了
如果你换了这个:
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 作为练习。
嗨,
我需要计算一些纯文本文件中字母字符的使用情况。这就是我带来的。基本上只是 运行 通过文本文件并将每个字符与特定搜索字符的 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);
}
在 for 循环结束时将指针倒回到文件开头?
之前发过:
P.S。 - 也许为你的输出值使用一个数组:int charactercount[pow(2,sizeof(char))] 这样你就不必重复解析文件?
编辑:缺少 pow()
因为第一次之后你就到了文件的末尾。 和你的 c = toupper(getc(fp));之后返回-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()
的 return 值以确保文件已成功打开。
有一个数组 sum
,它保存每个字符在 ASCIIend
和 ASCIIstart
宏表示的范围内出现的次数。
数组的大小就是要统计出现次数的字符个数
使用sum[c-ASCIIstart]
是因为 c
和 ASCIIstart
的 ASCII 值(如果编码确实是 ASCII)之间的差异将给出与 c
关联的索引.
我不知道你说的 FILE *fopen(), fp;
是什么意思,但 fopen()
是 C 中用于打开文件的函数的名称。
然后
FILE *fopen(), *fp;
你给出了一个函数的原型fopen()
。
但在 stdio.h
中,已经有 fopen()
的原型,例如
FILE *fopen(const char *path, const char *mode);
但没有显示错误(如果有的话),因为 fopen()
意味着该函数可以有任意数量的参数。看看here.
如果你的 FILE *fopen();
的 return 类型不是 FILE *
或者如果它被显示给其他参数类型如 int
,你肯定会得到一个错误.
而且,void main()
不被认为是好的做法。请改用 int main()
。看here.
为了只计算一个字符,您正在读取整个文件并对每个字符重复此操作。相反,您可以这样做:
#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;
}
可以使用字符数组,遍历一次解析文件内容,最后显示数组个数。
#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]);
}
}
希望对您有所帮助!!
TLDR
使用您的代码,您的循环是由内而外的。
我将以伪代码的形式回答,以使概念简单明了。
现在你正在这样做:
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' 的文件,然后到达文件末尾,因此 'B'...'Z' 什么也做不了
如果你换了这个:
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 作为练习。