C-EASY-1:C语言入门
C语言方向提交总述:
- 对于每一个题目,你需要提交包含:
- 一份回答该小节问题的文字说明文件,要求使用Markdown语言进行排版
- 题目中要求提供的可执行程序或代码文件
- 每一题请提交对应的github的url链接。
part1_了解C语言配置文件
Section titled “part1_了解C语言配置文件”在第一节C语言课程时,你的老师会要求你配置C语言环境。按照要求完成环境配置以后,你是否会有疑问,每一步的作用是什么?当编译环境配置好后,编译器中的三个配置文件的作用是什么?应该怎么调试?
现在我们一步一步来看:
-
什么是GCC,什么是MinGW?它的作用是什么?
-
c_cpp_properties.json launch.json tasks.json这三个文件分别有什么作用?
-
为什么要在编译器内下载C语言的插件,插件的作用又是什么?
应该指出,在后续的代码编写过程中,最常更改的就是launch.json,比如是否要有外置控制台,或者使用内置终端。
那么launch.json中的配置都是什么意思?
{ // 使⽤ IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "gcc.exe - ⽣成和调试活动⽂件", // 该调试任务的名字,启动调试时会在待选列表中显⽰ "type": "cppdbg", "request": "launch", "program": "${fileDirname}\\${fileBasenameNoExtension}.exe", "args": [], "stopAtEntry": false, // "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, // "MIMode": "gdb", "miDebuggerPath": "C:\\mingw64\\bin\\gdb.exe", // "setupCommands": [ { "description": "为 gdb 启⽤整⻬打印", "text": "-enable-pretty-printing", "ignoreFailures": true } ], "preLaunchTask": "C/C++: gcc.exe build active file" // 调试前的预执⾏任务,这⾥的值是tasks.json⽂件中对应的编译任务,也就是调试前需要先编译 } ]}这是一个launch.json的文件,请你补全上面的注释,并尝试更改你自己的设置,然后用外置终端和内置终端分别打印“hello world”并上传你输出结果的截图。
part2_C语言基础
Section titled “part2_C语言基础”C语言是大多数人学习的第一门计算机语言。我知道很多同学在上大学以前都没有接触过编程,接下来的招新题目都需要使用C语言进行,要求你至少要基本掌握C语言语法。所以我建议你,不要急于完成接下来我给出的题目,而是去找一个完整的网课或者一部详细的电子书,系统的学习并入门C语言,(这里我推荐黑马程序员和翁凯的课程)。我们的招新只有一轮,会一直持续到期中考试前两周才会截止,因此你完全可以拿出一两周的时间先学习C语言再进行更深入的招新题的学习。并且,我希望你在学习第一门语言的过程中,先不要打开AI的代码补全功能,这会很大的降低你的代码熟练度。希望你可以合理的使用AI。
我们刚刚完成了一个打印“hello world”的简单程序,可是如果我们想进行一定的更改(比如打印不同的内容),都要直接修改源代码。通过搜索引擎,你得知这样不仅太过繁琐,而且不利于我们对程序进行测试,在实际应用中也几乎不可行。所以你打算对程序进行一定的改写,使之可以实现动态交互。于是你打算进一步学习变量、数组、流程控制 - 循环结构、流程控制 - 逻辑表达式等知识。
- 变量类型: 什么是变量的类型?它为什么重要?如果你想存放你的年龄(比如 18),应该选择哪种基本变量类型(如整数、浮点数)?如果你想存放单词 “apple”,使用一个char类型的字符变量能实现吗?尝试编程验证你的想法,并思考正确的存储方式应该是什么?
- 数组的起始与边界: 数组的第一个元素下标通常是从 0 还是 1 开始?访问数组元素时,下标超出其有效范围(例如,长度为 5 的数组访问 arr[5] 或 arr[-1])会导致什么问题?为什么数组越界是一个常见的、危险的错误?
- 流程控制 - 循环结构: 循环结构(如 for, while)是如何控制代码块重复执行的?请分别简述它们的基本结构。for 循环的初始化、条件判断和迭代部分各自的作用是什么?while 循环和 do…while 循环在首次执行条件判断上有何关键区别?尝试用两种不同的循环结构实现同一个任务(例如,计算 1 到 10 的和),体会它们的异同。
- 流程控制 - 逻辑表达式:在条件判断(如 if, else if)和循环条件中使用的逻辑表达式(如age > 18 && score >= 60)与算术表达式(如a + b * c)有何本质区别(尝试从运算对象和运算结果分析)?运算逻辑符&&,||,!的含义分别是什么?尝试编写包含多个条件的逻辑表达式并预测其输出结果。
你恍然大悟,尝试对程序进行了修改,以期可以实现如下功能:
-
设置合适的变量用于存储输入的姓名与年龄。
-
利用设置的变量,以原格式打印姓名与年龄。
-
在每一次的读取输入->打印内容结束后,记录进行过读取输入->打印内容操作的次数,打印提示询问用户是否继续输入。
-
若判断得到用户需要继续输入,则重复之前的读取输入->打印内容操作。
-
若判断得到用户不需要继续,则打印记录的进行的读取输入->打印内容操作次数,然后结束程序。
part3_函数
Section titled “part3_函数”在程序设计中,设置函数的核心目的有两点:代码复用和逻辑组织
代码复用是指通过抽象化特定功能模块为独立单元,实现算法逻辑的”一次定义,多次调用”,从而消除冗余代码并确保功能一致性。简单来说,就是把常用的操作打包成工具,随用随取。
逻辑组织是指通过函数边界建立抽象层次结构,将复杂系统分解为高内聚、低耦合的功能模块,实现认知负荷的有效管理。简单来说,就是把代码按功能分装进盒子(函数),便于后续查找、维护和修改。
关于什么是函数,我相信你已经有所了解了,在日后的编程中,我们通常不会在主函数中写大段的语句,而是在主函数中调用自己设定的函数,以实现各种功能。包括实际项目当中,也是如此。在这一题当中,你需要学会如何定义一个简单的函数减少代码复用。
下面我们设置一个情景,方便你更好地了解。
小明、小强、小林是某人三项(共有A、B、C三项)的业余爱好者,某次,三人一同参加了某人三项的趣味赛,成绩如下(满分100):
小明:77 85 91
小强:82 84 84
小林:72 83 100
请你通过平均分和方差的计算,综合考虑后,为三人综合成绩由高到低排序(成绩相等时,对顺序不做要求)。综合考虑的具体方法为:综合成绩 = 3 * 平均分 - 方差 / 3;
下面给出仅由一个main()函数完成的程序:
#include <stdio.h>
int main(){ int x1, x2, x3; int y1, y2, y3; int z1, z2, z3;
printf("请输入小明的三项成绩(顺序为A B C,以一个空格为间隔):"); scanf("%d %d %d", &x1, &x2, &x3); printf("请输入小强的三项成绩(顺序为A B C,以一个空格为间隔):"); scanf("%d %d %d", &y1, &y2, &y3); printf("请输入小林的三项成绩(顺序为A B C,以一个空格为间隔):"); scanf("%d %d %d", &z1, &z2, &z3);
int p1 = (x1 + x2 + x3) / 3; int f1 = ((p1 - x1) * (p1 - x1) + (p1 - x2) * (p1 - x2) + (p1 - x3) * (p1 - x3)) / 3; int zh1 = 3 * p1 - f1 / 3;
int p2 = (y1 + y2 + y3) / 3; int f2 = ((p2 - y1) * (p2 - y1) + (p2 - y2) * (p2 - y2) + (p2 - y3) * (p2 - y3)) / 3; int zh2 = 3 * p2 - f2 / 3;
int p3 = (z1 + z2 + z3) / 3; int f3 = ((p3 - z1) * (p3 - z1) + (p3 - z2) * (p3 - z2) + (p3 - z3) * (p3 - z3)) / 3; int zh3 = 3 * p3 - f3 / 3;
if (zh1 >= zh2 && zh2 >= zh3) { printf("小明 > 小强 > 小林"); } else if (zh1 >= zh3 && zh3 >= zh2) { printf("小明 > 小林 > 小强"); } else if (zh2 >= zh1 && zh1 >= zh3) { printf("小强 > 小明 > 小林"); } else if (zh2 >= zh3 && zh3 >= zh1) { printf("小强 > 小林 > 小明"); } else if (zh3 >= zh1 && zh1 >= zh2) { printf("小林 > 小明 > 小强"); } else { // zh3 >= zh2 && zh2 >= zh1 printf("小林 > 小强 > 小明"); }
return 0;}相信你可以看出,在这其中,计算综合成绩(zh)时,代码的重复性非常高;于此同时,输入、计算、排序全过程都在一个函数中完成,不免使得程序看起来过于臃肿。下面,请你参考开始给出的将a + b封装成函数int add(int a, int b)的示例,尝试利用自定义函数将main()函数的下列内容精简:
-
利用自定义函数,实现乘方的计算(用于方差的计算)。(代码复用)
-
利用自定义函数,将三人的综合成绩计算的过程进行封装。(代码复用)
-
将综合成绩的排序,利用自定义函数进行封装。(逻辑组织)
上传更改后的整个程序的代码。
相信通过这个例子, 你对自定义函数应该有了初步的、大致的了解。我们通常称函数定义中声明的参数为形参(如:int add(int a, int b)中的int a和int b),函数调用时传入的参数为实参(如:main函数中的add(a,b)中的a和b)。默认情况下,实参的值会复制给形参,这时会分为两种情况:值传递和引用传递。下面请你进一步学习其相关知识,最好可以了解一下这方面的易错点。然后,尝试回答下面的问题:
-
猜猜下列函数的效果(你可以自行运行,看看结果怎么样),尝试从值传递的角度入手,说说为什么会这样
void swap(int a, int b){int temp = a;a = b;b = temp;}int main(){int a = 10;int b = 20;swap(a, b);} -
怎么修改函数才能真正实现值交换的效果呢?请你初步了解指针。我们会在下一个题中系统学习指针和初步的数据结构。
本题提交方式
Section titled “本题提交方式”出题人联系方式
Section titled “出题人联系方式”出题人:
taaaakoooo
QQ:1748798371
