单片机第二次上机报告 本文关键词:上机,单片机,报告
单片机第二次上机报告 本文简介:单片机上机实验报告学院:光学与电子信息学院班级:光电1001班姓名:秦承志学号:U201013349日期:2012.10.13微机实验二实验名称KeilC的使用与汇编语言的上机操作指导教师曹丹华专业班级光电1001班姓名秦承志学号U201013349序号联系方式13018036121一.实验目的:熟
单片机第二次上机报告 本文内容:
单片机上机实验报告
学院:光学与电子信息学院
班级:光电1001班
姓名:秦承志
学号:U201013349
日期:2012.10.13
微机实验二
实验名称
KeilC的使用与汇编语言的上机操作
指导教师
曹丹华
专业班级
光电1001班
姓名
秦承志
学号
U201013349
序号
联系方式
13018036121
一.实验目的:
熟练掌握KeilC环境下汇编语言程序的调试方法,加深对汇编语言指令,机器码,寻址方式等基本内容的理解,掌握用分支程序和简单程序的设计和调试方法,了解并行I/O口的使用。
二.实验内容:
1.
分支程序的设计:
1)设计要求:
设有8bits符号数X存于外部RAM单元,按以下方式计算后的结果Y也存于外部RAM单元,请按要求编写程序:
2)设计思路:
把外部RAM内容传给A,先判断正负,小于或等于0,则执行取反,并把结果传回片外RAM,并结束;若大于0,再判断A与14H的大小,若小于,则执行取反;若大于14H,则再判断A与28H的大小,若A大于等于28H,则执行平方操作,并依此分别把积的低八位,高八位传回片外RAM,并结束;若小于28H,则执行A除以2,结果传回片外RAM。
3)程序流程图如下所示:
4)资源分配和源代码如下所示:
File
name:
分支程序设计.asm
Description:
判断片外RAM的2000H单元的内容,若小于或等于40,则逐位取反,结果
存于原单元中,若大于20且小于40,则内容除以2,结果送回原单元,若大
于或等于40,则单内容平方,结果低八位送回原单元,高八位送至下一单元。
Date:
2012.10.10
Designed
by:
QinChengzhi
Source
used:
DPTR
对片外RAM进行读写
A,B
用于乘法运算的中间结果
2000H,2001H
存放待操作的数作为结果的存放单元
ORG
0000H
LJMP
MAIN
ORG
1000H
;程序从1000H开始
TABLE
EQU
2000H
;定义符号地址TABLE,为2000H
MAIN:
MOV
DPTR,#TABLE
;DPTR赋初值,指向2000H单元
MOVX
A,@DPTR
;把2000H单元内容给A
JB
ACC.7,L1
;最高位为1,则跳转至L1
CJNE
A,#14H,LOOP1
;最高位为0,则比较A与14H,不等则跳转LOOP1
L1:
CPL
A
;A等于14H,也跳转L1,A逐位取反
INC
DPTR
;
DPTR加1
MOVX
@DPTR,A
;把A的内容再送回下一单元
SJMP
DONE
;跳转至DONE
LOOP1:
JC
L1
;A小于14H,也跳转至L1
CJNE
A,#28H,LOOP3
;A大于14H,再与28H比较,不等则跳转LOOP3
LOOP2:
MOV
B,A
;若A小于28H,则转LOOP2,把A内容给B
MUL
AB
;A与B相乘
INC
DPTR
;DPTR加1
MOVX
@DPTR,A
;积的低位存于下一单元
INC
DPTR
;高位存于再下一单元
MOV
A,B
MOVX
@DPTR,A
SJMP
DONE
;跳转至DONE
LOOP3:
JNC
LOOP2
;若A大于28H,跳转到LOOP2
RR
A
;若A小于28H,则A除以2
INC
DPTR
;DPTR加1
MOVX
@DPTR,A
;把A内容传回下一单元
SJMP
DONE
;跳转至DONE
DONE:
SJMP
$
;踏步
END
;结束
4)
程序结果测试与软件性能分析:
4.1程序结果测试:
情况1:不妨在memory的2000H中输入FE,运行结果应为(2001H)=FE取反,即(2001H)=01
仿真结果如下:
对比运行结果和分析结果,两者相符
情况2:在memory的2000H中输入24H,运行结果应为24H/2=12H,运行结果如下所示:
对比运行结果和分析结果,两者相符
情况3:在memory的2000H中输入35H,运行的结果为(2001H)=F9,(2002H)=0A,运行结果如下:
对比运行结果和分析结果,两者相符
4.2软件性能测试:
1)运行时间:从simulation中即可看出程序的运行时间,情况如下:
情况1:
情况2:
情况3:
2)代码量的大小,资源的消耗情况如下所示:
2.
24小时的电子时钟的设计:
1)
设计要求:
利用51系列单片机设计一个24小时制电子时钟,电子时钟的时、分、秒数值分别通过P0、P1、P2端口输出(以压缩BCD码的形式)。P3.0为低电平时开始计时,为高电平时停止计时。
2)
设计思路:
先将P0,P1,P2端口清零,P3.0置0,调用延迟子程序,延时接近1s,在从P2端口读入数据到A中,并加1计数,再转换成压缩BCD码,再调用补偿延时子程序,使定时精确为1s,再判断加1次数,达到60次后,P2端口清零,P1端口加1,再继续调用延迟子程序和补偿延迟子程序,继续计数,再判断P1是否加到60次,加到后,P1端口清零,P0端口加1,再继续加1计数,判断P0所加次数是否达到24,达到24后,P0端口清零,程序结束。
3)
程序流程图如下所示:
4)
程序的资源分配及源代码如下:
File
name:
24小时电子时钟.asm
Description:
电子时钟的时,分,秒分别由P0,P1,P2端口输出,P3.0A为低电平时,开
始计时,输出形式为压缩BCD码
Date:
2012.10.10
Designed
by:
QinChengzhi
Source
used:
P0,P1,P2:输出时分秒
A:加1计数
P3.0:计数标志位
ORG
0000H
LJMP
MAIN
ORG
1000H
;程序从1000H开始
MAIN:
MOV
P0,#0
;P0端口清零
MOV
P1,#0
;P1端口清零
MOV
P2,#0
;P2端口清零
JNB
P3.0,LOOP
;若P3.0为0,则开始计时
LOOP:
LCALL
SDELAY
;调用S延时子程序,延时接近1秒
MOV
A,P2
;把P2端口值给A
ADD
A,#01H
;A的内容加1
DA
A
;转化为BCD码
LCALL
MDELAY
;调用M延迟子程序,补偿1秒延时
NOP
NOP
MOV
P2,A
;把A的内容给P2
CJNE
A,#60H,LOOP
;A小于60H,继续LOOP程序段
MOV
P2,#00H
;A等于60H,则将P2清零
MOV
A,P1
;把P1口内容读入A
ADD
A,#01H
;A的内容加1
DA
A
;转化为BCD码
MOV
P1,A
;把A的内容给P1
CJNE
A,#60H,LOOP
;A小于60H,继续LOOP程序段
MOV
P1,#00H
;A等于60H,则将P1清零
MOV
A,P0
;把P0口内容读入A
ADD
A,#01H
;A的内容加1
DA
A
;转化为BCD码
MOV
P0,A
;把A的内容给P0
CJNE
A,#24H,LOOP
;A小于24H,继续LOOP程序段
MOV
P0,#00H
;A等于60H,则将P0清零
SJMP
DONE
;跳至DONE
SDELAY:
MOV
R1,#8
;S延迟子程序,延迟为999012.5us
DELAY1:
MOV
R2,#250
DELAY2:
MOV
R3,#249
DELAY3:
NOP
NOP
DJNZ
R3,DELAY3
DJNZ
R2,DELAY2
DJNZ
R1,DELAY1
RET
MDELAY:
MOV
R4,#2
;M延迟子程序,补偿延迟979.5us
DELAY4:
MOV
R5,#244
DELAY5:
NOP
NOP
DJNZ
R5,DELAY5
DJNZ
R4,DELAY4
RET
DONE:
SJMP
DONE
;踏步指令
END
;结束
5)
程序结果测试与软件性能性能分析:
5.1
程序结果测试:
理论分析过程:该程序选用的8951单片机,晶振频率为24MHz,故一个机器周期时间为:
;
由于该程序使用了延时补偿,所以每一秒钟可以精确定时,第一个延时子程序—S延时子程序,用到了三层循环,共定时时间计算如下:
;
补偿延时子程序—M延时子程序,运用了两层循环,共定时为:
剩下有2个NOP操作,2个MOV操作,1个ADD操作,1个DA,一个CJNE操作,共定时为:
所以每两次加1操作之间的时间定时精确为
运行结果如下所示:取两次P2口刷新的时间差,即计数时间差如下:
下一次P2口刷新完一瞬时,即下一次计数时间如下:
对比两次计数时间的时间差,发现为精确的1秒钟,说明没隔1秒钟计数没有误差,即P2端口是严格的按照每个一秒钟加1刷新1次的。
再看每一分钟的误差:
理论上分析:每次P2端口清零,P1端口加1,即分钟加1时,经过了2个MOV,1个ADD,1个DA,2个CJNE的操作,故每相邻的P1口刷新时间间隔,也即是每1分钟的定时误差为:
即是每分钟误差为4us,因此每小时误差为240us.每相邻P1口刷新时间间隔如下:
下一次加1完成的时间见下页,两次时间差为4us.以上的分析是正确的
下次P1端口刷新时间如下:
5.2
软件性能分析如下:
三.提高任务:
1)
设计要求:
a.
实现4位十进制加、减1计数,千位、百位由P1口输出;十位、个位由P2口输出。利用P3.7状态选择加、减计数方式。
b.
利用P3口低四位状态控制开始和停止计数,控制方式自定。
2)2.1.1设计思路1:
4位十进制数加计数器为一个状态为0000—9999的循环计数器,可以从任何一个状态开始,必须先预处理,对于任何初始状态,先转换成BCD码。每次计数前,先由P3.0端口状态决定是否计数,再由P3.7端口状态决定计数模式。进行加1计数时:把P2端口(十位和各位)的值给A,然后加1,进行DA修正后,再传回P2端口,再把P1端口(千位和百位)的值给A,加上低位的进位,再进行DA修正,再把结果传回P1端口;进行减1计数时:把P2端口(十位和各位)的值给A,然后加上99H,进行DA修正后,再传回P2端口,判断P1端口是否为00H,为00H,则再把P1端口(千位和百位)的值给A,此时不管低位的进位,直接加上99H,进行DA修正,直接送回P1端口。
且每两次计数的时间间隔由两次延迟子程序决定。
2.1.2思路1的程序流程图如下所示:
2.1.3思路1的资源分配及其源代码如下:
File
name:
4位十进制加减计数器1.asm
Description:
P3.0=1,开始计数;P3.0=0,停止计数
P3.7=1,加计数;P3.0=0,减计数
P1显示千位和百位的压缩BCD码,P2输出十位和各位
Date:
2012.10.10
Designed
by:
QinChengzhi
Source
used:
P1,P2:输出计数器的千位百位,十位各位
A:用于加1计数和减1计数的中间操作
P3.0:计数起停标志位
P3.7:计数模式标志位
ORG
0000H
LJMP
MAIN
ORG
1000H
MAIN:
MOV
A,P2
;把P2端口的初始值转成成BCD码
ADD
A,#00H
DA
A
MOV
P2,A
MOV
A,P1
;把P1端口的初始值转化成BCD码
ADD
A,#00H
DA
A
MOV
P1,A
START:
JNB
P3.0,DONE
;P3.0为0,不计数,跳至DONE
ACALL
SDELAY
;计数开始,调用S延迟子程序
ACALL
MDELAY
;调用M延迟子程序,定时1秒
JNB
P3.7,DOWN
;P3.7为0,则调至减计数
UP:
MOV
A,P2
;P3.7为1,则进行加计数,P2口读到A
ADD
A,#01H
;A内容加1
DA
A
;2-10进制转换,化成BCD码
MOV
P2,A
;把A内容传回P2,显示十位和各位
MOV
A,P1
;把P1的内容读到A
ADDC
A,#00H
;A加上低位的进位
DA
A;2-10进制,化成BCD码
MOV
P1,A
;把A的内容传回P1
SJMP
START;不断的加循环计数
DOWN:
MOV
A,P2;减计数,P2内容给A
ADD
A,#99H;加上99H
DA
A;化成BCD
MOV
P2,A;把A的内容传回P2
CJNE
A,#00H,START
CLR
A;A清零
MOV
A,P1;P1的内容给A
ADD
A,#99H;A的内容加99H
DA
A;化成BCD码
MOV
P1,A;把A的内容传回P1
SJMP
START;继续减计数
SDELAY:
MOV
R1,#8;S延迟子程序,延迟为999014.5us
DELAY1:
MOV
R2,#250
DELAY2:
MOV
R3,#249
DELAY3:
NOP
NOP
DJNZ
R3,DELAY3
DJNZ
R2,DELAY2
DJNZ
R1,DELAY1
RET
MDELAY:
MOV
R4,#2
;M延迟子程序,补偿延迟981.5us
DELAY4:
MOV
R5,#244
DELAY5:
NOP
NOP
DJNZ
R5,DELAY5
DJNZ
R4,DELAY4
RET
DONE:
MOV
P1,#00H
;P1口清零
MOV
P2,#00H
;P2口清零
SJMP
DONE
;踏步指令
END
;结束
2.2.1设计思路2:
程序的预处理的和计数起停及计数模式标志位都与思路1相同,加1计数与思路1也相同,不同的是减1计数,思路如下:先进行低位的减1操作,把结果的各位和十位分别用寄存器存起来,
借位位存在C中,再取千位和百位,先减去借位位,再把百位和千位分别存起来。无论是高位还是低位,减1之前当遇到00H时,减之后单片机中为FFH,此时应该把FFH直接转换09H或90H.再将结果显示出来。
2.2.2程序的资源分配和部分源代码如下:(由于加1计数和延时子程序均与思路1相同,故此处只给出思路2的减1计数的子程序)。
File
name:
4位十进制加减计数器2.asm
Description:
P3.0=1,开始计数;P3.0=0,停止计数
P3.7=1,加计数;P3.0=0,减计数
P1显示千位和百位的压缩BCD码,P2输出十位和各位
Date:
2012.10.10
Designed
by:
QinChengzhi
Source
used:
P1,P2:输出计数器的千位百位,十位各位
A:用于加1计数和减1计数的中间操作
P3.0:计数起停标志位
P3.7:计数模式标志位
R1,R2,R3,R4分别用来存储各位,十位,百位,千位
R0用来存储中间计算结果
DOWN:
CLR
C
;C清零
MOV
A,P2
;P2的内容给A
SUBB
A,#01H
;A的内容减1
MOV
R0,A
;暂存结果于R0
ANL
A,#0FH
;取个位
MOV
R1,A
;存于R1
MOV
A,R0
;暂存结果传回A
ANL
A,#0F0H
;取十位
MOV
R2,A
;存于R2
MOV
A,P1
;把P1内容给A
SUBB
A,#00H
;A减去低位的借位
MOV
R0,A
;暂存结果
ANL
A,#0FH
;取百位
MOV
R3,A
;存于R3
MOV
A,R0
;暂存结果传回A
ANL
A,#0F0H
;取千位
MOV
R4,A
;存于R4
CJNE
R1,#0FH,L1
;个位不为0FH,转L1
MOV
R1,#09H
;个位为0FH,直接变为09H
L1:
CJNE
R2,#0F0H,L2
;十位不为F0H,转L1
MOV
R2,#90H
;十位为F0H,直接变为90H
L2:
CJNE
R3,#0FH,L3
;百位不为0FH,转L1
MOV
R3,#09H
;百位为0FH,直接变为09H
L3:
CJNE
R4,#0F0H,L4
;千位不为F0H,转L1
MOV
R4,#90H
;千位为F0H,直接变为90H
L4:
MOV
A,R1
;个位给A
ADD
A,R2
;十位个位相加
MOV
P2,A
;结果传回P2
MOV
A,R3
;百位给A
ADD
A,R4
;百位千位相加
MOV
P1,A
;结果传回P1
SJMP
START
;继续减1计数
3)
程序的测试结果如下:(由于两种思路的测试结果相同,这里就第2种思路进行结果测试)。
3.1加1计数:
取几个状态刷新一瞬时的结果,如下所示:
由以上的运行结果可看出:计数器从0099到0100完成状态转换,时间为1.000003秒
定时误差为3us,定时准确度比较高。
3.2减1计数如下:
由运行结果可知:以上为从0100减1到0099状态的转换,用时1.00001550秒
定时误差为15.5us,定时误差较加1计数大些。
4.
实验的思考题:
1.
实现多分支结构程序的主要方法有哪些?举例说明。
答:方法主要是分支表法,分支表发又分为:分支地址表法,转移指令表法,地址偏移量表法,现针对一个例子分别用三种方法:
例子如下:
根据R1的值,控制程序转向8个分支程序
1)
分支地址表法:思路就是先把分支地址表的表首地址给DPTR,再通过R1的值得出要跳转到的
程序的首地址在分支地址表中的位置,把要跳转到的地址给DPTR,再把A清
零,再用指令JMP
@A+DPTR转向分支地址,具体程序如下:
MOV
DPTR,#TABLE
;取表首地址
MOV
A,R1
ADD
A,R1
;R1加倍,给A
JNC
LOOP
;无进位,直接转LOOP
INC
DPH
;有进位,则DPTR的高8位加1
LOOP:
MOV
R2,A
;暂存A
MOVC
A,@A+DPTR
;取分支地址的高8位给A
MOV
R3,A
;存地址
MOV
A,R2
;回复A
INC
A
MOVC
A,@A+DPTR
;取分支地址的低8位给A
MOV
DPL,A
;分支地址低位给DPL
MOV
DPH,R3
;分支地址高位给DPH
CLR
A
JMP
@A+DPTR
;转向分支地址
TABLE:
DW
L1
;分支地址表
DW
L2
.
DW
L6
DW
L7
L1:
.
L2:
.
2)
采用转移指令表法:思路仍然是先把分支地址表的表首地址给DPTR,再通过R1的值得出要跳
转的分支程序的首地址在分支地址表中的位置,直接运用JMP
@A+DPTR
转向分支地址,程序举例如下:
MOV
DPTR,#TABLE
;取表首地址
MOV
A,R1
ADD
A,R1
;R1加倍,给A
JNC
LOOP
;无进位,直接转LOOP
INC
DPH
;有进位,则DPTR的高8位加1
LOOP:
JMP
@A+DPTR
;转向分支地址
TABLE:
DW
L1
;分支地址表
DW
L2
.
DW
L6
DW
L7
L1:
.
L2:
.
3)采用地址偏移量法:先把表首地址给DPTR,再把待转移的地址在地址表中的序号(地址为8
位2进制数)给A,运用MOVC
A,@A+DPTR把待转移的地址给A,再转向
相应的分支地址,程序举例如下所示:
MOV
DPTR,#TABLE
;取表首地址
MOV
A,R1
;表的序号送A
MOVC
A,@A+DPTR
;查表
JMP
@A+DPTR
;转相应分支地址
TABLE:
DB
L1
;地址偏移量表
DB
L2
.
DB
L7
L1:
.
L2:
.
2.
在编程上,十进制加1计数器与十六进制加1计数器的区别是什么?怎样用十进制加法指令实现减1计数?
答:
十六进制加1计数就是按照计算机的二进制运算法则进行加法的,可以直接进行加1操作,而十进制计数器的状态是以BCD码的形式显示出来的,而每次加1操作后,单片机仍然按照二进制运算规则进行计算,故需要对结果进行DA
A的修正,得到BCD码的运算结果并显示出来。
对十进制(用BCD表示的)的数进行加99H,可以实现减1计数。
2.在编程上,十进制加1计数器与十六进制加1计数器的区别是什么?怎样用十进制加法指令实现减1计数?
篇2:数值积分上机报告
数值积分上机报告 本文关键词:上机,数值,积分,报告
数值积分上机报告 本文简介:计算方法数值积分上机习题报告一、问题数学上已经证明:0141+x2dx=π成立,所以可以通过数值积分来计算π的近似值(1)分别使用矩形、梯形和Simpson复合求积公式计算π的近似值.选择不同的h,对每种求积公式,是将误差刻画成h的函数,并比较各方法精度.是否存在某个h值,当低于这个值后再继续减小h
数值积分上机报告 本文内容:
计算方法数值积分上机习题报告
一、
问题
数学上已经证明:
0141+x2dx=π
成立,所以可以通过数值积分来计算π的近似值
(1)分别使用矩形、梯形和Simpson复合求积公式计算π的近似值.选择不同的h,对每种求积公式,是将误差刻画成h的函数,并比较各方法精度.是否存在某个h值,当低于这个值后再继续减小h的值,计算不再有所改进?为什么?
(2)实现Romberg求积方法,并重复上面的计算.
(3)使用自适应求积方法重复上面的计算.
二、解决问题的算法
1、各求积方法的实现
先将[a,b]区间分割为小区间,引入等距分点
xi=a+ih,h=b-an,i=0,1,…,n
并记
xi+12=a+i+12h
(1)矩形求积方法公式:
If≈Mf,h=hi=0n-1f(xi+12)
(2)梯形求积方法公式:
If≈Tf,h=h2i=0n-1(fxi+fxi+1)
(3)Simpson复合求积公式:
If≈Sf,h=h6i=0n-1(fxi+4fxi+12+fxi+1)
(4)Romberg求积方法:
记T1h=T(f,h)为复合梯形求积公式,则有递推定义的求积序列:
Tk+1h=Tkh/2-4-kTkh1-4-k,k=1,2,3…
(5)自适应求积方法:
a.设给定的精度要求为ε,取初始步长为h=b-a;
b.计算T(h);
c.将h/2赋予h,计算T(h/2);
d.若|T(h/2)
-
T(h)|<
ε,则输出T(h/2),否则将h/2赋予h,转到b,再继续计算.
2、计算精度的方法
因为π是一个数学常数,在各大主流程序语言中均有定义,所以可以计算得到的数值积分值I与π的差值:|π-I|来得到各方法的精度
三、使用的工具
C语言
四、数值结果
1、矩形求积公式结果及误差:
2、梯形求积公式结果及误差:
3、Simpson复合求积公式结果及误差:
4、自适应求积方法结果及误差:
5、Romberg求积方法结果及误差:
五、数值结果分析
1、对于以上五种不同的算法,均可以得到π的近似值为3.141592654.
2、C++中储存的π的值为M_PI=3.14159265358979310862,精度达到10-20,而上表中表明各方法所计算出来的最高误差精度集中在10-13~10-16,并未达到10-20的精度,所以以下对精度的讨论是有效的.
3、下面对矩形、梯形、Simpson复合求积公式的精度做一个简单的比较
方法
h
矩形复合求积
梯形复合求积
Simpson复合求积
0.1
10-4
10-5
10-10
0.02
10-5
10-6
10-14
0.01
10-6
10-7
10-20
0.005
10-6
10-7
10-16
0.002
10-7
10-8
10-15
由此可见,在h不是非常小时,每种方法的精度均随着h的减小而提高。而且从上表可以看出,上面三种方法中Simpson复合求积公式的精度最高,当h=0.1时精度就达到了非常高的10-10;矩形、梯形复合求积公式精度相当,均比较低,其中梯形求积公式精度略高于矩形求积公式。
4、使用矩形、梯形复合求积公式h的精度达到10-6、Simpson复合求积公式h的精度达到10-2后精度便不再提高,反而有所降低,并在10-13~10-16附近震荡。所以存在某一个h值,当低于这个值后再继续减小h的值,精度不再有所改进。这是因为随着h的缩小,进行数值积分时数据的截断误差会增大,当其与积分公式的误差相比拟甚至高得多后,精度便不再提高。最重要的是,由于计算时使用的数据类型为double型,C语言中double型可以完全保证的有效位数是小数点后15位,16位只是部分数值有保证,所以精度基本都低于10-16。随着h的减小,精度仍能达到10-10以上,说明数值积分的数值稳定性比较好。
5、使用Romberg求积方法,精度取决于h和k.
求积精度比Simpson复合求积公式还要好。不过对于h减小到某个值、k增大到某个值后,精度不再有所改进,原因与上一条分析的原因相同。
6、使用自适应方法,结果的精度与h无关,只与选择的ε有关,而且随着ε的减小精度不断提高,ε与积分得到的误差相当。
篇3:计算机上机实习报告
计算机上机实习报告 本文关键词:上机,实习报告,计算机
计算机上机实习报告 本文简介:班级:自本一班学号:201028004姓名:徐艳改错题第1题1、题目要求函数fun的功能是:用递归算法计算斐波拉契级数数列中第n项的值。从第l项起,斐波拉契级数序列为1、1、2、3、5、8、13、21、…;例如:当给n输入7,该项的斐波拉契级数值为13。#includelongfun(intg)/*
计算机上机实习报告 本文内容:
班级:
自本一班
学号:
201028004
姓名:
徐艳
改错题
第1题
1、
题目要求
函数fun的功能是:用递归算法计算斐波拉契级数数列中第n项的值。从第l项起,斐波拉契级数序列为1、1、2、3、5、8、13、21、…;例如:当给n输入7,该项的斐波拉契级数值为13。
#include
long
fun(int
g)
/*************found************/
{
switch(g);
{
case
0:return
0;
/***********found*************/
case
1;case
2:
return
1;
}
return
(fun(g-1)+fun(g-2));
}
main()
{
long
fib;
int
n;
printf(“input
n:
“);
scanf(“%d“,printf(“n=%d/n“,n);
fib=fun(n);
printf(“fib=%d/n/n“,fib);
}
2、
错误分析
?语句swich(g);错误,swich(表达式)后不应该带有“;”,应该为:swich(g)
?语句case
1;case
2:
return
1;错误,case语句常量后应该是“:”,应该为:case:case:return
1;
第2题
一、题目要求
下列给定程序中,函数fun的功能是:将字符串p中的所有字符复制到字符串b中,要求每复制三个字符之后插入一个空格。例如,在调用fun函数之前给字符串a输入ABCDEFGHIJK,调用函数之后,字符串b中的内容则为ABC
DEF
GHI
JK。
#include
void
fun(charp,charb)
{
int
i,k=0;
while(*p)
/**********found********/
{
i=1;
/***********found*********/
while(i
#include
#define
MAXLINE
20
fun
(
charpstr[6])
{
int
i,j
;
charp
;
for
(i
=
0
;
i
0)
{
p
=(pstr
+
i)
;
/**************found**************/(pstr
+
i)
=
pstr
+
j
;(pstr
+
j)
=
p
;
}
}
}
}
main(
)
{
int
i
;
charpstr[6],str[6][MAXLINE]
;
clrscr(
)
;
for(i
=
0;
i
#include
long
fun
(long
num)
/************found************/
{
long
k;
do
{
k*=num%10;
/************found************/
num/=10;
}
while(num);
return
(k);
}
main(
)
{
long
n
;
clrscr()
;
printf(“/Please
enter
a
number:“);
scanf(“%ld“,printf(“/n%ld/n“,fun(n))
;
}
二、错误分析
①k用来存放各位数字的积,初始值应为1,应该为long
k=1;
②除号应用“/“来表示,所以应改为num/=10;
第5题
一、题目要求
下列给定程序中,fun函数的功能是:求出以下分数序列的前n项之和。和值通过函数值返回main()函数。
例如,若n=5,则应输出8.391667。
#include
#include
/**************found**************/
fun(n)
int
n
;
{
int
a=2,b=1,c,k
;
double
s=0.0
;
for(k
=1;k
#include
int
fun(intx,int
y)
{
int
t;
/**********found********/
t=x;x=y;
/************found************/
return(y);
}
main()
{
int
a=3,b=8;
clrscr();
printf(“%d
%d/n“,a,b);
b=fun(
printf(“%d
%d/n“,a,b);
}
二、错误分析
①变量t作为中间变量,然后进行数据交换,因参数x是指针变量,交换时应使用*x,所以应该为t=*x;*x=y;
②确定返回值,根据代码b=fun(8a,b)可以知道返回值将赋给变量b,而b中应存放交换前**中的值,所以函数应返回变量t,所以应该为return(t);
第7题
一、题目要求
下列给定程序中,函数fun的功能是:求出两个非零正整数的最大公约数,并作为函数值返回。例如,若给numl和num2分别输入49和2l,则输出的最大公约数为7;若给numl和num2分别输入27和81,则输出的最大公约数为27。
#include
int
fun(int
a,int
b)
{
int
r,t;
if(a
#include
void
fun
(long
s,longt)
{
int
d;
long
sl=1;
/************found************/
t
=
0;
while
(
s
>
0)
{
d
=
s%10;
/************found************/
if
(d%2
==
0)
{t
=
d
sl
+t;
sl=
10;
}
s
/=
10;
}}
main()
{
long
s,t;
clrscr();
printf(“/nPlease
enter
s:“);
scanf(“%ld“,fun(s,printf(“The
result
is:
%ld/n“,t);
}
二、错误分析
①变量t是指针变量,所以对t进行赋初值0是不对的。因为t指向的是存放新数的变量,所以此处应给新数赋初值0,即*t=0;
②变量d表示数s各个位上的数,此处的if条件应为判断d是否为奇数,所以此处应为if
(d%2
!=
0)
第9题
一、题目要求
下列给定程序中,函数fun的功能是:将一个由八进制数字字符组成的字符串转换为与其面值相等的十进制整数。规定输入的字符串最多只能包含5位8进制数字。例如,若输入77777,则输出将是32767。
#include
int
fun(charp)
{
int
n;
/*******found*********/
n=*p-
o
;
p++;
while(*p!=0)
/********found********/
{
n=n*7+*p-
o
;
p++;
}
return
n;
}
main()
{
char
s[6];
int
i;
int
n;
printf(“enter
a
string(ocatal
digits):“);
gets(s);
if(strlen(s)>5){
printf(“error:
string
too
longer!/n/n“);
exit(0);}
for(i=0;s[i];i++)
if(s[i]
7
)
{
printf(“error:%c
not
is
ocatal
digits!/n/n“,s[i]);
exit(0);}
printf(“the
original
string:“);
puts(s);
n=fun(s);
printf(“/n%s
is
convered
to
integer
number:
%d/n/n“,s,n);
}
二、错误分析
①“0“和“1“是字符串中的数字字符,为了进行数字运算,必须要将数字字符转换为数字,用数字字符减去字符
0
的ASCII码,就得到对应的数字。题中给出的是“o“,不是“0“,所以此处为n=P-
0
;
②要在一个八进制数的最后加上一位,原来各个位上的数上升一位,只需将原数乘以8再加上个位数,所以此处为n=n*8+*P-
0
;
第10题
一、题目要求
下列给定程序中,函数fun的功能是:计算并输出k以内最大的10个能被13或17整除的自然数之和。k的值由主函数传入,若k的值为500,则函数值为4622。
#include
#include
int
fun(
int
k
)
{
int
m=0,mc=0,j,n;
while((k
>=2)
for
(i=0;
i___3___)
{
min
=
a[j];
pn
=
j;
}
}
if
(pn
!=
i)
{
t
=
a[i];
a[i]
=
min;
a[pn]
=
t;
if
(px
==
i)
px
=pn;
}
if
(px
!=
i+1)
{
t
=
a[i+1];
a[i+1]
=
max;
a[px]
=
t;
}
}
}
main()
{
int
b[N]={9,1,4,2,3,6,5,8,7},i;
printf(“/nThe
original
data
:/n“);
for
(i=0;
i
/**********found**********/
___1___
fun(char
ch)
{
/**********found**********/
if
(ch>=
0
return
ch
;
}
main()
{
char
c1,c2;
printf(“/nThe
result
:/n“);
c1=
2
;
c2
=
fun(c1);
printf(“c1=%c
c2=%c/n“,c1,c2);
c1=
8
;
c2
=
fun(c1);
printf(“c1=%c
c2=%c/n“,c1,c2);
c1=
a
;
c2
=
fun(c1);
printf(“c1=%c
c2=%c/n“,c1,c2);
}
二、算法分析
本程序完成的功能是进行数字字符转换。
①对函数fun()的定义,函数名前是返回值的数据类型,第一个空白处应为:“_char_”。
②判断ch是否是数字字符,第二个空白处应为:“_ch
#include
#define
M
5
#define
N
20
int
fun(char
(*ss)[N],intn)
{
int
i,k=0,len=
N;
/**********found**********/
for(i=0;
i
void
fun(chars)
{
int
i,j=0,k=0;
char
t1[80],t2[80];
for(i=0;
s[i]!=
/0
;
i++)
if(s[i]>=
0
sl
=
strlen(s);
tl
=
strlen(t);
for
(i=0;
i=ul)
/************found************/
u[ul++]=___2___
;
}
}
/************found************/
___3___
=
/0
;
}
main()
{
char
s[100],t[100],u[100];
printf(“/nPlease
enter
string
s:“);
scanf(“%s“,s);
printf(“/nPlease
enter
string
t:“);
scanf(“%s“,t);
fun(s,t,u);
printf(“The
result
is:
%s/n“,u);
}
二、算法分析
程序的功能是将既在字符串s中出现、又在字符串t中出现的字符形成一个新的字符串放在u中,u中字符按原字符串中字符顺序排列,但去掉重复字符。
①重复字符时结束本次循环,去掉重复字符。第一个空白处应为:“_==_”。
②既在字符串s中出现、又在字符串t中出现的字符s[i]赋给u[ul++]第二个空白处应为:“_s[i]_”。
③为u[]添加字符串结束标志。第三个空白处应为:“_u[ul]_”。
第6题
一、题目要求
给定程序中,函数fun的功能是;统计形参s所指字符串中数字字符出现的次数,并存放在形参t所指的变量中,最后在主函数中输出。例如,形参s所指的字符串为:abcdef35adgh3kjsdf7。输出结呆为;4。
#include
void
fun(chars,intt)
{
int
i,n;
n=0;
/**********found**********/
for(i=0;
___1___
!=NULL;
i++)
/**********found**********/
if(s[i]>=
0
j
=
0;
for
(i=0;
i
void
fun(int
a[],int
n)
{
int
i,t;
/**********found**********/
for
(i=0;
i
#include
int
fun(charsource,chartarget)
{
FILEfs,*ft;
char
ch;
/**********found**********/
if((fs=fopen(source,___1___))==NULL)
return
0;
if((ft=fopen(target,“w“))==NULL)
return
0;
printf(“/nThe
data
in
file
:/n“);
ch=fgetc(fs);
/**********found**********/
while(!feof(___2___))
{
putchar(
ch
);
/**********found**********/
fputc(ch,___3___);
ch=fgetc(fs);
}
fclose(fs);
fclose(ft);
printf(“/n/n“);
return
1;
}
main()
{
char
sfname[20]
=“myfile1“,tfname[20]=“myfile2“;
FILEmyf;
int
i;
char
c;
myf=fopen(sfname,“w“);
printf(“/nThe
original
data
:/n“);
for(i=1;
i
#include
#include
void
WriteText(FILE);
void
ReadText(FILE);
main()
{
FILEfp;
if((fp=fopen(“myfile4.txt“,“w“))==NULL)
{
printf(“open
fail!!/n“);
exit(0);
}
WriteText(fp);
fclose(fp);
if((fp=fopen(“myfile4.txt“,“r“))==NULL)
{
printf(“open
fail!!/n“);
exit(0);
}
ReadText(fp);
fclose(fp);
}
/**********found**********/
void
WriteText(FILE
___1___)
{
char
str[81];
printf(“/nEnter
string
with
-1
to
end
:/n“);
gets(str);
while(strcmp(str,“-1“)!=0)
{
/**********found**********/
fputs(___2___,fw);
fputs(“/n“,fw);
gets(str);
}
}
void
ReadText(FILEfr)
{
char
str[81];
printf(“/nRead
file
and
output
to
screen
:/n“);
fgets(str,81,fr);
while(
!feof(fr)
)
{
/**********found**********/
printf(“%s“,___3___);
fgets(str,81,fr);
}
}
二、算法分析
程序的功能是:从键盘输入若干行文件(每行不超过80个字符),写到文件myfile4.txt中,用-1作为字符串输入结束的标志。然后将文件的内容读出显示在屏幕上
①
义一个文件指针fw第一个空白处应为:“_*fw_”。
②将str[81]字符串输入到fw所指文件中
第二个空白处应为:“_str_”。
③将字符串输出第三个空白处应为:“_str_”。
编程题
第1题
1、
题目要求
某学生的记录由学号、8门课程成绩和平均分组成,学号和8门课程的成绩已在主函数中给出。请编写函数fun,它的功能是:求出该学生的平均分放在记录的ave成员中。请自己定义正确的形参。例如,若学生的成绩是85.5,76,69.5,85,9l,72,64.5,87.5,则他的平均分应当是78.875。
#include
#define
N
8
typedef
struct
{
char
num[10];
double
s[N];
double
ave;
}STREC;
void
fun()
{
}
main()
{STRECs={“GA005“,85.5,76,69.5,85,91,72,64.5,87.5;
int
i;
fun(
printf(“the
%s
s
student
data:/n“,s.num);
for(i=0;i
#include
void
fun
(inta,intn)
{
}
main()
{int
aa[1000],n,k;
clrscr();
fun(aa,for(k=0;k
#include
void
fun(chara)
{
}
main()
{
char
s[81];
printf(“enter
a
string:/n“);
gets(s);
fun(s);
printf(“the
string
after
deleted:/n“);
puts(s);
}
二、算法分析
1.
主要数据结构
char
s[81];用于盛放一个字符串
2.
算法描述
①遍历数组a[i]。
②将不是‘*’的字符放入新数组中,并在新数组结尾加上字符串结束标识′/0′。
三、实现代码
void
fun(
chara
)
{int
i,j=0;
for(i=0;a[i]!=
/0
;i++)
if(a[i]!=
)
a[j++]=a[i];
a[j]=
/0
;
}
四、程序测试
程序测试结果正确,需要注意的是要删除字符串中所有*号需要用循环语句遍历字符串,用判断语句判断字符是否为*号,由此可以决定该程序应使用循环判断结构。
第4题
一、题目要求
编写一个函数fun,它的功能是:实现两个字符串的连接(不使用库函数strcat),
即把p2所指的字符串连接到pl所指的字符串后。例如,分别输入下面两个字符串:
FirstString—
SecondString
则程序输出:
FirstString--SecondString
#include
#include
void
fun(char
p1[],char
p2[])
{}
main()
{
char
s1[80],s2[40]
;
clrscr()
;
printf(“Enter
s1
and
s2:/n“)
;
scanf(“%s%s“,s1,s2)
;
printf(“s1=%s/n“,s1)
;
printf(“s2=%s/n“,s2)
;
printf(“Invoke
fun(s1,s2):/n“)
;
fun(s1,s2)
;
printf(“After
invoking:/n“)
;
printf(“%s/n“,s1)
;
}
二、算法分析
1.
主要数据结构
char
s1[80],s2[40]
;分别用来盛放两个字符串
2.
算法描述
①输入两个字符串数组。
②求出第1个字符串的长度,即将i指到第1个字符串的末尾。
③将第2个字符串的字符连到第1个字符串的末尾,并最后在第1个字符串的结尾加上字符串结束标识′/0′。
三、实现代码
void
fun(char
p1[],char
p2[])
{
int
i,j;
for(i=0;p1[i]!=
/0
;i++)
;
for(j=0;p2[j]!=
/0
;j++)
p1[i++]=p2[j];
p1[i]=
/0
;
}
四、程序测试
程序测试结果正确,需要注意的是不使用字符串函数实现字符串连接操作。通过for循环语句来完成,不要忘了最后需要加上字符串结束标识
/0
。
第5题
一、题目要求
编写函