1.问题描述
输入一个字符串(不含空格),分别统计大写字母A~Z、小写字母a~z、数字0~9的出现次数和频率。
2.算法思想
(1)定义一个count数组用来存储每个字符出现的次数,rate数用来存储每个字符出现的频率,A~Z、a~z、0~9共62个字符,故两个数组的长度均为62;
(2)通过ASCII码与对应字符的关系,采用强制类型转换,可以将s中每个字符出现的次数与count[i](rate数组与之相同)建立数学联系:
0~9:对应ASCII码为48~57,存在count数组的[0,9]之间;
A~Z:对应ASCII码为65~90,存在count数组的[10,35]之间;
a ~z:对应ASCII码为97~122,存在count数组的[36,61]之间;
于是在强制类型转换过程中有(详细见文末全部代码段):
if(e>=48 && e<=57) //0~9
count[e-48]++;
if(e>=65 && e<=90) //A~Z
count[e-65+10]++;
if(e>=97 && e<=122) //a~z
count[e-97+36]++;
3.程序运行截图
4.完整代码
#include<iostream>
#include<iomanip>
#include<string>
using namespace std;
int cnt() //用来判断是否继续输入
{
char judge; //判断字符
cout << "是否继续输入?(y/n)" << endl;
cin >> judge;
if(judge == 'y')
return 1;
else if(judge == 'n')
return 0;
}
void Statistic(string s,int count[],double rate[],int n) //n=52+10=62,为count数组长度
{
int t = 0;
for(int i=0;i<n;i++) //初始化计数数组count
count[i]=0;
while(s[t] != '\0') //未读取到字符串s的末尾则执行
{
int e = (int) s[t]; //强制类型转换,e为各字符对应的ASCII十进制整数
if(e>=48 && e<=57) //0~9
count[e-48]++;
if(e>=65 && e<=90) //A~Z
count[e-65+10]++;
if(e>=97 && e<=122) //a~z
count[e-97+36]++;
t++;
}
int sum = 0; //count[62]的总和,用于统计频率
for(int i=0;i<n;i++) //求总和
sum += count[i];
for(int i=0;i<n;i++) //计算频率
rate[i] = (double)count[i] / sum;
//注意此处要将count[i]强制转化为double类型 ,否则rate[i]只能求得0
cout << "统计数据为:" << endl;
for(int i=0;i<n;i++)
if(count[i])
{
if(i<10)
cout << "数字" << i << "出现的次数为:" << count[i] << "\t出现的频率为:" << fixed << setprecision(2) << rate[i] << endl;
if(i>=10 && i<36)
cout << "字母" << (char)(i+65-10) << "出现的次数为:" << count[i] << "\t出现的频率为:" << fixed << setprecision(2) << rate[i] << endl;
if(i>=36 && i<62)
cout << "字母" << (char)(i+97-36) << "出现的次数为:" << count[i] << "\t出现的频率为:" << fixed << setprecision(2) << rate[i] << endl;
}
}
int main()
{
string s;
int count[62];
double rate[62];
while(1)
{
cout << "请输入一段字符串:" << endl; //注意,输入的字符串不能带空格,这是由于string本身的特性决定
cin >> s;
Statistic(s,count,rate,62);
if(!cnt())
break;
}
}