资源描述
西安交通大学实验报告
课程__计算机程序设计__实验名称__指针与函数__第 1 页 共 25 页
系 别____ _______ 实 验 日 期 2014 年 4月 18日
专业班级__ ____组别_____________ 实 验 报 告 日 期 2014 年 4 月 19日
姓 名___ _______学号_ _ 报 告 退 发 ( 订正 、 重做 )
同 组 人_________________________________ 教 师 审 批 签 字
一、实验目的
学会使用递归函数和函数重载,进一步熟练动态分配等指针使用方法。
二、实验内容
(一)第一题:1、(必做题) 使用递归算法编写如下程序:对于任意给定的实数 X 和整数k( k>0) ,计算 Xk 。
1.源程序代码:
#include<iostream>
using namespace std;
double yunsuan(double x,int k);//递归函数用于计算x^k
int main()
{
double x;
int k;
cout<<"请输入实数x:";
cin>>x;
cout<<"请输入正整数k:";
cin>>k;
while(k<=0)//判断输入的k是否满足要求,若否则提示输入错误并重新输入
{
cout<<"您的输入有误!请输入正整数:";
cin>>k;
}
cout<<"计算结果是:"<<x<<"^"<<k<<"="<<yunsuan(x,k)<<endl;//输出运算结果
return 0;
}
double yunsuan(double x,int k)
{
if(k==1)//k=1时不再进行循环,输出值为x
return x;
else
{
double s=x*yunsuan(x,k-1);//对于k大于1的情况,进入下一循环
return s;
}
}
2.实验结果:
(1)输入X正实数:
(2)输入X正整数:
(3)输入x为负数:
(4)输入k为负数:
3.问题分析:
该函数的循环方式是:x^k=x*x^(k-1).设f(x,k)=x^k,那么就有f(x,k)=f(x,k-1)*x.而其结束递归的条件是k=1,此时有f(x,1)=x,由此给出初值。
(二)第二题:使用递归算法编写求斐波那契数列的第 n 项的函数,并编出主函数进行验证。
1.源程序代码:
#include<iostream>
using namespace std;
int fib(int n) //递归函数,计算斐波那契数列的第n项
{
if(n==0)//对于n=0不再进行递归,返回值0
return 0;
else
{
if(n==1)
return 1;//对于n=1不再进行递归,返回值1
else
{
int s=fib(n-1)+fib(n-2);//将计算第n项归为计算第n-1和n-2项
return s;
}
}
}
int main()
{
int n;
cout<<"请输入要计算的项数(非负整数):";//提示输入项数,首项为第0项
cin>>n;
while(n<0)//对于不符合要求的输入值重新输入
{
cout<<"输入有误,请输入非负整数:";
cin>>n;
}
cout<<"计算结果是:fib["<<n<<"]="<<fib(n)<<endl;//输出计算结果
return 0;
}
2.实验结果:
(1)输入项数正确(0或正整数):
(2)输入项数有误(负数):
3.问题分析:
该题的递归方式:第n项为之前两项之和,即:fib(n)=fib(n-1)+fib(n-2),由此递归至fib(1)和fib(2)时结束递归,而fib(1)和fib(2)已知。
(三)第三题:重载判断两个数值大小的函数 max ,这些数值可能是整型数、实型数和字符型,函数的返回值为两个数值中的最大值。
1.源程序代码:
#include<iostream>
using namespace std;
double zhuanhuan(char *c)//为了避免语句的重复,将字符与数值转换部分作为函数
{
int i=0;
double x=0;
if(c[0]=='-'||c[0]=='+')//若首字符为‘-’或者‘+’则跳过
i++;
while(c[i]!='\0'&&c[i]!='.')//对于整数部分逐位累加,直至遇到小数点或者数字结束
{
x=x*10+(c[i]-'0');
i++;
}
if(c[i]=='.')//对于小数部分进行累加
{
double s;//s用来反映数字所在位置是小数点后第几位,就用该数乘以的负几次方(s)
i++;//从小数点后的一位开始循环
for(s=0.1;c[i]!='\0';i++)
{
x=x+s*(c[i]-'0');
s=s/10;
}
}
if(c[0]=='-')//若为负数,则在上述计算基础上乘以-1得到最终值
x=-x;
return x;//返回x作为char c的对应的数值
}
int imax(int a,int b)//对整型数进行处理
{
if(a>=b)
return a;
return b;
}
double imax(double a,double b)//对实数进行处理
{
if(a>=b)
return a;
return b;
}
double imax(char *c,char *d)//对字符型进行处理
{
double x=zhuanhuan(c);
double y=zhuanhuan(d);
return (x>=y?x:y);
}int main()
{
int n;
cout<<"请选择您要输入的数的类型,\n如果是整型请输入,实数型输入,字符型输入:";
cin>>n;
while(n!=1&&n!=2&&n!=3)
{
cout<<"输入有误!重新选择:";
cin>>n;
}
int a[2];
double b[2];
char c[12],d[12];
if(n==1)//处理整型数
{
cout<<"请输入两个数:";
cin>>a[0]>>a[1];
cout<<"最大值为:"<<imax(a[0],a[1]);
}
else
{
if(n==2)//处理实数
{
cout<<"请输入两个数:";
cin>>b[0]>>b[1];
cout<<"最大值为:"<<imax(b[0],b[1]);
}
else//处理字符型
{
cout<<"请输入第一个数:";
cin>>c;
cout<<"请输入第二个数:";
cin>>d;
cout<<"最大值为:"<<imax(c,d);
}
}
cout<<endl;
return 0;
}
2.实验结果:
(1)输入整数型:
(2)输入为实数:
(3)输入为字符:
正数:
(带正号):
(不带正号):
整数:
负数:
3.问题分析:
该题的重点在于字符型的处理。在实验报告中,采取了两个数字逐个分开输入的方法,因而主要只需要判断开头是否为负号、中间是否有小数点并区别小数点前后处理方法的不同这几个问题。如果能够一次性输入两个数中间用空格隔开的话,就需要判断空格的位置,然后对空格之后的部分再进行与前半部分相同的判断方法,显得更加麻烦。
对字符型的处理思路:
首先判断首字符是不是“-”或者 “+”,如果是的话,先跳过从第二个字符开始处理,在最终的结果中再乘以-1即可;然后对于接下来的整数部分进行累加,直到遇见小数点,若没有小数点则一直执行到字符结束;如果有小数点的话,对于小数点后的部分再进行累加得到结果。
四、第四题:编写一个函数,用于去掉字符串前面的空格,其原型为 :
char *myltrim(char *string);
其中参数 string 为字符串,返回值为指向 string 的指针。
1.源程序代码:
#include<iostream>
using namespace std;
char *myltrim(char *string)
{
int i=0,j=0;
while(*(string+i)==' ')
i++;
do
{
*(string+j)=*(string+i);
i++;
j++;
}while(*(string+i-1)!='\0');
return string;
}
int main()
{
char string[41];
cout<<"请输入字符串:";
cin.get(string,40);
cout<<"去掉开头的空格之后为:\n"<<myltrim(string)<<endl;
return 0;
}
2.实验结果:为验证处理空格时仅是将开头处理而不处理中间空格:
(1)中间无空格:
(2)中间有空格:
3.问题分析:
曾经出现的问题:起初运行时发现,即使没有判断开头空格的程序,输出结果也是没有空格的,后来检查发现是输入语句没有写为cin.get导致空格不被录入。
五、第五题:用牛顿迭代法求任意一元方程: anXn+an-1Xn-1+......+a1X1+a0 = 0 的根。
提示:迭代公式:Xn+1 = Xn + f(Xn) / f'(Xn)
结束迭代过程的条件为(|f(Xn+1)|<ε )与(|Xn+1 - Xn|<ε )同时成立,其中 ε 为预先给定的精度要求。
1.源程序代码:
#include<iostream>
using namespace std;
double cf(double x,int k)//乘方函数,输出结果为x的k次方
{
double s=1;
while(k>0)
{
s=s*x;
k--;
}
return s;
}
double f(int n,double *a,double x)//计算函数值f(x)的函数
{
double sum=0;
for(int i=0;i<n;i++)
{
sum=sum+(*(a+i))*cf(x,i);
}
return sum;
}
double f_(int n,double *a,double x)//求导f_(x)函数
{
double sum=0;
for(int i=1;i<n;i++)
{
sum=sum+(*(a+i))*i*cf(x,i-1);
}
return sum;
}
double result(int n,double *a,double x) //求根函数
{
double u=0.00000001;//给定精确度
double m;//设m为中间变量储存x,以便于进行循环条件的判断
do
{
m=x;
x=x-(f(n,a,x)/f_(n,a,x));
}while(f(n,a,x)>=u||f(n,a,x)<=-u||x-m>=u||x-m<=-u);//循环直到达到精度
return x;//返回最终计算结果
}
int main()
{
int n,i;
cout<<"请输入最高项次数:";
cin>>n;
double *a=new double[n+1];//申请数组空间
cout<<"请从低到高输入系数:";
for(i=0;i<n+1;i++)
cin>>*(a+i);
double x=0;
cout<<"计算结果为:"<<result(n+1,a,x)<<endl;
delete a;//释放数组空间
return 0;
}
2.实验结果:
3.问题分析:
思路分析:程序中用到的多个函数:乘方函数、计算f(x)、f_(x)的函数、自定义的求根的主体的函数、主函数。乘方函数用于计算f(x)、f_(x),f(x)、f_(x) 函数的使用简化求根的函数。
六、第六题:将数字、小数点、正负号组成的字符串转换成相应的实数,例如:"-3.14159"变成-3.14159。函数原型如下: double myatof(char *num);要求编写主函数加以测试。
1.源程序代码:
#include<iostream>
double myatof(char *num);
using namespace std;
int main()
{
char num[20];
cout<<"请输入数值:";
cin>>num;
cout<<"转换结果为:"<<myatof(num)<<endl;
cout<<"检验:"<<myatof(num)<<"+1="<<myatof(num)+1<<endl;
return 0;
}
double myatof(char *a)
{
int i=0;
double x=0;
if(*(a+0)=='-'||*(a+0)=='+')//若首字符为‘-’或‘+’则跳过
i++;
while(*(a+i)!='\0'&&*(a+i)!='.')//对于整数部分逐位累加,直至遇到小数点或者数字结束
{
x=x*10+(*(a+i)-'0');
i++;
}
if(a[i]=='.')//对于小数部分进行累加
{
double s;//s用来反映数字所在位置是小数点后第几位,就用该数乘以的负几次方(s)
i++;//从小数点后的一位开始循环
for(s=0.1;a[i]!='\0';i++)
{
x=x+s*(a[i]-'0');
s=s/10;
}
}
if(a[0]=='-')//若为负数,则在上述计算基础上乘以-1得到最终值
x=-x;
return x;//返回x作为char c的对应的数值
}
2.实验结果:对整数、负数、小数等均进行检测:
(1)小数、负数:
(2)整数:
(正):
(负):
(3)0:
3.问题分析:
此题与第二题处理字符类似,需要处理开头正负号、小数点。
(七)第七题:在字符串T中查找子串S,若找到,返回子串的个数,若找不到返回0。要求编写主函数加以测试。
1.源程序代码:
#include<iostream>
using namespace std;
int find(char *a,char *b)
{
int i,s=0,x=strlen(a),y=strlen(b);
for(i=0;i<=x-y;i++)
{
if(b[0]==a[i])//找到首字符相同的位置
{
int j=0;
while(b[j]==a[i+j]&&i+j<x)//由该处开始逐次判断是否相同
j++;
if(j==y)
s++;
}
}
return s;
}
int main()
{
char a[101];
cout<<"请输入字符串:";
cin.get(a,100);
char b[31];
cout<<"请输入要查找的子串:";
cin>>b;
cout<<"字符串\n“"<<a<<"”\n中子串“"<<b<<"”的个数为:"<<find(a,b)<<endl;
return 0;
}
2.实验结果:
[注]:由于题目中没有说明,所以在这里当做可以共用来数,即:aaaa中查找aa时,第一二个a、第二三个a、第三四个a都认为是满足条件的,因而查出有三个而非两个。若要求不可重叠,只需循环完毕后从i=i+y+1再判断即可.
(1)其他符号:
(2)字母:
(3)此例说明可重叠:
(4)含空格:
3.问题分析:
不足之处:曾经尝试过让子串也输入“cin.get”但发现此时无法实现,当输入第一个字符串并回车后程序会跳过子串输入语句直接输出结果。不懂为何,如下:
八、第八题:编写一个程序,当输入一个整型数字以后,可以转换成相应的大写英文单词输出。如: 123 转换成 one hundred twenty three。
//第八题:编写一个程序,当输入一个整型数字以后,可以转换成相应的大写英文单词输出。如:转换成one hundred twenty three。
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int n;
cout<<"请输入整数:";
cin>>n;
if(n<0)
cout<<"error!";//对于输入小于,输出“error”
else
{
cout<<"转换结果是:\n";
if(n==0)//对于输入,输出zero
cout<<"zero";
else//输入正整数时,才进行以下操作
{
int m,x=n;
for(m=0;x>=1;m++)//求得所输入数n的位数m
{
x=x/10;
}
int a=m/3,b=m%3;
int *num=new int[3*(a+1)];
int j;
for(j=0,x=n;j<3*(a+1);j++)//分离出每一位数,存储于num[]中,定义其个数为的倍数,则不必考虑最高项的位置是i+1、i+2/还是i
{
num[j]=x%10;
x=x/10;
}//先将每一位上的数字分开分别储存下来。从个位向高位排列。
int i;
static char *u[]=//3i+2位和i位对应字符
{
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
};
static char *v[]=//3i+1位对应字符
{
"twenty",
"thirty",
"fourty",
"fifty",
"sixty",
"seventy",
"eighty",
"ninty"
};
static char *w[]=//单位,用于第、、位后
{
"thousand",
"million",
"billion",
};
static char *q[]=//当i+1位为时i+1和i位对应字符
{
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"ninteen",
};
for(i=a;i>=0;i--)//由高位到低位,每三位一循环
{
if(num[3*i+2]<=9&&num[3*i+2]>0)//3i+2位
cout<<*(u+num[3*i+2]-1)<<" hundred ";
if(num[3*i+1]==1)//3i+1位为时,根据i位输出ten、eleven……
cout<<*(q+num[3*i])<<" ";
else//若i+1位不是,可能是到或
{
if(num[3*i+1]!=0)//对于到则输出,则跳过
cout<<*(v+num[3*i+1]-2)<<" ";
if(num[3*i]!=0)
cout<<*(u+num[3*i]-1)<<" ";
}
if(i>0&&i<=3&&(num[3*i+1]!=0||num[3*i+2]!=0||num[3*i]!=0))//该循环个位上的数字不全为时,输出对应的单位
cout<<*(w+i-1)<<" ";
}
}
}
cout<<endl;
return 0;
}
2.实验结果:
(1)一位数:
(2)两位数:
(3)带正号:
(4)特定位置含0:
(5)0:
(6)位数为3的倍数:
(7)负数、非数字:
3.问题分析:应该注意以下几点:
(1)对于输入负数或者0或者不是整数的处理;
(2)每三位为一个环节,末尾输出应该是thousand、million还是billion还是不输出?要防止前面没有数字却输出一个单位如:
million three hundred twenty three
(3)当3i+1位为1时,要考虑到此时不是13——ten three,而是thirteen,因而需要对此分开处理。
展开阅读全文