计算文本文件中的字符使用情况? 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,它保存每个字符在 ASCIIendASCIIstart 宏表示的范围内出现的次数。

数组的大小就是要统计出现次数的字符个数

使用

sum[c-ASCIIstart] 是因为 cASCIIstart 的 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 作为练习。