C语言。求大神帮我做36。37。谢谢!

Python013

C语言。求大神帮我做36。37。谢谢!,第1张

36.

#include <stdio.h>

int main(void) 

{

int num[10],count=0,sum=0,i

for(i=0i<10++i)

{

scanf("%d",&num[i])

if(num[i]<0)

{

sum+=num[i]

count++

}

}

if(count)

{

printf("%d,%f\n",count,(double)sum/count)

}

return 0

}

37.

#include <stdio.h>

int main(void) 

{

FILE *fp=fopen("a:\\zm.dat","r")

char c[10]

int i,j,t

if(fp)

{

for(i=0i<10++i)

{

c[i]=fget(fp)

}

for(i=0i<9++i)

{

for(j=0j<9-i++j)

{

if(c[j]<c[j+1])

{

t=c[j]

c[j]=c[j+1]

c[j+1]=t

}

}

}

for(i=0i<10++i)

{

putchar(c[i])

}

fclose(fp)

}

return 0

}

完成功能说明:

基本功能以及OK,可以在线修改密码Ok,开机默认密码:123456,在线可修改

功能改进说明:

将代码继续优化,将其中的清楚按键设置成具有连按功能的按键,对于SET和SET_OUT利用一个按键来做(利用按键的3S长按进入重新设置密码模式,利用相同按键的短击退出密码设置模式),设置报警模式以及退出报警设置,利用剩余的按键来做。===============================================

==============MCU:AT89C52=====================

============名称:电子密码锁===================

===========程序编写人:DAIVD===================

=========程序编写时间:2010年8月3日============

=功能描述:六位数码管显示,4*4矩阵键盘作为外设=

=====通过矩阵键盘可以输入密码以及修改密码======

=====通过数码管以及LED显示当前密码锁状态=======

===============版本:V1.0======================

=====项目完成时间: ==========

===============================================

BT0 EQU 20H.0 节拍法标志位每个节拍为20MS

CHANGE_PW_FLAG EQU 20H.1 重新设置密码标志位

OK_FLAG EQU 20H.2 确认密码输入标志位

CLR_FLAG EQU 20H.3 清楚输入密码标志位

KEY_REG EQU 20H.4 按键按下标志位

FLASHING_FLAG EQU 20H.5 闪烁标志位

ONCE_TIME EQU 20H.6 第一次进入标志位

MEMORY_FLAG EQU 20H.7 修改密码是两次输入第一次需要记忆

DIGITAL_FLAG EQU 21H.0 是否需要键入数字标志位

NUM_FLAG EQU 21H.1 数字键标志位

FUNCTION_FLAG EQU 21H.2 功能键标志位

D_DONG_FLAG EQU 21H.3 消抖标志位

KEY_HAVE_REG EQU 21H.4 一次按键多次响应标志位

SET_OUT EQU 21H.5 设置密码状态退出标志位

OTI EQU 21H.6 第一次进入重置密码模式标志位

COMPARE_EN EQU 21H.7

OTII EQU 22H.0

ALARMEQU22H.1 报警标志位

ALARM_OUTEQU22H.2报警退出标志位

ORIGINAL_PW_1 EQU 30H 原始密码存储寄存器

ORIGINAL_PW_2 EQU 31H

ORIGINAL_PW_3 EQU 32H

ORIGINAL_PW_4 EQU 33H

ORIGINAL_PW_5 EQU 34H

ORIGINAL_PW_6 EQU 35H

CURRENT_PW_1 EQU 40H 当前密码存储器

CURRENT_PW_2 EQU 41H

CURRENT_PW_3 EQU 42H

CURRENT_PW_4 EQU 43H

CURRENT_PW_5 EQU 44H

CURRENT_PW_6 EQU 45H

CURRENT_PW_1_REG EQU 46H 当前密码暂存器

CURRENT_PW_2_REG EQU 47H 用于密码修改时比较两次输入是否相同

CURRENT_PW_3_REG EQU 48H

CURRENT_PW_4_REG EQU 49H

CURRENT_PW_5_REG EQU 4AH

CURRENT_PW_6_REG EQU 4BH

DISPLAY_REG_0 EQU 36H 显示寄存器

