C 语言超全练习题(一): 初识C语言

本文介绍了C语言的开发过程,包括编辑、编译、连接和运行四个步骤,并详细阐述了每个步骤的具体内容。此外,还讨论了C语言的应用领域,如系统软件、图形处理、嵌入式设备开发和游戏软件开发等。文中提供了四个上机练习题,包括输出、计算正方形周长等简单程序,适合C语言初学者进行实践操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、问答题

1.1 C语言开发过程是怎样的?

问题描述:C语言的整个开发过程是怎样的?都包括哪些步骤?

参考:C语言的开发过程包括编辑、编译、连接和运行4个步骤。

  1. 编辑源文件: 利用编辑器将编辑的C语言程序代码输入计算机,然后保存编辑好的代码在磁盘中,这样就生成了C语言的源文件。
  2. 编译源文件: 利用编译器将源程序翻译成目标代码的过程。其具体过程是先将源程序转换成汇编语言程序,然后再将汇编语言翻译成及其指令程序,即目标程序。

    举例说明:gcc 编译的流程:
    ① 预处理 生成预处理过得C代码 xx.i gcc -E xx.c -o xx.i -E 使编译器在预处理结束的时候停止
    ② 把我们预处理过的代码生成我们的汇编代码 xx.s gcc -S xx.i -o xx.s -S 使编译器在编译结束的时候停止
    ③ 把汇编代码生成我们的目标文件 xx.o gcc -c xx.s -o xx.o -c 使编译器在汇编结束的时候停止

  3. 连接: 将目标程序的各个部分进行连接配置,生成一个可供运行的可执行程序。
  4. 运行: 将编译好的可执行文件运行。通过运行程序可查看程序执行输出结果。④ gcc xx.o -o xx -o 输出gcc编译的结果

C语言程序代码的编译和运行过程如下图所示:
在这里插入图片描述
补充说明: 在学习的时候大家只需要掌握基本的程序设计步骤即可,具体如何实现编译和代码转换等操作则不需要深究(如果有兴趣可以进行深入的学习)。

1.2 C语言的应用领域有哪些?

问题描述:C语言被称为是使用最广泛的高级语言,那么C语言能够应用到哪些领域呢?

参考:因为C语言具有高级语言的特点,又具有汇编语言的特点,所以可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。因此,它的应用范围广泛,不仅仅是在软件开发上,而且各类科研都需要用到C语言。下面列举了C语言一些应用比较广泛的领域。

  1. 应用软件: LINUX操作系统中的应用软件都是使用C语言编写的,因为这样的应用软件安全性非常高。
  2. 对性能要求严格的领域: 一般对性能有严格要求的地方都是C语言编写的,比如网络程序的底层和网络服务器端底层,地图查询等。
  3. 系统软件和图形处理: C语言具有很强的绘图能力和移植性,并且具备很强的数据处理能力,因此适用编写系统软件,动画、二维图形和三维图形。
  4. 数字计算: 相对于其它编程语言,C语言是数值计算能力超强的高级语言。
  5. 嵌入式设备开发: 手机、PDA等时尚消费类电子产品相信大家都不陌生,其内部的应用软件、游戏等很多都是应用C语言进行嵌入式开发。
  6. 游戏软件开发: 游戏大家更不陌生,很多人是因玩游戏而熟悉了计算机,C语言可以做很多游戏,比如GBA、推箱子、贪吃蛇等。

ps:上面仅列出了几个主要的C语言应用领域,实际上C语言几乎可以应用到程序开发的任何领域。

二、上机题

2.1 第一个C语言程序

输出 hello,world~ 是大多数初学者运行调试的第一个程序,可以说输出 hello,world~ 是C语言最为简单的程序,实例运行效果如下图所示:
在这里插入图片描述
程序主要代码如下:

/*================================================================
*   Copyright (C) 2023 AmoXiang All rights reserved.
*   
*   文件名称:hello_world.c
*   创 建 者:AmoXiang
*   创建日期:2023年09月22日 19:06:02
*   描    述:第一个C语言程序
*
================================================================*/


#include <stdio.h>
int main(){
    printf("hello,world~\n");
    return 0;
}           

2.2 一个完整的C语言程序

使用程序求出 10+20 的结果,并将程序求出的结果进行输出,运行效果如下图所示:
在这里插入图片描述
程序主要代码如下:

/*================================================================
*   Copyright (C) 2023 AmoXiang All rights reserved.
*   
*   文件名称:get_sum.c
*   创 建 者:AmoXiang
*   创建日期:2023年09月22日 19:14:55
*   描    述:
*
================================================================*/


#include <stdio.h>
int main(){
    int i,j,sum = 0;
    i = 10;
    j = 20;
    sum = i + j;//求和
    printf("10+20=%d\n", i+j);
    return 0;    
}

2.3 输出名言

是否能够成为真正编程高手,主要在于是否有毅力坚持学习和练习。输出名言 贵有恒,何必三更起五更睡;最无益,只怕一日曝十日寒. 运行效果如下图所示:
在这里插入图片描述
程序主要代码如下:

/*================================================================
*   Copyright (C) 2023 AmoXiang All rights reserved.
*   
*   文件名称:print_saying.c
*   创 建 者:AmoXiang
*   创建日期:2023年09月22日 19:30:18
*   描    述:控制台输出名言警句
*
================================================================*/


#include <stdio.h>
int main(){
    printf("贵有恒,何必三更起五更睡;最无益,只怕一日曝十日寒.\n");
    return 0;    
}

2.4 计算出正方形的周长

已知正方形的边长为4,根据已知的条件计算出正方形的周长,并将其输出, 运行效果如下图所示:
在这里插入图片描述
程序主要代码如下:

/*================================================================
*   Copyright (C) 2023 AmoXiang All rights reserved.
*   
*   文件名称:get_perimeter.c
*   创 建 者:AmoXiang
*   创建日期:2023年09月22日 19:36:28
*   描    述:求正方形的周长
*
================================================================*/


#include <stdio.h>
int main(){
    int length_of_side,perimeter = 0;
    length_of_side = 4;
    //程序中的运算符与日常生活中运算符大致相同,但是有些日常生活中的运算公式并不能应用于程序之中
    //错误写法 ==> 4length_of_side
    perimeter = length_of_side * 4;
    printf("边长为%d的正方形,周长为:%d\n", length_of_side, perimeter);
    return 0;    
}

至此今天的学习就到此结束了,笔者在这里声明,笔者写文章只是为了学习交流,以及让更多学习C语言的读者少走一些弯路,节省时间,并不用做其他用途,如有侵权,联系博主删除即可。感谢您阅读本篇博文,希望本文能成为您编程路上的领航者。祝您阅读愉快!


在这里插入图片描述

    好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
    如果我的博客对你有帮助、如果你喜欢我的博客内容,请 点赞评论收藏 一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
 编码不易,大家的支持就是我坚持下去的动力。点赞后不要忘了 关注 我哦!

