实验八

来源:互联网 发布: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)分析与思考

结构体数组相当重要,可以实现多种数据类型的组合以实现现实世界数据处理的需要,对数据结构影响很大;调试过程中数据量太大时,可适当改小以节省时间。

 

原创粉丝点击