DISPLAY_REG_1 EQU 37H

DISPLAY_REG_2 EQU 38H

DISPLAY_REG_3 EQU 39H

DISPLAY_REG_4 EQU 3AH

DISPLAY_REG_5 EQU 3BH

COUNT_0 EQU 3CH 用于闪烁标志位的计数200MS

TH0_BUFFER EQU 3DH 定时器赋初值寄存器

TL0_BUFFER EQU 3EH

MAZHI_REG EQU 3DH 4*4矩阵键盘扫描得到的码值

COUNT_1 EQU 3FH 用于设置密码标志位的计数超过3S则置一

COUNT_2 EQU51H 用于输入密码次数是否超过3次

R2_REG EQU 50H

CHIP_SELECT EQU P1 P1作为片选口

OUTPUT EQU P0 P0口作为输出口

GREEN_LED EQU P3.4 绿灯代表输入密码正确

YELLOW_LED EQU P3.3 黄灯代表正在输入密码过程中

RED_LED EQU P3.2 红灯代表输入密码错误

SPKEQU P3.1 蜂鸣器代表输入密码超过3次报警

ORG 0000H

LJMP START

ORG 0003H 中断入口地址写RETI防止出现误判对程序影响

RETI

ORG 000BH

LJMP T0_SER

ORG 0013H

RETI

ORG 001BH

RETI

ORG 0023H

RETI

ORG 002BH

RETI

ORG 0030H

START: MOV ORIGINAL_PW_1,#01 设置初始密码

MOV ORIGINAL_PW_2,#02

MOV ORIGINAL_PW_3,#03

MOV ORIGINAL_PW_4,#04

MOV ORIGINAL_PW_5,#05

MOV ORIGINAL_PW_6,#06

MOV TMOD,#01H 设置定时器0工作方式1采用中断方式

SETB EA

SETB ET0

MOV DPTR,#65536-20000

MOV TH0,DPH

MOV TL0,DPL

MOV TH0_BUFFER,DPH

MOV TL0_BUFFER,DPL

SETB TR0

MOV R0,#CURRENT_PW_1 对当前密码以及当前密码暂存器赋初值

REFRESH_PW: MOV @R0,#0B9H 其中当前密码暂存器用于修改密码时

INC R0 比较两次重新输入的密码是否相等用

CJNE R0,#04CH,REFRESH_PW

MOV 20H,#00H

MOV 21H,#00H

MOV 22H,#00H

MOV COUNT_0,#00H

MOV COUNT_1,#00H

MOV COUNT_2,#00H

=========================================

MAIN: JNB BT0,MAIN

CLR BT0

JNB CHANGE_PW_FLAG,LOOP 判断是否需要修改密码

===============修改原始密码模式========== 当CHANGE_PW_FLAG=1表明进入修改密码模式

JB OTII,LP0

SETB OTII

MOV R2,#0

LP0: JNB SET_OUT,LP

MOV R2,#0

LJMP LP4

LP: JNB OK_FLAG,LOOP1 判断是否输入密码完成

CLR OK_FLAG

JNB OTI,LP1 判断是不是第一次进入要在输入密码正确的前提下

JNB COMPARE_EN,SAVE_MODE 记录两次输入的密码是否一致才确定是否需要重置

CALL COMPARE_CODE

LJMP LOOP1

SAVE_MODE: CALL SAVE_CODE

LJMP LOOP1

LP1: CALL ENTER_PW_MODE

CJNE R2,#0,LP2

LJMP LOOP1

LP2: CJNE R2,#7,LP3 等于7代表原始密码输入正确,下一步记忆新密码

SETB OTI

MOV R2,#0

LJMP LOOP1

LP3: MOV R2,#8

LP4: CLR ALARM_OUT

CLR SET_OUT

CLR OTI 清零所有内容恢复等待密码输入状态

CLR OTII

CLR COMPARE_EN

CLR CHANGE_PW_FLAG

LJMP LOOP1

===============常规输入密码模式==========

LOOP: CLR SET_OUT 非设置密码格式下也会扫描到SET_OUT

防止程序进入设置密码状态下直接退出

JNB ALARM,L1

JB ALARM_OUT,L2

CLR SPK