#include <reg51.h> #define uchar unsigned char #define SNAKE 20 //最大长度 #define TIME 50 //显示延时时间 #define SPEED 71 //速度控制 //#define keyenable 1 sbit keyenable=P3^6; //方向使能 /*sbit keyx=P0^1; //左右 sbit keyy=P0^2; //上下 */ //sbit up=P0^0; sbit up=P3^3; //down sbit down=P3^1; sbit right=P3^2; sbit left=P3^4; uchar x[SNAKE+1]; uchar y[SNAKE+1]; uchar time,n,i,e; //延时时间,当前蛇长,通用循环变量,当前速度 char addx,addy; //位移偏移量 /******************** 延时程序 *********************/ void delay(char MS) { char us,usn; while(MS!=0) { usn = 0; while(usn!=0) { us=0xff; while (us!=0){us--;}; usn--; } MS--; } } /******************************************* 判断碰撞 *******************************************/ bit knock() {bit k; k=0; if(x[1]>7||y[1]>7)k=1; //撞墙 for(i=2;i<n;i++)if((x[1]==x[i])&(y[1]==y[i]))k=1; //撞自己 return k; } /***************** 上下左右键位处理 *****************/ void turnkey()// interrupt 0 using 2 {//up=1; if(keyenable) { if(left){addy=0;if(addx!=1)addx=-1; else addx=1;} if(right){addy=0;if(addx!=-1)addx=1; else addx=-1;} if(up){addx=0;if(addy!=-1)addy=1; else addy=-1;} if(down){addx=0;if(addy!=1)addy=-1; else addy=1;} /*if(keyy) {addy=0; //左右 if(keyx)if(addx==-1)addx=-1; else addx=1; //左 else if(addx==1)addx=1; else addx=-1; //右 } else {addx=0; //上下 if(keyx)if(addy==1)addy=1; else addy=-1; //下 else if(addy==-1)addy=-1; else addy=1; //上 } */ } } /***************** 乘方程序 *****************/ uchar mux(uchar temp) { if(temp==7)return 128; if(temp==6)return 64; if(temp==5)return 32; if(temp==4)return 16; if(temp==3)return 8; if(temp==2)return 4; if(temp==1)return 2; if(temp==0)return 1; return 0; } /***************** 显示时钟 显示程序 *****************/ void timer0(uchar k) {while(k--) {for(i=0;i<SNAKE+1;i++) {P2=mux(x[i]);P1=255-mux(y[i]); turnkey(); //上下左右键位处理 delay(TIME); //显示延迟 P2=0x00;P1=0xff; }} } /***************** 主程序 *****************/ void main(void) {e=SPEED; P0=0x00; P1=0xff; P2=0x00; P3=0x00; while(1) {//if(keyenable==1){P1=0x00;P2=0xff;}else{P1=0xff;P2=0x00;} for(i=3;i<SNAKE+1;i++)x[i]=100;for(i=3;i<SNAKE+1;i++)y[i]=100;//初始化 x[0]=4;y[0]=4; //果子 n=3; //蛇长 n=-1 x[1]=1;y[1]=0; //蛇头 x[2]=0;y[2]=0; //蛇尾1 addx=0;addy=0; //位移偏移 //k=1; while(1){if(keyenable)break;timer0(1);} while(1) {timer0(e); if(knock()){e=SPEED;break;} //判断碰撞 if((x[0]==x[1]+addx)&(y[0]==y[1]+addy)) //是否吃东西 {n++; if(n==SNAKE+1) {n=3;e=e-10; for(i=3;i<SNAKE+1;i++)x[i]=100; for(i=3;i<SNAKE+1;i++)y[i]=100; } x[0]=x[n-2]; y[0]=y[n-2]; } for(i=n-1;i>1;i--){x[i]=x[i-1];y[i]=y[i-1];} //x[n-1]=x[2];y[n-1]=y[2]; x[1]=x[2]+addx;y[1]=y[2]+addy; //移动 } } } 给我转换下,这是个单片机贪吃蛇的程序
最新发布
05-19
以下是将你提供的C语言代码转换为51单片机汇编语言的版本,对每部分进行详细解释: --- ### 转换后的51单片机汇编代码 ```assembly ; 定义常量 SNAKE EQU 20 ; 最大蛇长 TIME EQU 50 ; 显示延时时间 SPEED EQU 71 ; 速度控制 ; 定义端口和位 sbit keyenable = P3^6 ; 方向使能 sbit up = P3^3 ; 上键 sbit down = P3^1 ; 下键 sbit right = P3^2 ; 右键 sbit left = P3^4 ; 左键 ; 数据段定义 DATA_SEG: x: DS SNAKE+1 ; 蛇的X坐标数组 y: DS SNAKE+1 ; 蛇的Y坐标数组 time: DS 1 ; 延时时间 n: DS 1 ; 当前蛇长 i: DS 1 ; 通用循环变量 e: DS 1 ; 当前速度 addx: DS 1 ; X轴位移偏移量 addy: DS 1 ; Y轴位移偏移量 ; 延时子程序 DELAY: MOV R6, #TIME ; 加载延时参数到R6 DELAY_LOOP: MOV R7, #255 ; 内层循环计数器 INNER_DELAY_LOOP: DJNZ R7, INNER_DELAY_LOOP ; 减少R7,直到为0 DJNZ R6, DELAY_LOOP ; 减少R6,直到为0 RET ; 返回主程序 ; 碰撞检测子程序 KNOCK: CLR C ; 清除进位标志 MOV A, x+1 ; 获取蛇头X坐标 CJNE A, #8, CHECK_Y ; 如果X坐标范围,设置碰撞标志 SETB C CHECK_Y: MOV A, y+1 ; 获取蛇头Y坐标 CJNE A, #8, CHECK_SELF ; 如果Y坐标范围,设置碰撞标志 SETB C CHECK_SELF: MOV R0, #2 ; 初始化循环计数器 CHECK_SELF_LOOP: MOV A, x+1 ; 获取蛇头X坐标 SUBB A, x+R0 ; 比较蛇头与身体坐标 JNZ NEXT_CHECK ; 如果不同,跳过 MOV A, y+1 ; 获取蛇头Y坐标 SUBB A, y+R0 ; 比较蛇头与身体坐标 JZ COLLISION ; 如果相同,触发碰撞 NEXT_CHECK: INC R0 ; 增加计数器 CJNE R0, n, CHECK_SELF_LOOP ; 循环直到检查完所有身体 CLR C ; 如果没有碰撞,清除标志 RET COLLISION: SETB C ; 设置碰撞标志 RET ; 键盘处理子程序 TURNKEY: JB keyenable, TURNKEY_END ; 如果方向使能关闭,直接返回 JB left, LEFT_KEY ; 检测左键 JB right, RIGHT_KEY ; 检测右键 JB up, UP_KEY ; 检测上键 JB down, DOWN_KEY ; 检测下键 SJMP TURNKEY_END ; 如果没有按键,结束 LEFT_KEY: MOV addy, #0 ; 设置Y轴位移为0 MOV A, addx ; 检查当前X轴位移是否为1 CJNE A, #1, SET_LEFT ; 如果不是1,则设置为-1 MOV addx, #1 ; 否则保持为1 SJMP TURNKEY_END SET_LEFT: MOV addx, #-1 ; 设置X轴位移为-1 SJMP TURNKEY_END RIGHT_KEY: MOV addy, #0 ; 设置Y轴位移为0 MOV A, addx ; 检查当前X轴位移是否为-1 CJNE A, #-1, SET_RIGHT ; 如果不是-1,则设置为1 MOV addx, #-1 ; 否则保持为-1 SJMP TURNKEY_END SET_RIGHT: MOV addx, #1 ; 设置X轴位移为1 SJMP TURNKEY_END UP_KEY: MOV addx, #0 ; 设置X轴位移为0 MOV A, addy ; 检查当前Y轴位移是否为-1 CJNE A, #-1, SET_UP ; 如果不是-1,则设置为1 MOV addy, #1 ; 否则保持为1 SJMP TURNKEY_END SET_UP: MOV addy, #1 ; 设置Y轴位移为1 SJMP TURNKEY_END DOWN_KEY: MOV addx, #0 ; 设置X轴位移为0 MOV A, addy ; 检查当前Y轴位移是否为1 CJNE A, #1, SET_DOWN ; 如果不是1,则设置为-1 MOV addy, #-1 ; 否则保持为-1 SJMP TURNKEY_END SET_DOWN: MOV addy, #-1 ; 设置Y轴位移为-1 TURNKEY_END: RET ; 返回主程序 ; 显示子程序 TIMER0: MOV R0, e ; 加载显示次数到R0 DISPLAY_LOOP: MOV R1, #SNAKE+1 ; 初始化循环计数器 DRAW_LOOP: MOV A, x+R1 ; 获取X坐标 CALL MUX ; 调用乘方函数计算显示值 MOV P2, A ; 输出到P2端口 MOV A, y+R1 ; 获取Y坐标 CALL MUX ; 调用乘方函数计算显示值 CPL A ; 取反 MOV P1, A ; 输出到P1端口 ACALL TURNKEY ; 处理按键 ACALL DELAY ; 延时 MOV P2, #0 ; 清空P2端口 MOV P1, #0FFH ; 清空P1端口 DJNZ R1, DRAW_LOOP ; 继续绘制下节 DJNZ R0, DISPLAY_LOOP ; 继续显示下帧 RET ; 乘方子程序 MUX: MOV R2, A ; 保存输入值 CLR A ; 清零累加器 CJNE R2, #7, MUX_6 ; 如果输入为7,返回128 MOV A, #128 SJMP MUX_END MUX_6: CJNE R2, #6, MUX_5 ; 如果输入为6,返回64 MOV A, #64 SJMP MUX_END MUX_5: CJNE R2, #5, MUX_4 ; 如果输入为5,返回32 MOV A, #32 SJMP MUX_END MUX_4: CJNE R2, #4, MUX_3 ; 如果输入为4,返回16 MOV A, #16 SJMP MUX_END MUX_3: CJNE R2, #3, MUX_2 ; 如果输入为3,返回8 MOV A, #8 SJMP MUX_END MUX_2: CJNE R2, #2, MUX_1 ; 如果输入为2,返回4 MOV A, #4 SJMP MUX_END MUX_1: CJNE R2, #1, MUX_0 ; 如果输入为1,返回2 MOV A, #2 SJMP MUX_END MUX_0: CJNE R2, #0, MUX_END ; 如果输入为0,返回1 MOV A, #1 MUX_END: RET ; 主程序 MAIN: MOV SP, #7FH ; 初始化堆栈指针 MOV P0, #0 ; 配置P0端口 MOV P1, #0FFH ; 配置P1端口 MOV P2, #0 ; 配置P2端口 MOV P3, #0 ; 配置P3端口 MOV R0, #3 ; 初始化蛇长 MOV n, R0 MOV x+0, #4 ; 初始化果子位置 MOV y+0, #4 MOV x+1, #1 ; 初始化蛇头位置 MOV y+1, #0 MOV x+2, #0 ; 初始化蛇尾位置 MOV y+2, #0 MOV addx, #0 ; 初始化位移偏移量 MOV addy, #0 MOV e, #SPEED ; 初始化速度 MAIN_LOOP: MOV R0, #SNAKE+1 ; 初始化循环计数器 INIT_SNAKE: MOV x+R0, #100 ; 初始化蛇的身体坐标为无效值 MOV y+R0, #100 DJNZ R0, INIT_SNAKE ; 循环初始化 ACALL TIMER0 ; 调用显示子程序 ACALL KNOCK ; 调用碰撞检测子程序 JC GAME_OVER ; 如果发生碰撞,跳转到游戏结束 MOV A, x+0 ; 检查是否吃到果子 ADD A, addx ; 计算新的X坐标 MOV B, y+0 ADD B, addy ; 计算新的Y坐标 CJNE A, x+1, NOT_EATEN ; 如果新坐标不等于果子坐标,跳过 CJNE B, y+1, NOT_EATEN INC n ; 吃到果子,增加蛇长 CJNE n, #SNAKE+1, NOT_MAX ; 如果蛇长未达到最大,跳过 MOV n, #3 ; 重置蛇长 DEC e ; 增加速度 MOV R0, #SNAKE+1 ; 重置蛇的身体坐标 RESET_SNAKE: MOV x+R0, #100 MOV y+R0, #100 DJNZ R0, RESET_SNAKE NOT_MAX: MOV A, x+n-2 ; 更新果子位置 MOV x+0, A MOV A, y+n-2 MOV y+0, A NOT_EATEN: MOV R0, n-1 ; 移动蛇的身体 MOVE_SNAKE: MOV A, x+R0-1 ; 将前节坐标赋值给当前节 MOV x+R0, A MOV A, y+R0-1 MOV y+R0, A DJNZ R0, MOVE_SNAKE MOV A, x+2 ; 移动蛇头 ADD A, addx ; 根据位移偏移量更新坐标 MOV x+1, A MOV A, y+2 ADD A, addy MOV y+1, A SJMP MAIN_LOOP ; 跳回主循环 GAME_OVER: SJMP $ ; 进入死循环 END ``` --- ### 解释 1. **延时子程序 `DELAY`**: - 使用嵌套循环实现延时功能。 - 外层循环由 `R6` 控制,内层循环由 `R7` 控制。 2. **碰撞检测子程序 `KNOCK`**: - 检查蛇头是否边界(X或Y大于7)。 - 检查蛇头是否与自身身体坐标重合。 3. **键盘处理子程序 `TURNKEY`**: - 检测上下左右键的状态。 - 根据按键状态更新 `addx` 和 `addy` 的值。 4. **显示子程序 `TIMER0`**: - 遍历蛇的所有节将其绘制到屏幕上。 - 调用 `MUX` 子程序计算显示值。 5. **乘方子程序 `MUX`**: - 根据输入值返回对应的乘方结果。 6. **主程序 `MAIN`**: - 初始化堆栈指针、端口配置以及蛇的相关数据。 - 在主循环中依次调用显示、碰撞检测、吃果子逻辑、移动蛇等功能模块。 --- ###
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

棒棒编程修炼场

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值