考研408之C语言入门
考研408之C语言入门
前言
这篇文章是我决定考研后写下的C
语言基础学习记录,因为在此之前我有过Java
项目开发的相关经验,对基础语言的学习也有一些心得,所以学习C
语言时也只是快速过一下语法重点,并进行记录总结。这里只是第一次学习C
语言基础进行的知识总结,未涉及到刷题后总结,后续刷题后如果觉得有总结的必要,也会在我的博客园中进行发布,读者可以关注了解,一起交流学习,祝成功上岸!
补充:因为我没有考研经验,只管闷头学习,不论成败,所以这篇文章是否适用读者阅读,还请自行甄别。
该文章笔记大量引用了尚硅谷宋红康老师的课程笔记,并进行了个人总结。如果你没有语言学习经验,建议跟着教学视频学习。
学习视频地址:尚硅谷C语言零基础入门教程(宋红康c语言程序设计精讲,含C语言考研真题)
视频配套资料:
百度网盘:https://pan.baidu.com/s/1Sy-dVuBjEWY4dwl5tnW4-w?pwd=yyds 提取码:yyds
阿里云盘(教程配套资料请从百度网盘下载):https://www.aliyundrive.com/s/MmTrj8vkoGR
目录
1. C语言的版本选择
随着微型计算机的日益普及,出现了许多C语言版本。有K&R C
、ANSI C(又称 C89 或 C90)
、C99
、C11
、C17
、C23
等等。C99
是目前最流行的版本。
引用:C语言标准的第一次大型修订,发生在1999年,增加了许多语言特性,比如双斜杠(//)的注释语法,可变长度数组、灵活的数组成员、复数、内联函数和指定的初始值设定项。这个版本称为C99,是目前最流行的C版本 。
2. C语言运行环境准备
这里在老师课程中介绍了很多种方式方法,其实如果不是进行项目开发等,只是用于学习C
语言基础语法知识,个人建议也无需下载安装什么编译运行环境,直接使用线上的C
语言编译器即可;以下是宋红康老师的推荐。
CodingGround: https://tutorialspoint.com/compile_c_online.php
OnlineGDB: https://onlinegdb.com/online_c_compiler
Lightly:https://lightly.teamcode.com/
(我个人比较常用,界面风格和我之前做Java
项目使用的IDEA
很像)
3. 第一个C程序的编写->编译->运行
第一步:线上登录Lightly
第二步:新建C项目,填写如下信息,等待创建完成。
第三步:运行代码
补充:如果你的项目没有自带main.c
文件,自己在对应位置建一个。粘贴如下代码即可;
引用:C
语言的源代码文件,以后缀名.c
结尾。下面是一个简单的C
程序 Hello.c
。
#include <stdio.h>
int main()
{
printf("hello,world!!\n");
return 0;
}
第四步:查看运行结果
4. C程序运行机制
过程1:编辑
编写C
语言源程序代码,并以文件的形式存储到磁盘中。源程序文件以“.c
”作为扩展名。
过程2:编译
将C
语言源程序转换为目标程序(或目标文件)
。如果程序没有错误,没有任何提示,就会生成一个扩展名为“.obj
”的二进制文件。C
语言中的每条可执行语句经过编译后最终都将被转换成二进制的机器指令。
过程3:链接/连接
将编译形成的目标文件“.obj”
和库函数及其他目录文件连接/链接,形成统一的可执行的
二进制文件“.exe
”。
为什么需要链接库文件呢?
因为我们的
C
程序中会使用C
程序库的内容,比如<stdio.h>
、<stdlib.h>
中的函数printf()
、system()
等,这些函数不是程序员自己写的,而是C
程序库中提供的,因此需要链接。链接后,生成的.exe
文件,比obj
文件大了很多。
过程4:运行
有了可执行的exe
文件,我们可以在控制台下直接运行此exe
文件。
注意:
对修改后的x
xx.c
源文件需要重新编译、链接,生成新的exe
文件后,再执行,才能生效。
补充说明:
为什么上述的Hello World
案例中我们没有看到上面所说的相关文件生成呢?其实只不过是我们用的线上C
语言编译运行工具,这些文件的细节都被隐藏了,让我们只关心源程序的编写,然后点击运行即可将后续编译、运行等操作一并做了。
如果你想了解具体细节演示,宋红康老师教程视频里有进行实验演示。
练习:
计算机高级语言程序的运行方法有编译执行和解释执行两种,以下叙述中正确的是( )。
A.C语言程序仅可以编译执行
B.C语言程序仅可以解释执行
C.C语言程序既可以编译执行,又可以解释执行
D.以上说法都不对【答案】A
【解析】编译执行是指程序执行前需要一个专门的编译过程把程序编译成机器语言的文件,再次运行时不需要重新翻译,执行效率高;解释执行是指每个语句都是执行的时候才翻译,执行效率低。用C语言编写的程序必须经过编译器编译后,转换为二进制的机器指令来运行。
练习:
以下叙述中错误的是( )。
A.C语言的可执行程序是由一系列机器指令构成的
B.用C语言编写的源程序不能直接在计算机上运行
C.通过编译得到的二进制目标程序需要链接才可以运行
D.在没有安装C语言集成开发环境的机器上不能运行C源程序生成的exe文件【答案】D
【解析】A项正确,C语言的可执行程序是由一系列机器指令组成的;BC项正确,用C语言编写的源程序必须经过编译,生成二进制目标代码,再经过连接才能运行;D项错误,C语言经过编译链接后的二进制目标代码可以脱离C语言集成开发环境独立运行。答案选择D选项。
5. C语言注释
-
什么是注释?
- 源文件中用于
解释
、说明
程序的文字就是注释。 - 注释只是给人看的,程序执行时,
编译器会忽略注释
,注释对代码执行没有影响
- 源文件中用于
-
注释是一个程序员必须要具有的良好编程习惯。实际开发中,程序员可以先将自己的
思想
通过注释整理出来,再用代码
去体现。 -
C语言中的注释类型:
- 单行注释
// 单行注释
- 多行注释(或块注释)
/* 这是第一行注释 这是第二行注释 这是第三行注释 */
-
举例
- 举例1
#include <stdio.h> // 这是编译预处理指令 int main() // 定义主函数 { // 函数开始的标志 printf("Hello World\n"); // 输出所指定的一行信息 return 0; // 函数执行完毕时返回函数值0 } // 函数结束的标志
- 举例2
printf("1"); /* 多行注释举例 printf("2"); printf("3"); */ printf("4");
- 举例4
int open(char* s /* 行内使用注释举例:file name */, int mode);
-
注意:
-
多行注释不能嵌套使用
/* 我是注释信息1 /* 我是注释信息2 */ 我是注释信息3 */
-
双引号内使用注释,会被当做普通字符串看待,失去注释作用
printf("// hello /* atguigu */ ");
-
练习:
以下叙述中错误的是( )。
A.C语言中的每条可执行语句和非执行语句最终都将被转换成二进制的机器指令
B.C程序经过编译、链接步骤之后才能形成一个真正可执行的二进制机器指令文件
C.用C语言编写的程序称为源程序,它以ASCII代码形式存放在一个文本文件中
D.C语言源程序经编译后生成后缀为.obj的目标程序【答案】A
【解析】A项错误,注释语句不会被翻译成二进制的机器指令。C源程序经过C编译程序编译之后生成后缀为.obj的二进制文件(称为目标文件),然后由“链接程序”(Link)的软件把.obj文件与各种库函数连接起来生成一个后缀为.exe的可执行文件。答案选择A选项。
6. HelloWorld的剖析
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
6.1 规范的代码风格
正确的缩进和空白
-
使用一次
tab
操作,实现缩进,默认整体向右边移动。相反,使用shift+tab整体向左移 -
运算符两边习惯性各加一个空格。比如:
2 + 4 * 5
。
代码块的风格
1)行尾风格(我个人习惯这种风格,因为Java
开发中我使用这种风格)
int main() {
if(a > b) {
return a;
}
else{
return b;
}
return 0;
}
2)次行风格
int main()
{
if(a > b)
{
return a;
}
else
{
return b;
}
return 0;
}
正确的注释和注释风格:
1)如果注释一个函数,可以使用多行注释(或块注释)。
2)如果注释函数中的某一行语句,可以使用单行注释。
6.2 代码细节剖析
① main()
int main(){}
- 每一个程序(或工程)可以定义很多函数(后面讲),但有且只有一个
main()
函数,作为程序执行的入口,在main()
函数结尾结束整个程序的运行。 - 空括号
()
,表示main
不接受任何参数。 - 写在
main
之前的“int”
称为关键字,代表数据类型是整型。它是main()
的返回值类型。即在执行main()
函数后会得到一个整型值(即函数值)。 C
语言约定:return 0
,表示main()
函数终止运行,且运行成功;如果返回其它非零整数,就表示运行失败。默认情况下,如果main()
里面省略return 0
这一行,编译器会自动加上,但是为了保持统一的代码风格,不建议省略。
② 函数体
-
一对花括号
{}
定义了函数的主体,所有函数都必须以大括号开头和结尾,成对出现。 -
C
程序中的函数体指的是作为该函数一部分的语句。它可以是任何操作,比如搜索、排序、打印等。 -
每一个执行语句后面都会有一个英文分号
“;”
作为语句结束的标志。 -
一行内可写几条语句,一条语句也可写在几行上。
③ printf()
printf()函数是产生格式化输出的函数,作用是将参数文本输出到屏幕。它名字里面的f
代表format
(格式化),表示可以指定输出文本的格式。
printf("Hello World"); // 将字符串输出到控制台,行尾不换行
为了让光标移到下一行的开头,可以在输出文本的结尾,添加一个换行符 \n
。
printf("Hello World\n");
④ 标准库、头文件
printf()
是在标准库的头文件 stdio.h
中定义的。要想在程序中使用这个函数,必须在源文件头部引入这个头文件。即:
(相等于Java
中的导包)
#include <stdio.h>
何为标准库?
程序需要用到的功能,不一定需要自己编写,C
语言可能已经自带了。程序员只要去调用这些自带的功能就可以了。C
语言自带的所有这些功能,统称为“标准库”(standard library)
,包含C
内置函数、常量和头文件。
因为它们是写入标准的,到底包括哪些功能,应该怎么使用,都是规定好的,我们直接调用即可。
何为头文件?
不同的功能定义在不同的文件里,这些文件统称为“头文件”(header file)
。如果系统自带某一个功能,就一定会自带描述这个功能的头文件,比如printf()
的头文件就是系统自带的 stdio.h
。头文件的后缀通常是 .h
。
预处理命令:#include
命令
如果要使用某个功能,就必须先加载其对应的头文件,加载使用的是 #include
命令,声明在各文件模块的开头。C
语言中以#
号开头的命令称为预处理命令
。顾名思义,在编译器对当前C
程序进行编译前执行预处理操作。
格式:
#include <头文件名>
举例:
#include <stdio.h>
注意,加载头文件的
#include
语句不需要分号结尾
对比写法:
#include <stdio.h>: // 编译系统在系统头文件所在目录搜索
#include "stdio.h": // 编译系统首先在当前的源文件目录中查找 stdio.h,找不到的话,再转向系统头文件所在目录搜索。
stdio.h
是系统提供的一个文件名,stdio
是standard input & output
的缩写。
结论:
- 引用系统头文件,两种形式都会可以,
#include <>
效率高。
- 引用用户头文件,只能使用
#include ""
。
常用的C头文件
stdio.h
——定义核心输入和输出函数printf()
、scanf()
、getchar()
、putchar()
stdlib.h
——定义数值转换函数、伪随机网络生成器和内存分配string.h
——定义字符串处理函数stdint.h
——定义精确宽度的整数类型math.h
——定义常用的数学函数sin()
、sqrt()
stddef.h
——定义了几个有用的类型和宏
练习:
以下叙述中正确的是( )。
A.C程序中的注释只能出现在程序的开始位置和语句的后面
B.C程序书写格式严格,要求一行内只能写一个语句
C.C程序书写格式自由,一个语句可以写在多行上
D.用C语言编写的程序只能放在一个程序文件中【答案】C
【解析】C程序的注释可以出现在C程序的任何位置,注释符号:“//”或“/…/”,选项A错误。C程序中,一行内可写多个语句,每条语句用分号“;”结束,选项B错误,选项C正确。用C语言编写的程序可以放在多个程序文件中,用#include命令行实现文件包含功能,选项D错误。答案选择C选项。
练习:
【中央财经大学2018研】以下叙述错误的是( )。
A.在程序中凡是以“#”开始的语句行都是预处理命令行
B.预处理命令行的最后不能以分号表示结束
C.#include MAX是合法的宏定义命令行
D.C程序对预处理命令行的处理是在程序执行的过程中进行的【答案】D
【解析】在C语言中,凡是以“#”开头的行都称为编译预处理命令行,为了区别C语句,后面是不加分号的。编译预处理是在编译程序对C源程序进行编译前执行的,而不是在程序执行过程中进行的。
注意:
学习编程最容易犯的错是
语法错误
。C语言要求必须按照语法规则编写代码。如果你的程序违反了语法规则,例如:忘记了分号、大括号、引号 或者拼错了单词等,C编译器都会报语法错误。尝试着去看懂编译器会报告的错误信息
。
7. 关于printf()
7.1 printf()标准格式
printf(格式控制字符串,输出列表);
其中,
-
"格式控制字符串"
是用双引号括起来的一个字符串。包括:- 普通字符:普通字符即需要在输出时原样输出的字符。
- 占位符:由
“%”
和格式字符组成。这个位置可以用其它值代入。
-
"输出列表"
是程序需要输出的一些数据,可以是常量、变量或表达式。用于替换占位符的位置。
注意:
printf()
参数与占位符是一一对应关系。如果参数个数少于对应的占位符,printf()
可能会输出内存中的任意值。
7.2 占位符
占位符的第一个字符是 %
,第二个字符表示占位符的类型。
printf()
的占位符有许多种类,与C
语言的数据类型相对应。
下面按照字母顺序,列出占位符如下,方便查阅(红色为常用的):
%a :浮点数(仅C99有效)
%A :浮点数(仅C99有效)
%c :char型数据
%d :十进制整数(int)
%e :使用科学计数法的浮点数,指数部分的 e 为小写
%E :使用科学计数法的浮点数,指数部分的 E 为大写
%i :整数,基本等同于 %d
%f :浮点数(float)
%g :6个有效数字的浮点数。整数部分一旦超过6位,就会自动转为科学计数法,指数部分的 e 为小写
%G :等同于 %g ,唯一的区别是指数部分的 E 为大写
%hd :十进制 short int 类型
%ho :八进制 short int 类型
%hx :十六进制 short int 类型
%hu :unsigned short int 类型
%ld :十进制整数(long)
%lo :八进制 long int 类型
%lx :十六进制 long int 类型
%lu :unsigned long int 类型
%lld :十进制 long long int 类型
%llo :八进制 long long int 类型
%llx :十六进制 long long int 类型
%llu :unsigned long long int 类型
%le :科学计数法表示的 long double 类型浮点数
%lf :十进制浮点数(double)
%n :已输出的字符串数量。该占位符本身不输出,只将值存储在指定变量之中
%o :八进制整数
%p :指针
%s :字符串
%u :十进制无符号整数(unsigned int)
%x :十六进制整数
%zd : size_t 类型
%% :输出一个百分号
7.3 举例
举例1:%d
int num = 10;
printf("count is %d\n",num); //输出:count is 10
printf("There are %i students\n", 5); //输出:There are 5 students
举例2:%lf 和 %f
float f = 3.1415926535f; // 单精度浮点数
double d = 3.1415926535; // 双精度浮点数
// 使用 %f 输出单精度浮点数
printf("Float: %f\n", f); //Float: 3.141593
// 使用 %lf 输出双精度浮点数
printf("Double: %lf\n", d); //Double: 3.141593
// 使用 %f 输出单精度浮点数
printf("Float: %.8f\n", f); //Float: 3.14159274
// 使用 %lf 输出双精度浮点数
printf("Double: %.8lf\n", d); //Double: 3.14159265
举例3:%c
char level = 'A';
printf("this score level is:%c\n",level); //输出:this score level is:A
举例4:%s
printf("%s是我最喜欢的冷门歌手.\n","孙燕姿"); //输出:孙燕姿是我最喜欢的冷门歌手.
举例5:多个占位符
输出文本里面可以使用多个占位符。
printf("%s有%d部手机\n", "老板", 2); //输出:老板有2部手机
7.4 输出格式
printf()
可以定制占位符的输出格式。
格式1:限定宽度
printf()
允许限定占位符的最小宽度。
printf("%5d\n", 123); // 输出为 " 123"
说明:%5d
表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。
输出的值默认是右对齐,即输出内容前面会有空格;如果希望改成左对齐,在输出内容后面添加空格,可以在占位符的 % 的后面插入一个 - 号。
printf("%-5d\n", 123); // 输出为 "123 "
对于小数,这个限定符会限制所有数字的最小显示宽度
printf("%12f\n", 123.45); // 输出 " 123.450000"
%12f
表示输出的浮点数最少要占据12位。由于小数的默认显示精度是小数点后6位,所以123.45 输出结果的头部会添加2个空格。
格式2:总是显示正负号
默认情况下,printf()
不对正数显示 + 号,只对负数显示 - 号。如果想让正数也输出 + 号,可以在占位符的 % 后面加一个 + 。
printf("%+d\n", 11); // 输出 +11
printf("%+d\n", -11); // 输出 -11
格式3:限定小数位数
输出小数时,有时希望限定小数的位数。举例来说,希望小数点后面只保留两位,占位符可以写成%.2f
。
printf("Number is %.2f\n", 0.8); // 输出 Number is 0.80
这种写法可以与限定宽度占位符,结合使用。
printf("%6.2f\n", 0.8); // 输出为 " 0.80"
说明:%6.2f
表示输出字符串最小宽度为6,小数位数为2。整体长度不足 6 位时,右对齐显示。
最小宽度和小数位数这两个限定值,都可以用 * 代替,通过printf()
的参数传入。
printf("%*.*f\n", 6, 2, 0.8);
//等同于
printf("%6.2f\n", 0.8);
【华南理工大学2018研】十六进制形式输出整数的格式说明符是( )。
A.%u
B.%ld
C.%x
D.%o【答案】C
【解析】A表示输出的是无符号整型;B表示输出的是有符号长整型;D表示输出的是八进制。