LJMP LOOP3

L2: SETB SPK

CLR ALARM_OUT

CLR ALARM

LJMP LOOP1

L1: JNB OK_FLAG,LOOP1 判断是否输入密码完成

CLR OK_FLAG

CALL ENTER_PW_MODE

==========================================

LOOP1: JNB CLR_FLAG,LOOP2 判断是否需要清除所输入密码

CLR CLR_FLAG

LCALL CLR_INPUT_PW

LOOP2: JNB DIGITAL_FLAG,LOOP3 判断是否需要输入密码

CLR DIGITAL_FLAG

LCALL INPUT_PW

LJMP LOOP3

=========================================

LOOP3: LCALL DISPLAY

LCALL KEY_SCAN

INC COUNT_0

MOV A,COUNT_0

CJNE A,#5,LOOP4

MOV COUNT_0,#0

CPL FLASHING_FLAG

LOOP4:

LJMP MAIN

=============下面是具体的子程序===========

================检测密码是否正确==========

ENTER_PW_MODE:

CLR OK_FLAG 比较是否为零,为零的时候

CJNE R2,#0,ENTER_PW_MODE_0 代表还没密码输入,直接跳出

LJMP ENTER_PW_MODE_OUT

ENTER_PW_MODE_0:

CJNE R2,#7,$+3 用来比较R2是否为7或者8

JC ENTER_PW_MODE_2

MOV R2,#00 如果8在BAD的模式下切换到输入密码状态

LJMP ENTER_PW_MODE_OUT 如果7在GOOD的模式下切换到输入密码状态

ENTER_PW_MODE_2:

CJNE R2,#6,ENTER_PW_MODE_3 如果R2里的数字不为6代表密码位数不够,肯定错

MOV R0,#ORIGINAL_PW_1 如果R2里的数字等于6那么在比较是否相同

MOV R1,#CURRENT_PW_1

ENTER_PW_MODE_4:

MOV A,@R0

XRL A,@R1 相异或内容相同为0

CJNEA,#00H,ENTER_PW_MODE_3

INC R0

INC R1

CJNER0,#36H,ENTER_PW_MODE_4

MOV R2,#7 如果相同代表密码输入正确GOOD

MOV COUNT_2,#0

LJMP ENTER_PW_MODE_OUT

ENTER_PW_MODE_3:MOV R2,#8 如果不相同则代表密码不正确BAD

INC COUNT_2

MOV A,COUNT_2

CJNE A,#3,$+3

JC KK

FUZHI: MOV COUNT_2,#00H

SETB ALARM

KK: MOV R0,#CURRENT_PW_1 对当前密码以及当前密码暂存器赋初值

REF_PW: MOV @R0,#0B9H 其中当前密码暂存器用于修改密码时

INC R0 比较两次重新输入的密码是否相等用

CJNE R0,#04CH,REF_PW

ENTER_PW_MODE_OUT:

RET

==========================================

=============清除所输入的密码=============

CLR_INPUT_PW:

CLR CLR_FLAG

CJNE R2,#0,CLR_INPUT_PW_0 如果为零则不操作

LJMP CLR_INPUT_PW_OUT

CLR_INPUT_PW_0:

CJNE R2,#7,$+3 用来比较R2是否为7或者8

JC CLR_INPUT_PW_1

MOV R2,#00 如果8在BAD的模式下切换到输入密码状态

LJMP CLR_INPUT_PW_OUT 如果7在GOOD的模式下切换到输入密码状态

CLR_INPUT_PW_1:

DEC R2 正常模式下将R2减一

CLR_INPUT_PW_OUT:

RET

==========================================

============输入单位密码子程序============

INPUT_PW: JB NUM_FLAG,INPUT_PW_0

LJMP INPUT_PW_OUT

INPUT_PW_0: CLR NUM_FLAG

CJNE R2,#7,$+3 比较R2是否大于7,大于C=0

JC INPUT_PW_2

MOV R2,#01 数字键按下输入密码

LJMP INPUT_PW_3_3

INPUT_PW_2: CJNE R2,#6,INPUT_PW_3 如果当前R2等于则6位密码已经输满则不操作

LJMP INPUT_PW_OUT

INPUT_PW_3: INC R2

