82 密码分析

82 密码分析

作者: Turbo时间限制: 1S章节: 结构体

问题描述 :

密码分析学中常常需要统计字符出现的频度。给定若干行短文,要求按字符出现的频度由高到低输出,当两个字符出现的频度相同时,按字符大小的顺序输出。

注意:只需要统计英文字母的频度,非英文字母一律忽略。

输入说明 :

输入由多组数据组成。每组数据由一行长度不超过100的字符串组成,不区分字母大小写,如A与a看作同一个字母。

输出说明 :

对每组输入数据都有若干行输出,每行有两个输出数据,第一个数据为某个大写字母,第二个数据为该字母出现的频度,两个数据之间有一个空格。输出顺序按字母出现的频度由高到低输出,当两个字母的频度相同时,按字母大小的顺序输出。两组输出之间有一行空行。

输入范例 :

Do what you say, say what you do.
This is a test.
Count me 1 2 3 4 5.
输出范例 :

A 4
O 4
Y 4
D 2
H 2
S 2
T 2
U 2
W 2

S 3
T 3
I 2
A 1
E 1
H 1

C 1
E 1
M 1
N 1
O 1
T 1
U 1

#include<stdio.h>
#include<string.h>
#include<memory.h>
#include<ctype.h>
struct frequent{
	int count;
	int c;
};

int main(){
	char str[1001];
	int len,i,j,temp1,temp2;
	struct frequent f[26];
	while(gets(str)){
		//初始化结构体体数组,字段初试值为0
		memset(&f,0,sizeof(struct frequent)*26);
		len=strlen(str);
		for(i=0;i<len;i++){
			if(!isalpha(str[i])){
				continue;
			}
			if(islower(str[i])){
				str[i]-=32;
			}
			f[str[i]-'A'].count++;
			f[str[i]-'A'].c=str[i]-'A';
		}
		//结构体排序
		for(i=1;i<26;i++){
			//先按照频率排序desc排序
			temp1=f[i].c;
			temp2=f[i].count;
			if(f[i].count>f[i-1].count){
				for(j=i-1;j>=0&&f[j].count<temp2;j--){
					f[j+1].c=f[j].c;
					f[j+1].count=f[j].count;
				}
				f[j+1].c=temp1;
				f[j+1].count=temp2;
			}
		}
		for(i=1;i<26;i++){
			//如果频率相同再按字符大小asc排序
			temp1=f[i].c;
			temp2=f[i].count;
			if(f[i].count==f[i-1].count&&f[i].c<f[i-1].c){
				for(j=i-1;f[j].c>temp1;j--){
					f[j+1].c=f[j].c;
					f[j+1].count=f[j].count;
				}
				f[j+1].c=temp1;
				f[j+1].count=temp2;
			}
		}
		for(i=0;i<26;i++){
			if(f[i].count>0){
				printf("%c %d\n",f[i].c+'A',f[i].count);
			}
		}
		printf("\n");
	}
	return 0;
}

#总结

1、使用memset初试化结构体值
memset(void *s, int ch,size_tn);中key实际范围应该在0~~255,因为该函数只能取ch的后八位赋值给你所输入的范围的每个字节,比如int a[5]赋值memset(a,-1,sizeof(int )*5)与memset(a,511,sizeof(int )*5) 所赋值的结果是一样的都为-1;因为-1的二进制码为(11111111 11111111 11111111 11111111)而511的二进制码为(00000000 00000000 00000001 11111111)后八位都为(11111111),所以数组中每个字节,如a[0]含四个字节都被赋值为(11111111),其结果为a[0](11111111 11111111 11111111 11111111),及a[0]=-1。
所以memset(data, 1, sizeof(data));会截取1的后八位进行单个字节的赋值,1的16进制表示为0x01,那么将int类型的4字节中每个字节赋值为01,即0x01010101;

int data[10];  
memset(data, 0, sizeof(data));    // right  
memset(data, -1, sizeof(data));    // right  
memset(data, 1, sizeof(data));    // wrong, data[x] would be 0x01010101 instead of 1  

2、使用直接插入排序先对频率desc,再对字符asc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值