注册 登录
编程论坛 C++教室

[答案]统计字母的使用频率.简易版

野比 发布于 2007-06-30 21:02, 2871 次点击

我写了一个简单的, 对付考试,作业应该够了.. 各位就不要再发帖问这题了..好好消化一下..

/////////////////////////////////////////
// 字母频率统计及显示 简易版
// By Nobi 2007-6-30
/////////////////////////////////////////
#include <iostream>
using namespace std;

int getratio(int * ratio, char * str); //统计
void display(int * ratio, char * str, int len); //显示, 可设置升序/降序

void displayratio(int * ratio, int len){
cout<<"字符串长度:"<<len<<endl;
cout<<"使用频率表:"<<endl;
for(int i=0;i<26;++i)
cout<<char('A'+i)<<":"<<ratio[i]<<endl;
}

void main(){
cout<<"输入:";
char str[201];
cin>>str;
int ratio[26]; //统计26个字母出现频率 & initiate
int len=getratio(ratio,str); //串长度(不含\0)
cout<<"已排序字符串: ";
display(ratio,str,len);
displayratio(ratio,len);
}

int getratio(int * ratio, char * str){
int len=0;
for(int i=0;i<26;++i)
ratio[i]=0; for(i=0;str[i]!=0;++i){
//判断是否字母
//大写
if(str[i]>='A'&&str[i]<='Z')
//yes
++ratio[(str[i]-'A')]; //指定字母频率表(出现次数)+1
//小写
if(str[i]>='a'&&str[i]<='z')
++ratio[(str[i]-'a')]; //同上
//后续操作
++len; //统计长度
}
return len;
}
void display(int * ratio,char * str, int len){
int tmp[26]; //临时, 存放已排序字母频率
for(int i=0;i<26;++i)
tmp[i]=0;
int si; //操作寄存器
for(i=26;i>0;--i){
si=0;
for(int j=0;j<i;++j){
//获取目前最大的频率
if(ratio[si]<ratio[j])
si=j;
}
if(ratio[si]!=0){
//得到当前最大频率ratio[si]
//显示该字母
for(j=0;j<len;++j){
if(str[j]>='A'&&str[j]<='Z'){
if(str[j]=='A'+si)
cout<<str[j];
}
if(str[j]>='a'&&str[j]<='z'){
if(str[j]=='a'+si)
cout<<str[j];
}
}
}
ratio[si]=0;
}
cout<<endl;
}

12 回复
#2
天空の城2007-07-01 13:17
if(str[i]>='A'&&str[i]<='Z')
//yes
++ratio[(str[i]-'A')]; //指定字母频率表(出现次数)+1
//小写
if(str[i]>='a'&&str[i]<='z')
++ratio[(str[i]-'a')];

还不如一行代替:
++ratio[(toupper(str[i])-'A')];
#3
mp3aaa2007-07-01 16:58
你运行了吗? 在CFREE上 错误很多
#4
野比2007-07-01 21:09

To 天空の城

只用了iostream库...用那么多库没意思..

#5
野比2007-07-01 21:11

To mp3aaa

不用怀疑我, Visual C++ 6.0 sp6 + Windows Server 2003 运行通过

#6
天空の城2007-07-02 13:49

代码化简的同时没有影响效率,那么我们就应该尽量用库函数。。。

#7
weishj2007-07-02 17:26
#pragma warning(disable:4786)
#include <iostream>
#include <map>
#include <fstream>
#include <cctype>
#include <iomanip>
using namespace std;
int main()
{
map<char,int> ch;
map<char,int>::iterator iter;
char c1;
int sum=0;
ifstream ifs("source.txt");
ofstream ofs("sum.txt");
if (ifs.fail() || ofs.fail())
{
cout << "文件打开出错!" << endl;
return 1;
}
while(ifs.get(c1))
if(isalpha(c1))
{
c1=tolower(c1);
ch[c1] +=1;
}
for(iter=ch.begin();iter!=ch.end();++iter)
sum+=iter->second;
for(iter=ch.begin();iter!=ch.end();++iter)
{
cout<<setw(5)<<iter->first<<" "<<setw(6)<<iter->second<<" "<<setw(15)<<float(iter->second)/sum<<endl;
ofs<<setw(5)<<iter->first<<" "<<setw(6)<<iter->second<<" "<<setw(15)<<(float(iter->second)/sum)*100<<"%"<<endl;
}
cout<<"字母总数: "<<sum<<endl;
ofs<<"字母总数: "<<sum<<endl;
ofs.close();
ifs.close();
return 0;
}