INPUT_PW_3_3: MOV R1,#01

MOV R2_REG,R2 根据R2的给相应的位送密码

MOV R0,#CURRENT_PW_1

JMP I_LOOP

I_LOOP1: INC R0

INC R1

I_LOOP: MOV A,R1

CJNE A,R2_REG,I_LOOP1

MOV A,R3

MOV @R0,A

INPUT_PW_OUT: RET

==========================================

===============SAVE_CODE==================

SAVE_CODE: CJNE R2,#6,SAVE_CLR 如果R2不等于6代表密码输入错误直接退出

SAVE_IN: MOV R0,#CURRENT_PW_1_REG 将输入的新密码先保存在密码暂存区

MOV R1,#CURRENT_PW_1 46H

SAVE_IN_LOOP: MOV A,@R1

MOV @R0,A

INC R0

INC R1

MOV A,R1

CJNE A,#46H,SAVE_IN_LOOP

SETB COMPARE_EN

MOV R2,#0 密码输入正确则程序处于等待输入状态

LJMP SAVE_OUT

SAVE_CLR: MOV R2,#8

CLR SET_OUT

CLR OTI 清零所有内容恢复等待密码输入状态

CLR OTII

CLR COMPARE_EN

CLR CHANGE_PW_FLAG

SAVE_OUT: RET

===========================================

=================COMPARE_CODE==============

COMPARE_CODE: CJNE R2,#6,COMPARE_FAIL 如果R2不等于6代表上次输入密码数不足6位

COMPARE_IN: MOV R0,#CURRENT_PW_1_REG

MOV R1,#CURRENT_PW_1 46H

COMPARE_IN_LOOP:

MOV A,@R1

XRL A,@R0

CJNE A,#00H,COMPARE_FAIL

INC R0

INC R1

MOV A,R1

CJNE A,#46H,COMPARE_IN_LOOP

MOV R0,#ORIGINAL_PW_1

MOV R1,#CURRENT_PW_1 46H

TIHUAN_LOOP: MOV A,@R1

MOV @R0,A

INC R0

INC R1

MOV A,R1

CJNE A,#46H,TIHUAN_LOOP

MOV R2,#7

CLR SET_OUT

CLR OTI 清零所有内容恢复等待密码输入状态

CLR OTII

CLR COMPARE_EN

CLR CHANGE_PW_FLAG

LJMP COMPARE_OUT

COMPARE_FAIL: MOV R2,#8

CLR SET_OUT

CLR OTI 清零所有内容恢复等待密码输入状态

CLR OTII

CLR COMPARE_EN

CLR CHANGE_PW_FLAG

COMPARE_OUT: RET

===========================================

==================显示子程序==============

DISPLAY: MOV R4,#0

MOV DPTR,#TAB_0

MOV A,R2

RL A

JMP @A+DPTR

TAB_0: AJMP DISPLAY_0

AJMP DISPLAY_1

AJMP DISPLAY_2

AJMP DISPLAY_3

AJMP DISPLAY_4

AJMP DISPLAY_5

AJMP DISPLAY_6

AJMP DISPLAY_7

AJMP DISPLAY_8

DISPLAY_0: MOV DPTR,#TAB_1

LJMP REFRESH_DISPLAY

DISPLAY_1: MOV DPTR,#TAB_2

LJMP REFRESH_DISPLAY

DISPLAY_2: MOV DPTR,#TAB_3

LJMP REFRESH_DISPLAY

DISPLAY_3: MOV DPTR,#TAB_4

LJMP REFRESH_DISPLAY

DISPLAY_4: MOV DPTR,#TAB_5

LJMP REFRESH_DISPLAY

DISPLAY_5: MOV DPTR,#TAB_6

LJMP REFRESH_DISPLAY

DISPLAY_6: MOV DPTR,#TAB_7

LJMP REFRESH_DISPLAY

DISPLAY_7: MOV DPTR,#TAB_8

LJMP REFRESH_DISPLAY

DISPLAY_8: MOV DPTR,#TAB_9

REFRESH_DISPLAY:

MOV R0,#DISPLAY_REG_0

DISPLAY_LOOP:

MOV A,R4

MOVC A,@A+DPTR

