一、第八章第一次作业需要注意的问题:
(1)主函数和子函数的N-S图都要画,且要分开画
(2)子函数的N-S图外要给出完整的具体的函数头,返回值类型、参数类型及参数名等都不能省略。调用处只需且必须给出具体的完整的语句,要传递的实参不能省略,且不能要类型说明符。此外要注意参数个数。
如求一元二次方程的根,当deta<0时,若用如下方法则需要三个参数,因a、b和deta的值在子函数都用到,三者都需要从调用处传递过来。此时,对应函数头为void smaller_than_zero(float a,float b,float deta),主函数中发生调用的位置写“smaller_than_zero(a,b,deta)”
若用如下方法则只需两个参数,因子函数中只有a和b需要从调用处传递过来,此时,对应函数头为void smaller_than_zero(float a,float b),主函数中发生调用的位置写“smaller_than_zero(a,b)”
(3)尽量避免用全局变量,确实需要用时,要在主函数N-S图的开始说明哪些是全局变量。
(4)变量名与函数名不能相同,且都不能与系统的保留字(如int long for goto if等)重复
(5)子函数头中已经定义的形参不能在子函数体内重新定义,且形参的值由调用语句中的对应实参(按顺序对应)传递过来,通常不需重新赋初值。
(6)主函数或者子函数两者至少要有一个有输出,否则,整个程序无输出!
(7)函数功能划分要合理,各自相互独立。
(8)8.16输入一个十六进制串,求对应的十进制并输出,可参考如下答案:
/*主函数将十六进制串输入字符数组s,之后判断str是否合法,合法则调用函数求对应十进制数并输出*/
注意:当子函数有返回值时,调用语句处要把该返回值接收并利用起来,如flag=judge(str[i]),否则,如只写judge(str[i])则此次函数调用毫无意义,因返回值未被利用;有时不必如此,如子函数返回值类型为空时,此时调用语句可直接写trans(str),如输出欢迎界面的子函数,只需输出一个界面即可,无需返回值;再如数组名作函数参数时,因主调函数和被调函数中的数组是同一个数组,在子函数中对数组加以改变,原函数中的数组也相应改变,故此时无返回原数组也发生了改变!
(9)求最长单词并输出一题提示:设一个标记变量flag,用flag=0或1代表前一个字符是否空格,当且仅当前一个字符是空格,且当且字符是字母代表单词开始。当前一个字符不是字母,而当且字符不是字母是单词结束。
第二次作业说明递归法N-S图画法,如求n!对应的N-S图如下:
主函数:输入n,调用递归函数f求n!:
/*递归法求阶乘子函数*/
int f(int m)
或二、
说明:数组元素作参数是将数组元素的值传递到形参对应的内存空间中,之后操作是对形参对应空间的数值进行的,故原来的数组内容不变;而数组名作参数是将数组名的值(即数组首地址)传递到形参对应的单元中,从而形参的值就是原数组的首地址,之后的操作是根据形参的值即原数组的首地址进行的,从而原数组的内容改变。
exchange(a[0],a[1]) ---> exchang(int i,int j){float tmp;tmp=i;i=j;j=tmp}/*互换的是形参i与j*/
excange(a) ---> excange(int b[]){float tmp;tmp=b[0];b[1]=tmp;}/*b=a均为原数组首址*/
8.13’、递推法求勒让德多项式值
#include<stdio.h>
void main()
{
int n,i;
float x,y,y1,y2;
printf(“input x & n\n”);
scanf(“%f %d”,&f,&n) /*注意数据类型与格式控制符一致,比如读入实数用%f*/
if(n= =0)y=1;
else if(n= =1)y=x;
else
{
y1=1;y2=x; /*应y1=x;y2=1;*/
for(i=2;i<=n;i++)
{
y=((2*n-1)*x-y1-(n-1)*y2)/n; /*应y=((2*i-1)*x-y1-(i-1)*y2)/i*/
y1=y2;
y2=y;
}
}
printf(“the result is %f\n”,y);
}
/*int n;float x;int p[n];for(i=2;i<n;i++)p[i]=p[i-1]+p[i-2]*x;因数组名大小必须为常数,故错误*/
/* int n;float x;int p(n,x); for(i=2;i<n;i++)p(n,x)=p(n-1,x)+p(n-2,x)*x;因int p(n,x)既非定义变量(不符合变量命名规则),也非定义函数(函数的形参应指定类型),且赋值语句左侧既非变量,也非数组名,故严重错误*/
递归法自己想!可参考下例类似得到。
8.17递归法将一个整数以字符形式输出。如483,先用putchar()输出字符4,后putchar(‘8’),最后putchar(‘3’)
递归求解思路如下,构造递归函数void convert(int n);用以将n转化为字符串输出:
当n为个位数即n/10==0时直接输出该数字对应的字符即可
if(n/10==0)
putchar(n+'0'); /*如putchar(8)输出ASCII码为8的字符,而putchar(‘8’)输出数字字符8,显然8的ASCII码值等于0的ASCII码加8*/
降阶:假设convert(n/10)能正确将n/10转化并输出,则对于n分两步:
先用convert(n/10)将n/10转化并输出,之后输出n%10对应的字符。
#include<stdio.h>
void main()
{
int n;
void convert(int n); /*函数声明,此时函数返回值类型和形参类型不可省,但形参变量名可省*/
printf(“input n:\n”);
scanf(“%d”,&n);
convert(n); /*函数调用,此时不可有函数返回值类型和形参类型,写上实参即可*/
}
void convert(int n) /*函数定义,此时函数返回值类型、形参类型和形参变量名均不可省*/
{
int i;
if(n/10==0)
putchar(n%10+'0'); /*putchar(8)输出ASCII码为8的字符,而putchar(‘8’)输出数字字符8,显然8的ASCII码值等于0的ASCII码加8*/
else
{
convert(n/10);
putchar(n%10+'0');
}
输入123,程序执行过程如下,注意箭头方向与缩进意义
convert(123) /*第一次调用函数时形参为123*/
-->n=123;i=12;convert(12); /*第二次调用时形参为12,返回后执行putchar(123%10+’0’)*/
-->n=12; i=1; convert(1); /*第三次调用时形参为1,返回后执行putchar(12%10+’0’)*/
-->n=1;i=0;putchar(1%10+'0'); /*第三次调用结束*/
putchar(12%10+'0');<-- /*返回执行putchar(12%10+’0’),第二次调用结束*/
putchar(123%10+'0');<-- /*返回执行putchar(123%10+’0’)第一次调用结束,返回主函数*/
思考二:Gauss消去法化矩阵为阶梯形/*注意模块的划分及函数参数的确定*/
#define ROWNUM 4 /*代表矩阵行数,注意见名知意*/
#define COLNUM 4 /*代表矩阵列数*/
#include<stdio.h>
/*输入矩阵子函数*/
void inputmatrix(float a[][COLNUM]) /*只有第一维大小可省略,形参名可改*/
{
int i,j;
printf("input the matrix:\n");
for(i=0;i<ROWNUM;i++)
for(j=0;j<COLNUM;j++)
scanf("%f",&a[i][j]); /*float型变量在输入输出时不可用%d,int型不可用%f*/
}
/*输出矩阵子函数*/
void outputmatrix(float a[][COLNUM])
{
int i,j;
printf("the matrix is:\n");
for(i=0;i<ROWNUM;i++)
{
for(j=0;j<COLNUM;j++)printf("%5.2f ",a[i][j]);
printf("\n");
}
}
/*寻找非零行函数,若a[i][i]为0,则找其正下方非零元素所在行,找不到返回-1,否则返回行号*/
int findnzero(float a[][COLNUM],int i) /*函数起名也要见名知义*/
{
int j,result=-1;
for(j=i+1;j<ROWNUM;j++)
if(a[j][i]!=0){result=j;break;}
return(result);
}
/*两行互换子函数*/
void exchange(float a[][COLNUM],int i,int j)
{
int k;float tmp;
for(k=0;k<COLNUM;k++){tmp=a[i][k];a[i][k]=a[j][k];a[j][k]=tmp;}
}
/*消元子函数,i行加上j行的k倍,结果放回i行*/
addrow(float a[][COLNUM],int i,int j,float k) /*注意形参的类型*/
{int tmp;
for(tmp=0;tmp<COLNUM;tmp++)a[i][tmp]=a[i][tmp]+k*a[j][tmp];
}
/*Gauss消去法化阶梯形*/
int gauss(float a[][COLNUM])
{
int i,j,flag,sign=1;
for(i=0;i<ROWNUM-1;i++)
{
if(a[i][i]= =0)
{
flag=findnzero(a,i);
if(flag= =-1)continue; /*若当前列剩余元素均零则重新开始循环,处理下一行*/
else {exchange(a,i,flag);sign*=-1;}
}
for(j=i+1;j<ROWNUM;j++)addrow(a,j,i,-a[j][i]/a[i][i]); /*逐行进行消元*/
}
return(sign);
}
void main()
{
float a[ROWNUM][COLNUM];
inputmatrix(a);
gauss(a);
outputmatrix(a);
}
(1)主函数和子函数的N-S图都要画,且要分开画
(2)子函数的N-S图外要给出完整的具体的函数头,返回值类型、参数类型及参数名等都不能省略。调用处只需且必须给出具体的完整的语句,要传递的实参不能省略,且不能要类型说明符。此外要注意参数个数。
如求一元二次方程的根,当deta<0时,若用如下方法则需要三个参数,因a、b和deta的值在子函数都用到,三者都需要从调用处传递过来。此时,对应函数头为void smaller_than_zero(float a,float b,float deta),主函数中发生调用的位置写“smaller_than_zero(a,b,deta)”
若用如下方法则只需两个参数,因子函数中只有a和b需要从调用处传递过来,此时,对应函数头为void smaller_than_zero(float a,float b),主函数中发生调用的位置写“smaller_than_zero(a,b)”
(3)尽量避免用全局变量,确实需要用时,要在主函数N-S图的开始说明哪些是全局变量。
(4)变量名与函数名不能相同,且都不能与系统的保留字(如int long for goto if等)重复
(5)子函数头中已经定义的形参不能在子函数体内重新定义,且形参的值由调用语句中的对应实参(按顺序对应)传递过来,通常不需重新赋初值。
(6)主函数或者子函数两者至少要有一个有输出,否则,整个程序无输出!
(7)函数功能划分要合理,各自相互独立。
(8)8.16输入一个十六进制串,求对应的十进制并输出,可参考如下答案:
/*主函数将十六进制串输入字符数组s,之后判断str是否合法,合法则调用函数求对应十进制数并输出*/
注意:当子函数有返回值时,调用语句处要把该返回值接收并利用起来,如flag=judge(str[i]),否则,如只写judge(str[i])则此次函数调用毫无意义,因返回值未被利用;有时不必如此,如子函数返回值类型为空时,此时调用语句可直接写trans(str),如输出欢迎界面的子函数,只需输出一个界面即可,无需返回值;再如数组名作函数参数时,因主调函数和被调函数中的数组是同一个数组,在子函数中对数组加以改变,原函数中的数组也相应改变,故此时无返回原数组也发生了改变!
(9)求最长单词并输出一题提示:设一个标记变量flag,用flag=0或1代表前一个字符是否空格,当且仅当前一个字符是空格,且当且字符是字母代表单词开始。当前一个字符不是字母,而当且字符不是字母是单词结束。
第二次作业说明递归法N-S图画法,如求n!对应的N-S图如下:
主函数:输入n,调用递归函数f求n!:
/*递归法求阶乘子函数*/
int f(int m)
或二、
说明:数组元素作参数是将数组元素的值传递到形参对应的内存空间中,之后操作是对形参对应空间的数值进行的,故原来的数组内容不变;而数组名作参数是将数组名的值(即数组首地址)传递到形参对应的单元中,从而形参的值就是原数组的首地址,之后的操作是根据形参的值即原数组的首地址进行的,从而原数组的内容改变。
exchange(a[0],a[1]) ---> exchang(int i,int j){float tmp;tmp=i;i=j;j=tmp}/*互换的是形参i与j*/
excange(a) ---> excange(int b[]){float tmp;tmp=b[0];b[1]=tmp;}/*b=a均为原数组首址*/
8.13’、递推法求勒让德多项式值
#include<stdio.h>
void main()
{
int n,i;
float x,y,y1,y2;
printf(“input x & n\n”);
scanf(“%f %d”,&f,&n) /*注意数据类型与格式控制符一致,比如读入实数用%f*/
if(n= =0)y=1;
else if(n= =1)y=x;
else
{
y1=1;y2=x; /*应y1=x;y2=1;*/
for(i=2;i<=n;i++)
{
y=((2*n-1)*x-y1-(n-1)*y2)/n; /*应y=((2*i-1)*x-y1-(i-1)*y2)/i*/
y1=y2;
y2=y;
}
}
printf(“the result is %f\n”,y);
}
/*int n;float x;int p[n];for(i=2;i<n;i++)p[i]=p[i-1]+p[i-2]*x;因数组名大小必须为常数,故错误*/
/* int n;float x;int p(n,x); for(i=2;i<n;i++)p(n,x)=p(n-1,x)+p(n-2,x)*x;因int p(n,x)既非定义变量(不符合变量命名规则),也非定义函数(函数的形参应指定类型),且赋值语句左侧既非变量,也非数组名,故严重错误*/
递归法自己想!可参考下例类似得到。
8.17递归法将一个整数以字符形式输出。如483,先用putchar()输出字符4,后putchar(‘8’),最后putchar(‘3’)
递归求解思路如下,构造递归函数void convert(int n);用以将n转化为字符串输出:
当n为个位数即n/10==0时直接输出该数字对应的字符即可
if(n/10==0)
putchar(n+'0'); /*如putchar(8)输出ASCII码为8的字符,而putchar(‘8’)输出数字字符8,显然8的ASCII码值等于0的ASCII码加8*/
降阶:假设convert(n/10)能正确将n/10转化并输出,则对于n分两步:
先用convert(n/10)将n/10转化并输出,之后输出n%10对应的字符。
#include<stdio.h>
void main()
{
int n;
void convert(int n); /*函数声明,此时函数返回值类型和形参类型不可省,但形参变量名可省*/
printf(“input n:\n”);
scanf(“%d”,&n);
convert(n); /*函数调用,此时不可有函数返回值类型和形参类型,写上实参即可*/
}
void convert(int n) /*函数定义,此时函数返回值类型、形参类型和形参变量名均不可省*/
{
int i;
if(n/10==0)
putchar(n%10+'0'); /*putchar(8)输出ASCII码为8的字符,而putchar(‘8’)输出数字字符8,显然8的ASCII码值等于0的ASCII码加8*/
else
{
convert(n/10);
putchar(n%10+'0');
}
输入123,程序执行过程如下,注意箭头方向与缩进意义
convert(123) /*第一次调用函数时形参为123*/
-->n=123;i=12;convert(12); /*第二次调用时形参为12,返回后执行putchar(123%10+’0’)*/
-->n=12; i=1; convert(1); /*第三次调用时形参为1,返回后执行putchar(12%10+’0’)*/
-->n=1;i=0;putchar(1%10+'0'); /*第三次调用结束*/
putchar(12%10+'0');<-- /*返回执行putchar(12%10+’0’),第二次调用结束*/
putchar(123%10+'0');<-- /*返回执行putchar(123%10+’0’)第一次调用结束,返回主函数*/
思考二:Gauss消去法化矩阵为阶梯形/*注意模块的划分及函数参数的确定*/
#define ROWNUM 4 /*代表矩阵行数,注意见名知意*/
#define COLNUM 4 /*代表矩阵列数*/
#include<stdio.h>
/*输入矩阵子函数*/
void inputmatrix(float a[][COLNUM]) /*只有第一维大小可省略,形参名可改*/
{
int i,j;
printf("input the matrix:\n");
for(i=0;i<ROWNUM;i++)
for(j=0;j<COLNUM;j++)
scanf("%f",&a[i][j]); /*float型变量在输入输出时不可用%d,int型不可用%f*/
}
/*输出矩阵子函数*/
void outputmatrix(float a[][COLNUM])
{
int i,j;
printf("the matrix is:\n");
for(i=0;i<ROWNUM;i++)
{
for(j=0;j<COLNUM;j++)printf("%5.2f ",a[i][j]);
printf("\n");
}
}
/*寻找非零行函数,若a[i][i]为0,则找其正下方非零元素所在行,找不到返回-1,否则返回行号*/
int findnzero(float a[][COLNUM],int i) /*函数起名也要见名知义*/
{
int j,result=-1;
for(j=i+1;j<ROWNUM;j++)
if(a[j][i]!=0){result=j;break;}
return(result);
}
/*两行互换子函数*/
void exchange(float a[][COLNUM],int i,int j)
{
int k;float tmp;
for(k=0;k<COLNUM;k++){tmp=a[i][k];a[i][k]=a[j][k];a[j][k]=tmp;}
}
/*消元子函数,i行加上j行的k倍,结果放回i行*/
addrow(float a[][COLNUM],int i,int j,float k) /*注意形参的类型*/
{int tmp;
for(tmp=0;tmp<COLNUM;tmp++)a[i][tmp]=a[i][tmp]+k*a[j][tmp];
}
/*Gauss消去法化阶梯形*/
int gauss(float a[][COLNUM])
{
int i,j,flag,sign=1;
for(i=0;i<ROWNUM-1;i++)
{
if(a[i][i]= =0)
{
flag=findnzero(a,i);
if(flag= =-1)continue; /*若当前列剩余元素均零则重新开始循环,处理下一行*/
else {exchange(a,i,flag);sign*=-1;}
}
for(j=i+1;j<ROWNUM;j++)addrow(a,j,i,-a[j][i]/a[i][i]); /*逐行进行消元*/
}
return(sign);
}
void main()
{
float a[ROWNUM][COLNUM];
inputmatrix(a);
gauss(a);
outputmatrix(a);
}