实验八
来源:互联网 发布:hp打印机软件 编辑:程序博客网 时间:2024/04/28 03:15
(1)实验内容
编写一个程序,根据用户输入的本金、存款年数、年利率计算到期本息,并扣除20%的个人所得税,输出实际利息。
编程要求:本金、年利率用float型变量存放,存款年数用整型变量存放。输出的金额数值只需两位小数。
(2)算法说明
先算应得利息t=本金a*(1+年利率p)存款年数n-本金a,再算实际利息s=应得利息t*0.8。
(3)程序清单
#include <stdio.h>
#include <math.h>
void main()
{
int n;
float a, p, s,t;
scanf("a=%f p=%f n=%d",&a,&p,&n);
t=a*pow((1+p),n)-a;
s=t*0.8;
printf("s=%.2f/n",s);
}
(4)测试数据与实验结果
原始数据:a=10000 p=0.01 n=5
相应的运行结果:s=408.08
必要的说明:本金a 年利率p 存款年数n 实际利息s 应得利息t
(5)分析与思考
刚开始调试时出现以下错误:
--------------------Configuration: 123 - Win32 Debug--------------------
Compiling...
123.cpp
C:/Program Files/Microsoft Visual Studio/MyProjects/123/123.cpp(8) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
C:/Program Files/Microsoft Visual Studio/MyProjects/123/123.cpp(9) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
Linking...
123.exe - 0 error(s), 2 warning(s)
经过改正后调试成功了:
--------------------Configuration: 123 - Win32 Debug--------------------
Compiling...
Skipping... (no relevant changes detected)
123.cpp
123.obj - 0 error(s), 0 warning(s)
原因至今仍没搞非常清楚,可能是连接是出了问题,编译器说可能丢失数据,在写实验内容和编程要求时发现输出的金额只需两位小数,源代码改成printf("s=%.2f/n",s);就OK了!
(1)实验内容
假定向国外邮寄包裹的收费如下:首先,包裹质量四舍五入到最近的15g的倍数,然后按表4.2收费。编写一个程序,根据用户输入的包裹质量和里程计算邮费。
编程要求:在程序中使用swith语句进行判断计算。
(2)算法说明
首先,包裹质量四舍五入到最近的15g的倍数,使用m=(m+7)/15*15;实现,然后当得到的包裹质量m等于60时,按表得用t1=s/1000;语句实现,当得到的包裹质量m超过75时,按表得用t2=s/1000*2;语句实现,最后,根据输入的包裹质量和里程计算相应的邮费y。
(3)程序清单
#include <stdio.h>
void main()
{
int m,s,t1,t2,y;
printf("请输入重量和里程:");
scanf("m=%d,s=%d",&m,&s);
m=(m+7)/15*15;
t1=s/1000;
t2=s/1000*2;
switch(m)
{
case 0:y=5; break;
case 15:y=5; break;
case 30:y=9;break;
case 45:y=12; break;
case 60:y=14+t1; break;
default:y=15+t2;break;
}
printf("应付邮资y=%d/n",y);
}
(4)测试数据与实验结果
原始数据:m=100,s=2000
相应的运行结果:应付邮资y=19
必要的说明:根据包裹质量m和里程s计算应付邮资y。
(5)分析与思考
同一个程序用if ;else if ;if ;语句和用swith语句都可以编写以解决问题,但else if语句常用于对多条件并列测试,从中取一的情形;而swith结构用于为单条件测试,从其多种结果中取一种的情形,应在适合的情况下选择合适的语句结构以提高程序的运行效率。
(1)实验内容
有A、B、C、D和E共5所学校。在一次检查评比中,已知E肯定不是第2或第3名,他们互相进行推测,A校有人说,E校肯定是第1名B校有人说,我校可能是第2名;C校有人说,A校最差;D校有人说,C校不是最好的;E校有人说,D校会获得第1名。结果只有第1名和第2名的学校的人猜对了。编写一个程序,求出这5所学校的名次。
编程要求:
为了防止不同的学校取得相同的名次,设立了一个数组x[i],x[i]为0(假)表示已有某校取得了第i名.
(2)算法说明
设a,b,c,d,e分别表示A,B,C,D,E这5所不同学校的名次(1到5),则有:
a+b+c+d+e=15 即e的名次为 e = 15-a-b-c-d;
根据题目给出的条件有:
1. “已知E校不是第2名或第3名”得到:
b0 = (e!=2)&&(e!=3);且b0为真
2. 由“他们互相推测,A校有人说,E校一定是第1名;B校有人说,我校可能是第2名;C校有人说,A校最差;D校有人说,C校不是最好的;E校有人说,D校会获得第1名。”得到:
m = (e==1)+(b==2)+(a==5)+(c!=1)+(d==1);且m的值一定为2
因为,结果是只有第1名和第2名的学校的人猜对,即以上5个条件中,只有两个条件的值为真(“1”),其余3个条件的值为假(“0”)。
3. 只有第1名和第2名的学校的人猜对,则以下都是假的:
b1 = (e==1)&&(a!=2);A校说对了,而A校又不是第1名和第2名(B校可能说对了)
b1 = (a==5)&&(c!=1)&&(c!=2);C校说对了,而C校又不是第1和第2名
b1 = (c!=1)&&(d!=1)&&(d!=2);D校说对了,而D校又不是第1和第2名
b1 = (d==1)&&(e!=2);E校说对了,而E校又不是第1 名和第2名
采用穷举法(4重循环语句),测试5所学校名次的各种情况,看哪种组合符合以上假设的条件,即为所求的解。为防止不同的学校取相同的名次,设立一个数组x[5],x[i]为0(假)表示已有某校取了第i名。
(3)程序清单
#include "stdio.h"
void main()
{ int a,b,c,d,e,i,m,b0,b1;
int x[6];
for(i=1;i<6;i++)x[i]=1;
for(a=1;a<=5;a++) //A校名次由1测到5
{ x[a]=0;
for(b=1;b<=5;b++) //B校名次由1测到5
if(x[b])
{ x[b]=0;
for(c=1;c<=5;c++) //C校名次由1测到5
if(x[c])
{ x[c]=0;
for(d=1;d<=5;d++) //D校名次由1测到5
if(x[d])
{ x[d]=0;
e = 15-a-b-c-d;
for(e=1;e<=5;e++) //e校名次由1测到5
if(x[e])
{
{
b0=(e!=2)&&(e!=3);
m=(e==1)+(b==2)+(a==5)+(c!=1)+(d==1);
b1=(e==1)&&(a!=2);
b1=b1+((a==5)&&(c!=1)&&(c!=2));
b1=b1+((c!=1)&&(d!=1)&&(d!=2));
b1=b1+((d==1)&&(e!=2));
}
if(b0==1 && m==2 && b1==0)
printf("A:%d B:%d C:%d D:%d E:%d/n",a,b,c,d,e);
}
x[d]=1;
}
x[c]=1;
}
x[b]=1;
}
x[a]=1;
}
}
(4)测试数据与实验结果
原始数据:无
相应的运行结果:A:5 B:2 C:1 D:3 E:4
必要的说明:无
(5)分析与思考
调试程序过程中出现多个答案,显然不符合实际情况,源代码由于
1:缺少对e的for循环:for(e=1;e<=5;e++) //e校名次由1测到5;
2:由于缺少条件表达式的整体深刻理解:
b1=b1+(a==5)&&(c!=1)&&(c!=2);
b1=b1+(c!=1)&&(d!=1)&&(d!=2);
b1=b1+(d==1)&&(e!=2);
整体缺少表达式值括号();
应改为:b1=b1+((a==5)&&(c!=1)&&(c!=2));
b1=b1+((c!=1)&&(d!=1)&&(d!=2));
b1=b1+((d==1)&&(e!=2));
最后调试成功了!
(1)实验内容
求2-100的所有素数,并把结果存放于一维数组a[100]中。其中,a[0]存放素数的个数,a[1],a[2],...存放素数,然后输出结果,要求每行输出5个素数。
编程要求:无
(2)算法说明
先判断是否为素数;
是则将i的值赋予数组s[k]。
(3)程序清单
#include <stdio.h>
#include <math.h>
#define N 100
void main()
{
int i,j,k,l,num,s[N],flag;
k=0;
for(i=2;i<=100;i++)
{
flag=1;
l=(int)sqrt(i);
for(j=2;j<=l;j++)
if(i%j==0)
{
flag=0;
break;
}
if(flag==1)
{
k++;
s[k]=i;
}
}
s[0]=k;
num=1;
for(k=0;k<=s[0];k++)
{
printf("s[%d]=%4d ,",k,s[k]);
if(num++%5==0)
printf("/n");
}
}
(4)测试数据与实验结果
原始数据:无
相应的运行结果:
s[0]= 25 ,s[1]= 2 ,s[2]= 3 ,s[3]= 5 ,s[4]= 7 ,
s[5]= 11 ,s[6]= 13 ,s[7]= 17 ,s[8]= 19 ,s[9]= 23 ,
s[10]= 29 ,s[11]= 31 ,s[12]= 37 ,s[13]= 41 ,s[14]= 43 ,
s[15]= 47 ,s[16]= 53 ,s[17]= 59 ,s[18]= 61 ,s[19]= 67 ,
s[20]= 71 ,s[21]= 73 ,s[22]= 79 ,s[23]= 83 ,s[24]= 89 ,
s[25]= 97 ,Press any key to continue
必要的说明:无
(5)分析与思考
调试过程中遇到了如下几个问题:
1.for循环后加if else语句是一个语句,
而for循环后加if 语句再加if 语句是两个语句。
2.数组s[k]=i;k赋初值为0与k赋初值为1的差别。
(1)实验内容
编写一个程序,将用科学计数法输入的一个数串(全部由数字或小数点字符组成的字符串)转换成对应的实数。
编程要求:
用字符数组存放用户输入的数串。
(2)算法说明
科学计数法是用e指数表示的一个实数,比如 23.57e3,程序要将其转换成0.01345。转换过程是:先跳过其前面的空格,考虑其符号,正数用sign=1表示,负数用sign=-1表示;然后考虑整数和小数部分,产生一个实数val;跳过e或E,对于正指数,val乘以相应个数的10,对于负数,val除以相应个数的10。最后返回val*sign 。
科学计数法的各种形式:
+3.57e3 -3.57e+3 23.57e-3 ...
可以用字符数组s[20]来存放从键盘输入的数字串,如图所示
+ 3 . 5 7 e 3 /0
注意:数字串"23.57"如何转换为实数 23.57;字符'2'转换为数字2的方法:'2' - '0'
(3)程序清单
#include <stdio.h>
void main()
{
char s[20];
int i,j, sign=1,signexp,e;
char c;
double val; //val为要求的结果
gets(s); //输入用科学计数法表示的数串,存入字符数组s中
i = 0;
while(s[i]==' ')i++ ; //跳过空格,即s[0]、s[1]
if (s[i]=='-') sign=-1;
//处理正负号,若s[i]为“+”,则sign=1; 否则sign=-1
i++;
val=e=0;
for (; (c = s[i]) != '.' && c != 'e' && c != 'E' && c != '/0'; i++)
val = val * 10.0 + (c - '0');//数字字符转换 如 23.57e3 , 则先转换23.57, 结果赋给 val
//val = 2*10+3+0.5+0.07 ( 23.57 )
//处理小数点前的整数部分
if(s[i]=='.') //处理小数点后部分
{
i++;
for (j = 0; (c = s[i]) != 'e' && c != 'E' && c != '/0'; j++, i++)
val = val * 10.0 + (c - '0');
while (j--)
val /= 10.0;
}
if(s[i]=='e' || s[i]=='E') //处理指数部分
{
i++;
if (s[i] == '-')
{
signexp = -1;
j++;
}
}
while (c = s[++i])
e = e * 10 + (c - '0');
if (signexp == -1)
for (; e; e--)
val /= 10.0;
else
for (; e; e--)
val *= 10.0;
val=val*sign;
printf("%f",val);//输出val
}
(4)测试数据与实验结果
原始数据:-23.57e-3
相应的运行结果:-0.023570Press any key to continue
必要的说明:无
(5)分析与思考
调试程序过程中if中的if (s[i]='-') sign=-1;中的=号有问题;
改为if (s[i]=='-') sign=-1;中的==号就可以了;
还有用printf查找错误所在处查到while (c = s[i]++)
e = e * 10 + (c - '0');
明显应改为while (c = s[++i])
e = e * 10 + (c - '0');
(1)实验内容:
编写一个程序,求解皇后问题:在n * n的方格上,放置n个皇后,要求每个皇后不同行、不同列、不同左右对角线。
编程要求:
(1) 皇后的个数n由用户输入,其值不能超过20
(2)采用递归方法。
(2)算法说明
由于每行有且只能有一个皇后,为简化求解过程,用整数数组q{N]表示求解结果,因为每列只能放一个皇后,q[i]的值表示第i个皇后所在的行号,即该皇后放在(q[i],i)的位置上。求解皇后的递归模型如下:
place(i,n): 若 i = n , 则n个皇后放置完毕,输出解(输出q数组元素)
place(k,n): 在第k列找一个合适位置i,放置一个皇后(即q[k] = i):place(k+1,n)
其中,place(k,n)表示前面的第1,...,k-1个皇后放置好后,现在用于放置k,...,n的皇后。递归算法如下:
void place(int k, int n) //第k个皇后放到第k列上
{
for(int i=1;i<=n;i++)
if(find(i,k))
{
q[k]=i; //即在该位置放置一个皇后
if(k==n)
print(k);
else
place(k+1,n);
}
}
检查在(i,k)位置上的皇后,是否与已放好的皇后(q[j],j)(1 <= j <= k-1)有冲突a 。
1.显然它们不同列,若有两个皇后处于同一行,则有q[j] == i;
2.若在同一对角线,则有 (i-q[j] == k-j),或者 (q[j]-i == j-k)
(3)程序清单
#include <stdio.h>
#include <stdlib.h>
#define N 20 //最多皇后个数
int q[N]; //存放各皇后所在行号
int count = 0; //存放解个数
void print(int n) //输出一个解 ,即输出q[1],q[2],...,q[n]
{
count++;
for(int i=1;i<=n;i++)
printf("%3d",q[i]);
putchar('/n');
}
int find(int i, int k) //测试第k列的第i行上能 否放置皇后
{ int j = 1;
while(j<k) //j = 1 -- k-1 是已放置了皇后的列,对应的行号为q[j]。
{
if(q[j]==i||abs(q[j]-i)==abs(j-k))
return 0;
j++;
}
return 1; //没有冲突则返回 1
}
void place(int k, int n) //第k个皇后放到第k列上
{
for(int i=1;i<=n;i++)
if(find(i,k))
{
q[k]=i; //即在该位置放置一个皇后
if(k==n)
print(k);
else
place(k+1,n);
}
}
void main( )
{
int n;
scanf("%d", &n);
place(1,n); //调用递归函数place(1,n)
}
(4)测试数据与实验结果
原始数据:6
相应的运行结果:6
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
5 3 1 6 4 2
Press any key to continue
必要的说明:无
(5)分析与思考
调试程序过程中用:
place(int k, int n)
{
if(k==n)
输出一个解;
else
for(int i=1;i<=n;i++)
if(第k列的第i行合适)
{
在该位置放置一个皇后即q[k]=i;
place(k+1,n);
}
}
将产生算法错误,改为:
void place(int k, int n) //第k个皇后放到第k列上
{
for(int i=1;i<=n;i++)
if(find(i,k))
{
q[k]=i; //即在该位置放置一个皇后
if(k==n)
print(k);
else
place(k+1,n);
}
}
程序调试成功!
1.程序源代码清单:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
char *word[]={"from","in","at","an","on"};
#define NUM (sizeof(word)/sizeof(char *))
#define LINES 256
#define MAXLEN 1000
void del_word(char *s, int n, int len)
/*del_word()函数删除s串中从第n+1个字符开始的长度为len个字符,
删除子串采用移动字符方法进行。*/
{
while (*(s+n)=*(s+n+len))
n++;
}
int getline(char *s, int len)
/*getline()函数用于接受用户输入的一行输入,直到按回键为止。
参数s是字符指针,指向存放输入字符串的缓冲区首址;
len是字符数组长度。*/
{
int c;
char *p=s;
while(--len>0 && ((c=getchar())!='/n'))
*s++=c;
*s='/0';
return(s-p) ;
}
void writelines(char *lineptr[],int nlines)
/*writeline()函数输出正文字符串。*/
{
int i;
printf("删除后的文本段:/n");
for(i=0;i<nlines;i++)
printf("%s/n",lineptr[i]);
}
int index(char s[],char t[])
/*del_word()函数删除s串中从第n+1个字符开始的长度为len个字符,
删除子串采用移动字符方法进行。*/
{
int i,j,k;
for(i=0;s[i]!='/0';i++ )
{
for(j=i,k=0;t[k]!='/0' && s[j]==t[k];j++,k++) ;
if(t[k]=='/0')return i;
}
return -1;
}
int readlines(char *lineptr[],int maxlines)
/*index()函数的功能 是在第一个参数串s中查找是否包含第二个参数串t。*/
{
int len,nlines=0;
char *p,line[MAXLEN];
printf("输入一段文本:/n");
while((len=getline(line,MAXLEN))>0)
if(nlines>maxlines)
return -1;
else if((p=(char *)malloc(len+1))==NULL)
return -1;
else
{
line[len]='/0';
strcpy(p,line);
lineptr[nlines++]=p;
}
return nlines;
}
void main()
{
char *lineptr[100],*p;
int i,j,k,nlines;
if((nlines=readlines(lineptr,100))>0)
for(i=0;i<NUM;i++)
{
j=0;
while(j<nlines)
{
p=lineptr[j++];
while((k=index(p,word[i]))>=0)
del_word(p,k,strlen(word[i]));
}
}
writelines(lineptr,nlines);
}
2.程序调试心得体会:
采用模块化设计方法,将各子功能设计成函数,
可以先将各子函数先用主函数调试成功后,
再将各子函数连接成完整的程序源代码,
运用模块化程序设计的思想对于大的工程项目有很大益处,
并且是已成为一种行业规则,练习函数的实现将有助于未来的挑战和机遇。
实验10 结构体
(1)实验内容:
某班有50个学生,每个学生包含的信息为学号、姓名及语文、数学、英语成绩。
编程要求:
1. 求每个学生的平均成绩
2. 求每门课程的平均成绩
(2)算法说明:定义结构体数组变量student[51]存放个学生学号、姓名及语文、数学、英语成绩,其中student[50]存放全班各科课程总成绩;通过void xshavg(struct stu student[],int n) //每个学生的平均成绩函数和 void kchavg(struct stu student[],int n) //每门课程平均成绩函数,主函数中调用实现编程要求中的两个实验目的。
(3)程序源代码清单:
#include <stdio.h>
struct stu
{
char name[10]; //姓名
int no; //学号
int score[3]; //语数英三科成绩
int avg; //每个学生的平均成绩
}student[51];
void xshavg(struct stu student[],int n) //每个学生的平均成绩函数
{
for(int i=0;i<n;i++)
{
student[i].avg=0;
for(int j=0;j<3;j++)
student[i].avg+=student[i].score[j];
student[i].avg/=3;
}
}
void kchavg(struct stu student[],int n) //每门课程平均成绩函数
{
for(int j=0;j<3;j++)
{
for(int i=0;i<n;i++)
student[50].score[j]+=student[i].score[j];
student[50].score[j]/=n;
}
}
void main()
{
int n=50;
printf("请输入 姓名 学号 语文成绩 数学成绩 英语成绩/n");
for(int i=0;i<n;i++)
{
printf("第%d个学生:",i+1);
scanf("%s%d%d%d%d",&student[i].name,&student[i].no,&student[i].score[0],&student[i].score[1],&student[i].score[2]);
}
xshavg(student,n);
kchavg(student,n);
printf("姓名 学号 三科平均成绩/n");
for(i=0;i<n;i++)
{
printf("%s%d%d/n",student[i].name,student[i].no,student[i].avg);
}
printf("语文平均成绩 数学平均成绩 英语平均成绩/n");
printf("%d%d%d/n",student[50].score[0],student[50].score[1],student[50].score[2]);
}
(4)测试数据与实验结果:
数据量太大将50个学生改为2个:
输入:
a 100 50 60 70
b 101 60 70 80
输出:
a 100 60
b 101 70
55 65 75
必要的说明:无
(5)分析与思考
结构体数组相当重要,可以实现多种数据类型的组合以实现现实世界数据处理的需要,对数据结构影响很大;调试过程中数据量太大时,可适当改小以节省时间。