MOV @R0,A

INC R4

INC R0

MOV A,R0

CJNE A,#3CH,DISPLAY_LOOP 此时表明数码管显示的数值已送完

DISPLAY_SHOW:

MOV R0,#DISPLAY_REG_0 数码管动态显示

MOV R5,#0FEH

NEXT_0: MOV CHIP_SELECT,R5

MOV A,@R0

MOV OUTPUT,A

LCALL DELAY

MOV OUTPUT,#0FFH

INC R0

MOV A,R5

RL A

MOV R5,A 片选

CJNER0,#3CH,NEXT_0

CJNE R2,#0,NEXT_6

MOV P3,#0FFH

LJMP DISPLAY_OUT

NEXT_6: CJNE R2,#7,NEXT_1

CLR GREEN_LED

SETB YELLOW_LED

SETB RED_LED

LJMP DISPLAY_OUT

NEXT_1: CJNE R2,#8,NEXT_2

SETB YELLOW_LED

SETB GREEN_LED

CLR RED_LED

LJMP DISPLAY_OUT

NEXT_2: JNB CHANGE_PW_FLAG,NEXT_3

JNB FLASHING_FLAG,NEXT_4

MOV P3,#0FFH

LJMP DISPLAY_OUT

NEXT_4: MOV P3,#00H

LJMP DISPLAY_OUT

NEXT_3: JNB FLASHING_FLAG,NEXT_5

MOV P3,#0F7H

LJMP DISPLAY_OUT

NEXT_5: MOV P3,#0FFH

DISPLAY_OUT: RET

=======================================

============按键扫描程序===============

KEY_SCAN: MOV R3,#00H 对码表扫描进行初始化可以访问到第一位

JNB D_DONG_FLAG,PANDUAN 判断是否进行过消抖

LCALL FANZHUAN_SCAN 反转扫描确定码值

CJNE A,#0FFH,L4 如果码值等于0FFH可能是抖动或者按键抬起

L3: CLR D_DONG_FLAG 表明是按键抬起,此时要对D_DONG_FLAG/

CLR KEY_HAVE_REG KEY_HAVE_REG进行清零

CLR COUNT_1

LJMP KEY_SCAN_OUT

L4: JNB ALARM,KEY_SCAN_1

CJNE A,#0B7H,L3

SETB ALARM_OUT

CLR D_DONG_FLAG

LJMP KEY_SCAN_OUT

PANDUAN: LCALL FANZHUAN_SCAN 第一次进入没有经过消抖判断是否有按键按下

CJNE A,#0FFH,KEY_SCAN_0 对所扫描的码值进行比较如果为0FFH没按键按下

LJMP KEY_SCAN_OUT

KEY_SCAN_0: SETB D_DONG_FLAG 所扫到的码值不等于0FFH可能是按键按下

LJMP KEY_SCAN_OUT

KEY_SCAN_1:

JNB KEY_HAVE_REG,KEY_SCAN_1_1一次按键多次响应标志位

CJNE A,#0E7H,KEY_SCAN_1_1_1

INC COUNT_1 长按处理

MOV A,COUNT_1

CJNE A,#150,KEY_SCAN_1_1_1

MOV COUNT_1,#00H

SETB CHANGE_PW_FLAG

CLR D_DONG_FLAG

CLR KEY_HAVE_REG

KEY_SCAN_1_1_1:

LJMP KEY_SCAN_OUT

KEY_SCAN_1_1: MOV MAZHI_REG,A

KEY_SCAN_LOOP:

MOV DPTR,#TAB_10

MOV A,R3

MOVC A,@A+DPTR

CJNE A,#0FFH,KEY_SCAN_2 如果查出的码表值为0FFH代表已经查完了

MOV R3,#0 但是没有符合的就代表是乱码不处理

CLR D_DONG_FLAG

CLR KEY_HAVE_REG

LJMP KEY_SCAN_OUT

KEY_SCAN_2: CJNE A,MAZHI_REG,KEY_SCAN_3 比较是哪个键按下

CJNE R3,#10,$+3 通过比较后形成小于等于9或者大于9两种情况

JNC COMPARE

SHUZI_MODE: SETB KEY_HAVE_REG

