C语言典例解析文档格式.docx
《C语言典例解析文档格式.docx》由会员分享,可在线阅读,更多相关《C语言典例解析文档格式.docx(46页珍藏版)》请在冰豆网上搜索。
同时,当结束循环后指针pi与pj所指的值不相同时,也表示字符串s不是回文字符串。
因此,*pi!
=*pj也是
(2)空的等价答案
***************
2.字符串分割
函数f(char*str,chardel)的功能是:
将非空字符串str分割成若干个子字符串并输出,del表示分割时的标志字符。
例如若str的值为“33123333435”,del的值为‘3’,调用此函数后,将输出三个子字符串,分别为“12”、“4”和“5”。
〔程序〕
voidf(char*str,chardel)
{inti,j,len;
len=strlen(str);
i=0;
while (i<
len){
while (__
(1)__) i++;
/*忽略连续的标志字符*/
/*寻找从str[i]开始直到标志字符出现的一个子字符串*/
j=i+1;
while(str[i]!
=del&
str[j]!
=’\0’)j++;
__
(2)__="
"
;
/*给找到的字符序列置字符串结束标志*/
printf("
%s"
&
str[i]);
__(3)__;
}
}
(1)str[i]==del&
i
(2)str[j]
(3)i=j+1
(1)空所在的循环语句的功能是忽略连续的标志字符del。
因此,当前位置i的字符若为标志字符del并且字符串未结束时,需继续往后查找。
因此,
(1)空的答案为str[i]==del&
i
****************
3.字符串中寻找字符
函数char*strrchr(char*s,charch)的功能是在字符串s中寻找字符ch若ch出现在字符串s中,则返回最后一次出现时的位置,否则返回NULL。
char*strrchr(char*s,charch)
{
char*p;
p=__
(1)__;
/*p指向字符串s的结束标志*/
while(--p>
=s)
if(__
(2)__)returnp;
returnNULL;
(1)s+strlen(s)
(2)*p==ch
由于函数strrchr(char*s,charch)的功能是实现在字符串s中寻找字符ch最后一次出现时的位置。
为了实现这一功能,只需要从字符串最后一个字符开始往前找,只要找到字符,该字符就是在字符串中最后一次出现的字符。
循环语句while(--p>
=s)就实现从后往前查找的功能。
因此,需在执行该循环语句之前,必须使指针p指向该字符串的最后一个字符。
而
(1)空所在的语句正是实现此功能。
由于循环语句中的条件为--p>
=s(即先往前移指针p,再与指针s比较),因此,
(1)空的答案为s+strlen(s),而不是s+strlen(s)-1。
由于函数功能是返回指向最后一次出现位置的字符指针,因此,在从后往前找的过程中,只要p所指的字符与字符ch相等,返回值就是p。
即
(2)空的答案为*p==ch
4.字符串连接
函数strcat(char*s1,char*s2)是将字符串s2连接在字符串s1之后,构成一个首指针为s1的字符串。
voidstrcat(char*s1,char*s2)
{while(*s1!
=’’)
____
(1)____;
for(;
___
(2)___;
s1++,s2++);
(1)s1++或++s1
(2)*s1=*s2
函数strcat(char*s1,char*s2)功能是将字符串s2连接在字符串s1之后。
要将字符串s2连接在字符串s1之后,首先需找到第一个字符串的结束位置’’字符。
其次,再将第二个字符串中的字符逐个复制到第一个字符串的后面。
因此
(1)空的答案为s1++或++s1。
函数中的第一个循环实现了指针s1指向第一个字符串的结束字符’’。
因此,第二个循环应是实现将第二个字符串中的字符逐个复制到第一个字符串的后面。
由于第二个循环语句还没有将第二个字符串中的字符复制到第一个字符串后的语句,因此,
(2)空中应包括*s1=*s2。
同时,
(2)空是for循环的条件,由于C语言中,非0值表示条件成立,0值表示条件不成立。
当s2指向第二个字符串结束时,*s2的值为0。
若*s2的值为0,则表达式*s1=*s2的值也为0。
即当s2指向第二个字符串结束时,第二个循环也结束。
因此,
(2)空的答案为*s1=*s2。
**************
5.比较两个字符串的大小
函数strcmp()是比较两个字符串s和t的大小。
若s<
t函数返回负数;
若s=t函数返回0;
若s>
t,函数返回正数。
〔函数〕
intstrcmp(char*s,char*t)
{while(*s&
*t&
___
(1)___)
{s++;
t++;
return___
(2)___;
(1)*s==*t
(2)*s-*t
而比较字符串的规则是从字符串开始扫描两个字符串,当两个字符串都未结束并且对应字符相同时,则需继续比较。
因此,
(1)空的答案为*s==*t。
(2)空则是函数返回值,由于当st时函数返回正数。
因此,
(2)空答案为*s-*t。
*******************
6.计算个人所得税
本程序用于计算某公司每个职工应缴纳的个人所得税额和全体职工缴纳的个人所得税总额。
职工的当月收入(工资或薪金)通过键盘输入,每次输入一个职工的工号和工资(或薪金)。
由于该公司的工资或薪金是不定时发放的,所以输入过程中每个职工的收入会出现多次输入,整个输入以工号小于等于0结束。
假设个人所得税法规定;
个人收入所得,按月计税,以每月收入总额减除免税金额800元后的余额作为该月的月应纳税所得额,适用税率如下表所示。
级数月应纳税所得额适用税率(%)
1不超过500元的部分5
2501元~2000元的部分10
32001元~5000元的部分15
45001元~20000元的部分20
520001元~40000元的部分25
640001元~60000元的部分30
7 60001元~80000元的部分35
8 80001元~100000元的部分40
9 超过100000元的部分45
上表表明,个人收入所得税是按照超额累进的税率来征收的。
设一个人的月应纳税所得额为K(元),用下面的公式计算其应缴纳的个人所得税额S(元):
若0<
K≤500,则S=K×
5%;
若500<
K≤2000,则S=500×
5%+(K-500)×
10%:
若2000<
K≤5000,则S=500×
5%+1500×
10%+(K-2000)×
15%:
若5000<
K≤20000,则S=500×
10%+3000×
15%+(K-5000)×
20%:
例如,某人某月工资总额为4100元,减去800元后,应纳税所得额为3300元,其应缴纳的个人所得税额为500*5%+1500*10%+1300*15%=370元。
#include<
stdio.h>
#defineMaxNum50
#defineBASE800 /*免税金额基数*/
intpaylevel[]={0,500,2000,5000,20000,40000,60000,80000,100000,1000001};
inttaxPrate[]={5,10,15,20,25,30,35,40,45};
/*税率表*/
typedefstruct{
intld;
/*职工的工号*/.
longSalary;
/*职工的工资*/
}Info;
/*查找工号为Id的职工在数组employee中的下标,返回值为0表示没有*/
intfind(intId,Infoemployee[],intm){
intj;
employee[0].Id=Id;
for(j=m;
___
(1)___;
j--);
returnj;
voidmain(void)
{Infoemployee[MaxNum+1];
longWage;
doublesum=0,K,S;
inti,j,N=0,Code;
scanf("
%d%ld"
&
Code,&
Wage);
/*读入职工号、工资或薪金*/
while(Code>
0) {
i=find(Code,employee,N);
if(i>
0)employee[i].Salary+=Wage;
else{ ___
(2)___;
employee[N].Id=Code;
employee[N].Salary=Wage;
}
scanf("
%d%ld"
for (i=1;
i<
=N;
i++){
K=___(3)___;
/*计算月应纳税所得额*/
S=0;
;
/*月应纳税额赋初值*/
if(K>
0){
for(j=1;
j<
=9;
j++)
if(____(4)____) /*月应纳税所得额超过第j级*/
S=S+(paylevel[j]-paylevel[j-1])*taxPrate[j-1]/100;
else{ S=S+(___(5)___)*taxPrate[j-1]/100;
break;
}
printf("
职工%d应缴纳的个人所得税额:
%10.21f"
employee[i].Id,S);
sum+=S;
全体职工个人所得税总额:
%10.2lf"
sum);
(1)employee[j].Id!
=Id
(2)N++
(3)employee[i].Salary-BASE
(4)k>
paylevel[j]
(5)K-paylevel[j-1]
函数find(intId,Infoemployee[],intm)实现了查找工号为Id的职工在数组employee中的下标,返回值为0表示没有。
由于在函数中,将待查找的工号Id赋给employee[0].Id,因此,在从后往前循环查找时,由于在搜索到位置0时总能找到该工号的,因此,不需要再考虑找不到的情况。
因此,在当前工号与待查找的工号不相等时需继续查找,即
(1)空的答案为employee[j].Id!
=Id。
程序中,while(Code>
0){...}循环读入所有员工不定时发放的工资,并计算出每位员工的月工资。
(2)空所在语句为处理读入的职工号是一个以前还没有出现过的情况。
此时的处理应该需在employee中新增一个元素,存放该职工的工资与职工号,同时使当前的职工总数增1。
由于在程序中,用变量N存放在employee中当前的职工总数,因此,新增一个职工,需将变量N的值增1。
即
(2)空的答案为N++。
接下去所在的循环for (i=1;
i++){......}实现了计算每位职工的个人所得税额及全体职工的个人所得税总额。
(3)所在的语句实现了计算第i位职工的月应纳税所得额。
根据试题的要求,月应纳税所得额为该职工每月收入总额减去免税金额的余额。
因此,(3)的答案为employee[i].Salary-BASE。
(4)空与(5)空所在的循环语句计算了第i位职工的个人所得税。
在本程序中,个所得税计算采用分级计算出每一级别的纳税额,并累加每一级别的纳税额所得。
(4)为判断该职工的月应纳税所得额是否超过第j级的条件,而第j级的月应纳税的所得额的上限存于数组元素paylevel[j]。
因此,(4)空的答案为k>
paylevel[j]。
根据题目的说明,当超过j级时,该级需交纳的个人所得税为该级的上限减去该级的下限再乘上该级的适用税率。
否则,该级需交纳的个人所得税为第i位职工的工资减去该级的下限再乘上该级的适用税率。
(5)空所在的语句为第i位职工的级数刚好处于j级时的情况,因此,(5)空的答案为K-paylevel[j-1]。
***********************
7.矩阵中求最大数
在n行n列的矩阵中,每行都有最大数,本程序是求这n行最大数中的最小数。
#include<
#defineN100
inta[N][N];
voidmain()
{introw,col,max,min,n;
/*输入合法n(<
100),和输入n*n个整数到数组a的代码略*/
for(row=0;
row<
n;
row++)
{
for(max=a[row][0],col=1;
col<
n;
col++)
if(___
(1)___)max=a[row][col];
if(___
(2)___)min=max;
elseif(___(3)___)min=max;
printf("
Theminofmaxnumbersif%d"
min);
(1)a[row][col]>
max
(2)row==0
(3)max
本程序实现的功能是在已知n行n列的矩阵中,找出每行的最大数,并从每行找出的最大数中找出最小的一个数。
为此,函数用循环语句for(row=0;
rowmax。
当考查完了row行的所有元素后,max中存放的是该行的最大值。
为了从每行找出的最大数中再找出最小的一个数,则还需要考虑第row行的最大元素max是否比已有的最大值中的最小值min要小。
若第row行的最大元素max比已有的最大值中的最小值min要小,则需用max值来更新已有的最小值min。
同时,还需要考虑边界问题,即第0行的情况。
由于当找出第0行的最大值max时,min还没有初始值,因此,max与min不能比较。
由于此时只有一个数,可将max赋给min,即只有一个数时,该数就是最小值。
因此,
(2)空的答案为row==0,(3)空答案为max
8.长整数处理
如有k位的长整数m用数组a[]存储:
m=a[k]*10k-1+a[k-1]*10k-2+…+a[2]*101+a[1]*100
并用a[0]存储长整数m的位数,即a[0]=k。
通常,存储长整数数组的每个元素只存储长整数的一位数字。
长整数运算时,产生的中间结果的某位数字可能会大于9。
这时,就应调用函数formal(int*a)将它规整,使数组的每个元素只存储长整数的一位数字。
函数combine(a,b,c)是计算两个整数的组合数。
由于计算结果可能超出longint的表示范围,因此采用了上面的方法存储计算结果。
设整数a和b(a>
b),它们的组合c(a,b)=a!
/((a-b)!
*b!
)。
计算a和b的组合可采用以下方法:
a!
/(a-b)!
/b!
=a*(a-1)*(a-2)*…*(a-b+1)/b!
=u1*u2*…*uh/(d1*d2*…*dh)
其中u1=a,u2=a-1,…,uh=a-b+1;
d1=1,d2=2,…,dh=b。
从而计算a和b的的组合c(a,b),可变成计算上述分式。
为计算上述分式,先从u1,u2,…,uh中去掉所有d1*d2*…*dh的因子,得到新的u1,u2,…,uh。
然后再将它们相乘。
以下函数中调用的外部函数gcd(a,b)是求两整数a和b最大公因子的函数。
#defineMAXN200
voidformal(int*a)
{intp;
for(p=1;
p<
a[0]││a[p]>
=10;
p++)
{if(p>
=a[0])___
(1)___;
a[p+1]+=a[p]/10;
a[p]=___
(2)___;
if(p>
a[0])___(3)___;
voidcombine(inta,intb,int*c)
{inti,j,x,k;
intd[MAXN],u[MAXN];
for(k=0,i=a;
i>
=a-b+1;
i--)
u[++k]=i;
___(4)___;
for(i=1;
=b;
i++)
d[i]=i;
/*将整数1至b顺序存于数组d*/
=u[0];
i++)/*从u的各元素中,去掉d中整数的所有因子*/
if(u[i]!
=1)
for(j=1;
j++)
if(___(5)___)
{x=gcd(u[i],d[j]);
u[i]/=x;
d[j]/=x;
c[0]=c[1]=1;
/*长整数数c初始化*/
{for(j=1;
j<
=c[0];
j++)
c[j]=___(6)___;
formal(c);
/*将存于c中的长整数规整*/
(1)a[p+1]=0
(2)a[p]%10
(3)a[0]=p
(4)u[0]=k
(5)d[j]!
=1或d[j]>
1
(6)c[j]*u[i]
规整函数从低位至高位逐一检查存储长整数的数组的每个元素,将其中可能存储多位数字的元素,除个位数字之外的数字,作为进位累计到比它高一位的元素,而将其中的个位数字继续保留存储在该元素中。
注意经这个步骤处理,当存储最高位数字的元素值也是多位数时,长整数的位数就会增加。
为对新增加的位也能同前面的低位部分的元素作同样处理,能直接累计低一位数字的高位部分的进位,对应新增加位的元素在处理前先要置0,所以
(1)空的答案是a[p+1]=0。
使数组的每个元素只存储长整数的一位数字,当前位的高位数字作为进位累计到高一位后,当前位的值是原来值的个位,用代码描述是a[p]=a[p]%10,所以
(2)空的答案是a[p]%10。
经规整运算求出各位数字后,如增加了新的位,还得修正该长整数的位数,即将当前位数p存于a[0],所以(3)空的答案是a[0]=p。
函数combine(a,b,c)先为数组u[]设置初值:
u[1]=a,u[2]=a-1,…,u[b]=a-b+1,并置数组d为:
d[1]=1,d[2]=2,…,d[b]=b。
函数为计算分式u[1]*u[2]*…*u[b]/(d[1]*d[2]*…*d[b]),先从u[1],u[2]…,u[b]中去掉所有d[1]*d[2]*…*d[b]的因子,得到新的u[1],u[2],…,u[b]。
函数用代码for(i=l;
i<
=u[0];
i++)实现对u[1]至u[b]中的元素逐一检查,所以(4)空中的代码是为u[0]置值b。
由于为数组u置值结束时,k的值也是b,u[0]也可赋值k。
所以(4)空的答案是u[0]=b或u[0]=k。
在检查u[i]时,若它的值不为1,就逐一考察d[j](1≤j≤b),从u[i]和d[j]中去掉它们的公因子。
如同u[i]!
=l一样,d[j]也要求不等于1,这正是(5)空的解答:
d[j]!
=1或d[j]>
1。
函数从u[1],u[2],…,u[b]中去掉所有d[1]*d[2]*…*d[b]的因子,得到新的u[1],u[2],…,u[b]后,将它们相乘的结果存于长整数c中。
相乘前,先置长整数为1,然后逐一考察新的u[1],u[2],…,u[b],在u[i]不等于l的情况下,让它与长整数c的每位数字c[j]相乘,得到新的c[j]=c[j]*u[i]。
所以(6)空的答案是c[j]*u[i]。
最后让数组c[]中的长整数作规整,重新变成规整的长整数。
************************
9.链表1
函数DelA_InsB(LinkedListLa,LinkedListlb,intkey1,intkey2,intlen)的功能是,将线性表A中关键码为keyl的结点开始的len个结点,按原顺序移至线性表B中关键码为key2的结点之前,若移动成功,则返回0;
否则返回-1。
线性表的存储结构为带头结点的单链表,La为表A的头指针,Lb为表B的头指针。
单链表结点的类型定义为:
typedefstructnode{
intkey;
structnode*next;
}*LinkedList;
intDelA_InsB