[此贴子已经被作者于2007-7-2 17:40:56编辑过]

#8
aipb20072007-07-02 18:07
weishj,很不错。
其实一看这题目,最直观的反映就是map,不过对那些求作业的人来说,应该看不明白。
#9
野比2007-07-02 20:23
整那么多有的没的..
代码都简化没了人家学啥?.. 拿啥练手?..
#10
游乐园2007-07-02 22:14

的确 用map很方便的 ....偶没用map之前就笨了

int sum[26]={0};
char alpha[]={'a','b','c','d','e',...,'y','z','\0'};
//相当于typedef map<char,int> 了 ^^

fstream file("*.txt",ios::in);
...
while(file.get(ch))
{
for(int i=0; i<26; ++i)
if(tolower(ch)==alpha[i])
{
sum[i]++;
break;
}
}
...

[此贴子已经被作者于2007-7-2 22:20:28编辑过]

#11
HJin2007-07-03 11:39
回复:(野比)[答案]统计字母的使用频率.简易版

Using a map is a very good approach for handling this kind of stuff. However, if you don't want to use STL, you can use an array.

/*---------------------------------------------------------------------------
File name: LetterStats.cpp
Author: HJin
Created on: 7/2/2007 20:36:21
Environment: Windows XP Professional SP2 English +
Visual Studio 2005 v8.0.50727.762


Modification history:
===========================================================================

Analysis:
---------------------------------------------------------------------------

Sample output:
---------------------------------------------------------------------------
A: 1
B: 1
C: 1
D: 0
E: 0
F: 0
G: 1
H: 2
I: 2
J: 0
K: 0
L: 2
M: 1
N: 4
O: 1
P: 1
Q: 0
R: 0
S: 2
T: 1
U: 0
V: 0
W: 2
X: 0
Y: 0
Z: 0
a: 8
b: 3
c: 8
d: 7
e: 18
f: 7
g: 3
h: 5
i: 16
j: 2
k: 0
l: 2
m: 6
n: 12
o: 18
p: 3
q: 0
r: 14
s: 11
t: 16
u: 7
v: 2
w: 1
x: 0
y: 4
z: 0
Press any key to continue . . .

Reference:

*/

#include <iostream>
#include <fstream>

using namespace std;

/** content of a.txt

WASHINGTON (CNN) -- President Bush commuted Monday the prison term of
former White House aide I. Lewis "Scooter" Libby, facing 30 months in
prison after a federal court convicted him of perjury, obstruction of
justice and lying to investigators.

*/


int main(int argc, char** argv)
{
/**
c[0..25] for letter A..Z
c[26..51] for letter a..z
*/
int c[52];
int i;

for(i=0; i<52; ++i)
c[i] = 0;

ifstream ifs("a.txt");
if(!ifs)
{
cout<<"cannot open file a.txt.\n";
exit(0);
}

char ch;

while(ifs.get(ch))
{
if(ch>='A' && ch <= 'Z')
++c[ch-'A'];

if(ch>='a' && ch <= 'z')
++c[ch-'a'+26];
}
ifs.close();

for(i=0; i<26; ++i)
{
cout<<char('A'+i)<<": "<<c[i]<<endl;
}

for(i=26; i<52; ++i)
{
cout<<char('a'+i-26)<<": "<<c[i]<<endl;
}

return 0;
}

#12
野比2007-07-04 12:42
呵呵, 使用map肯定完全超出了这题考试的范围, 不过对学习C++的考生来说是一个拓宽思路, 提高能力的好机会
#13
hehe2142010-06-28 10:38
哥我用了你这个程序 链接之后输入字母 使用频率表里字母频率都是0  这是什么问题 麻烦你告诉我一下怎么改  明天就用了 !!谢谢了
1