SETB NUM_FLAG

SETB DIGITAL_FLAG

LJMP KEY_SCAN_OUT

COMPARE: SETB KEY_HAVE_REG

CJNE R3,#10,COMPARE_0 此时R3内的数值大于9则CY=1

SETB OK_FLAG 等于10为OK键按下

LJMP KEY_SCAN_OUT

COMPARE_0: CJNE R3,#11,COMPARE_1 等于11为清除按键按下

SETB CLR_FLAG

LJMP KEY_SCAN_OUT 等于12为设置密码按键在长按里面加处理

COMPARE_1: CJNE R3,#13,COMPARE_2 等于13为设置密码跳出标志

SETB SET_OUT

LJMP KEY_SCAN_OUT

COMPARE_2: CJNE R3,#14,COMPARE_3

SETB ALARM

LJMP KEY_SCAN_OUT

COMPARE_2: CJNE R3,#14,COMPARE_4

SETB ALARM_OUT

LJMP KEY_SCAN_OUT

COMPARE_4: LJMP KEY_SCAN_OUT 按键加功能

KEY_SCAN_3: INC R3

LJMP KEY_SCAN_LOOP

KEY_SCAN_OUT:

RET

=======================================

FANZHUAN_SCAN: MOV P2,#0F0H 反转扫描确定码值

MOV A,P2

ANL A,#0F0H

MOV B,A

MOV P2,#0FH

MOV A,P2

ANL A,#0FH

ORL A,B

RET

===============显示的码表==============

TAB_1: DB 0BFH,0BFH,0BFH,0BFH,0BFH,0BFH ------

TAB_2: DB 0B9H,0BFH,0BFH,0BFH,0BFH,0BFH +-----

TAB_3: DB 0B9H,0B9H,0BFH,0BFH,0BFH,0BFH ++----

TAB_4: DB 0B9H,0B9H,0B9H,0BFH,0BFH,0BFH +++---

TAB_5: DB 0B9H,0B9H,0B9H,0B9H,0BFH,0BFH ++++--

TAB_6: DB 0B9H,0B9H,0B9H,0B9H,0B9H,0BFH +++++-

TAB_7: DB 0B9H,0B9H,0B9H,0B9H,0B9H,0B9H ++++++

TAB_8: DB 090H,0A3H,0A3H,0A1H,0FFH,0FFH good

TAB_9: DB 083H,0A0H,0A1H,0FFH,0FFH,0FFH bad

TAB_10: DB 0EEH,0DEH,0BEH,07EH,0EDH,0DDH,0BDH,07DH 4*4矩阵键盘的码表

DB 0EBH,0DBH,0BBH,07BH,0E7H,0D7H,0B7H,77H,0FFH

=======================================

==============延时子程序===============

输入:无

输出:无

功能:延时一段时间稳定数码管的显示2.4MS

DELAY:

MOV R7,#30

DL: MOV R6,#40

DJNZR6,$

DJNZR7,DL

RET

=======================================

============定时器中断服务程序=========

T0_SER:

MOV TMOD,#01H

SETB BT0

MOV TH0,TH0_BUFFER

MOV TL0,TL0_BUFFER

RETI

=======================================

END

从数学角度看 设男,女,儿童为x,y,z。

列不等式组:

x+y+z = 36;

4x+3y+1/2z = 36

求x,y,z的值就好了。

数学的解法是讲究推理。程序呢不讲究推理,你只要模拟试数的过程就好了。

那么我应该按照什么原则试数呢?

首先确定x,y,z的范围

0<=x <= 36/4=9

0<=y<=36/3=12

0<=z<=36/0.5=18且z为偶数,因为1个小孩办不了一块砖。

然后看看x,y,z是否符合这个不等式组。

程序如下:

include <stdio.h>

int main(void)

{

    for(int x = 0 x <= 9 ++x)

    {

        for(int y = 0 y <= 12 ++y)

        {

            for(int z = 0 z <= 18 z += 2)

            {

                if(x+y+z == 36 && 4x+3y+z/2 == 36)

                    printf("男%d,女%d,小孩%d", x, y , z)

            }

         }

     }

    return 0

}

此程序不是最高效的,但是你看的懂。