c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define NUM_CHARS 128
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <filename>\n", argv[0]);
return 1;
}
FILE *file;
int c;
int char_frequencies[NUM_CHARS] = {0};
if ((file = fopen(argv[1], "r")) == NULL) {
printf("Error: Unable to open file '%s'\n", argv[1]);
return 1;
}
// 实现字符频率统计
while ((c = fgetc(file)) != EOF) {
if (isascii(c)) { // 判断是否为ASCII字符
char_frequencies[c]++; // 每种字符在ASCII中都有对应的索引,这个数组正好一一映射
}
}
/*
判断字符是否为可打印字符的目的是为了确保直方图输出的可读性和易理解性。
在ASCII码中,除了表示字符的ASCII码值(0~127)外,还有一些控制字符,如换行
符、制表符、回车符等,这些字符在文本中不可见,并且输出它们可能会导致直方图
失去可读性。
*/
printf("字符出现频率直方图:\n");
for (int i = 0; i < NUM_CHARS; i++) {
if (char_frequencies[i] > 0 && isprint(i)) { // 判断是否为可打印字符,并且字符是否出现过
printf("%c: ", i);
for (int j = 0; j < char_frequencies[i]; j++) {
printf("■");
}
printf("\n");
}
}
fclose(file);
return 0;
}
#include <stdio.h>
:包含标准输入输出库,提供了文件操作和输入输出功能。#include <stdlib.h>
:包含标准库,提供了一些常用的函数和类型。#include <ctype.h>
:包含字符处理函数库,用于字符分类和转换。#define NUM_CHARS 128
:定义了常量**NUM_CHARS
**,表示ASCII码字符的数量,取值为128。int main(int argc, char *argv[])
:程序的入口函数,接受命令行参数。if (argc != 2)
:检查命令行参数数量是否正确,如果不是2个参数,打印使用说明并退出程序。FILE *file;
:声明了一个文件指针**file
**,用于打开和操作文件。int c;
:声明了一个整型变量**c
**,用于存储读取的字符。int char_frequencies[NUM_CHARS] = {0};
:声明了一个整型数组**char_frequencies
**,用于记录每个字符的出现频率,初始化为0。if ((file = fopen(argv[1], "r")) == NULL)
:打开命令行参数指定的文件,如果文件打开失败,则打印错误信息并退出程序。while ((c = fgetc(file)) != EOF)
:逐个读取文件中的字符,直到文件结束。if (isascii(c))
:判断字符是否为ASCII字符。char_frequencies[c]++;
:根据字符的ASCII码值,将对应位置的频率加1。printf("字符出现频率直方图:\n");
:打印输出直方图标题。for (int i = 0; i < NUM_CHARS; i++)
:遍历ASCII码字符范围。if (char_frequencies[i] > 0 && isprint(i))
:判断字符是否出现过且是否为可打印字符。printf("%c: ", i);
:打印输出当前字符。for (int j = 0; j < char_frequencies[i]; j++)
:根据字符频率,输出相应数量的字符,用于表示直方图。printf("\n");
:打印换行符,用于分隔不同字符的直方图。fclose(file);
:关闭文件,释放资源。return 0;
:返回程序执行成功的标志