2023年信息科学与工程学院学生科协第一次软件培训
文章目录
- 2023年信息科学与工程学院学生科协第一次软件培训
- 运行第一个代码(“Hello World!”)
- 初识C语言代码的具体结构
- 头文件
- (主)函数
- 输入与输出
- scanf函数
- printf函数
- 转义字符
- 变量的定义
- 进一步了解数据类型
- 整形数据的存储
- 负数的存储
- 浮点型数据的存储
- 变量的初始化
- 变量的转换
- 赋值运算中的自动类型转换
- 强制类型转换
- 算术表达式
- 算术运算符
- 关于/与%更多的细节:
- 复合运算符
- 自增、自减运算符
- 位运算符
- 其他运算符
- 逻辑运算符
- 关系运算符
- 逻辑运算符
- 运算符之间的优先级
- 多个逻辑表达式
- 条件控制
- if 语句
- if-else 语句
- 多个 if-else 形成的多条件分支
- switch-case语句
- 循环控制
- while 语句
- do-while 语句
- for 语句
- 循环的嵌套
运行第一个代码(“Hello World!”)
首先,我们先看以下程序:
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
输出应该是这个样子:
Hello World!
显然,这个程序是可以成功运行的
那么,它为什么能成功运行呢?这就是我们接下来的第一个主题:
初识C语言代码的具体结构
简单来说,一个C程序就是由若干头文件和函数组成。
头文件
以上面的程序为例,下面这一行代码就是头文件。
#include <stdio.h>
你可以认为这就是一条预处理命令, 它的作用是通知C语言编译系统在对C程序进行正式编译之前需做一些预处理工作。有了头文件,你就可以在你写的C语言程序中调用其他文件定义的函数,即可以在该程序中使用其他文件写好的部分内容,列如 p r i n t f printf printf 和 s c a n f scanf scanf
ppt上已经给出常见的头文件和函数,以及查找相关函数的方法,这里就不过多赘述了
(主)函数
一个程序中,有且仅有一个主函数
主函数的函数名是main,也就是 “主要的” 的意思,主函数就是下面的:
int main()
{
// DoSomething
return 0;
}
如果不想在考试中得到一个非常好看的0分的话,主函数这个格式就按照我上面写的这样写就行 (先不谈什么void main()的抽象使用方式和return 0;要不要写,为何要写,如果感兴趣的话可以百度)
好的,主函数说完了,我们来说一下一般的函数。
在C语言程序中,函数的形式应该是这样的:
返回值类型 函数名(参数值) //这里的括号可不是对函数名的解释,这个括号是实打实需要写上的
{
// DoSomething
return 返回值;
}
我们一般用 f u n c t i o n function function这个词代表函数,所以我们下面就定义一个简单的函数:
int fun(int x)
{
x = x + 1;
return x;
}
然后我们执行这样的一个语句:
int a = fun(3);
显然,a的赋值是4。
(这里另外提一嘴,如果你要在一个函数中引用另一个函数的东西,请先确保该函数被声明)
比如:
#include <stdio.h>
int slove(int b)
{
b = 1 + fun(3);
return b;
}
int fun(int x)
{
x = x + 1;
return x;
}
int main()
{
int a = slove(5);
printf("%d",a);
return 0;
}
哦,这个程序好像比较复杂,正好,我们来学习一下C语言语句的运行顺序。
首先执行的是第一句的头文件,这是毋庸置疑的。
然后,先执行主函数中的那句话,
由于a的定义引用到了函数slove,所以我们要执行函数slove,该函数的传入的参数是5(也就是说此时的b = 5)
但是这不是主要的,因为我们的b又在后面被修改了,可以看到,b = 1 + fun(3)
此时,我们要引用fun(3),可是我们把这段代码在本地编译运行时可以发现这一行报错了!(为什么呢)
我们都知道一般来说C语言都是从上往下运行的,显然,slove前面并没有任何关于fun()函数的定义,所以在这个函数中,slove就没法引用fun函数,导致报错
那我们不妨换个写法:
#include <stdio.h>
int fun(int x)
{
x = x + 1;
return x;
}
int slove(int b)
{
b = 1 + fun(3);
return b;
}
int main()
{
int a = slove(5);
printf("%d",a);
return 0;
}
此时,我们能够得到如下输出
5
这样通过一个程序我们就完成了C语言的运行顺序以及函数的调用的基本学习
输入与输出
scanf函数
使用格式:
scanf("变量数据类型", &变量名);
作用:
获取若干个数据并赋值于指定的变量
使用:
#include <stdio.h>
int main()
{
int a, b;
scanf("%d %d", &a, &b);
printf("%d", a);
printf("%d", b);
return 0;
}
衷心提醒:
不要写成如下的输入方式,否则你会经历很多很多挫折。
scanf("%d,%d", &a, &b);//理论上这是正确的,但是逗号的输入很容易因为中英文的输入法出问题,所以别写
scanf("%d", a); //忘了加取地址符!
printf函数
使用格式:
printf("变量数据类型", 变量名);
使用:
使用:
#include <stdio.h>
int main()
{
int a;
scanf("%d", &a);
printf("%d", a);
return 0;
}
转义字符
转义字符有很多,也是因为直播中讲过,我们只挑两个来解释:
- \n,意义是换行,例如
printf("1\n2");
那么你的输出应该是:
1
2
- \0,意义是空字符,同时代表着字符串的结束,列如
printf("1234\0ABC");
你会得到如下的输出:
1234
变量的定义
格式:
变量的数据类型 变量的名称;
int a;
也可以一次定义多个变量
int a, b;
变量的命名规则:
1.可以用小写字母、大写字母、数字和下划线(即‘_’)来命名。
2.名称的第1个字符必须是字符或者下划线,不能是数字。
进一步了解数据类型
整形数据的存储
0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
---|
在数据的储存时,一个字节由八个二进制组成: ( 1 B y t e = 8 b i t ) (1 Byte = 8 bit) (1Byte=8bit)
有符号类型(signed):第一位为符号位,0表示正数,1表示负数,所以范围为 [ − 128 , 127 ] [-128,127] [−128,127]
无符号类型(unsigned):没有符号位,范围为 [ 0 , 255 ] [0,255] [0,255]
一个int占有4个字节,即 4 B y t e 4Byte 4Byte , 32 b i t 32bit 32bit。所以int的范围是
( − 2147483648 ~ 2147483647 ( − 2 31 ~ 2 31 − 1 ) ) (-2147483648~2147483647(-2^{31} ~ 2^{31}-1)) (−2147483648~2147483647(−231~231−1))
负数的存储
计算机只能做加法,不能做减法,减去一个数,等于加上一个负数。
在计算机中,负数以补码的形式存在
补码:
-
对原码除符号位以外取反(1变0,0变1)
-
加一
浮点型数据的存储
这不是必须了解的内容,大家只需要记住两种浮点型数据的精度范围就好了
- float 的精度是6~7位有效数字
- double的精度是15~16位有效数字
想了解原理的同学可以点这里浮点数的底层原理和精度损失问题
变量的初始化
有三种初始化变量的方法
- 在声明变量的同时指定初值
int a = 3, b = 2;
int c = 4;
- 先声明变量,再赋值
int a, b;
a = 3;
b = 2;
- 从外部读入数据
int a;
scanf("%d", &a);
在这里我要问,C语言中的单个等于号(也就是赋值)与数学中的等于是相同的含义吗?
显然不是的
int a = 2;
if (a = 1) printf("Yes");
else printf("No");
输出是这样的
Yes
因为if中执行的是赋值,而不是判断,如果你要写判断a 和 1 相等的话,应该这样写
int a = 2;
if(a == 1) printf("Yes");
else printf("No");
这一点大家一定不要记混哦~
变量的转换
赋值运算中的自动类型转换
这一部分在直播和ppt中已经提到过了,我们就简要说几个例子吧
double x;
x = 4.6;
printf("%d", x);
输出应该是
4
不难看出,浮点型小数如果要转化成整数,后面的小数位数会被直接抹掉,不会有任何的四舍五入
强制类型转换
格式:(数据类型)(表达式)
这里的表达式可以为常量,变量或表达式
#include <stdio.h>
int main()
{
int i, j;
double f = 4.5;
i = (int)f;
j = (int)(f + 2.5);
printf("%d %d", i, j);
return 0;
}
输出为:
4 7
算术表达式
算术运算符
运算符 | 类型 | 举例 | 含义 |
---|---|---|---|
+ | 一元运算符 | +a | a的值 |
- | 一元运算符 | -a | a的负值 |
+ | 二元运算符 | a+b | a与b的和 |
- | 二元运算符 | a-b | a与b的差 |
* | 二元运算符 | a*b | a与b的积 |
/ | 二元运算符 | a/b | a除以b的商(整除) |
% | 二元运算符 | a%b | a除以b的余数(取余) |
关于/与%更多的细节:
-
正负问题
/ :若一个为负数则结果为负数,两个为负数则负负得正
% :分子为负则结果为负,分子为正则结果为正,不受分母影响
-
小数问题
/ :若两个都是整数,则做整除运算;若有一个浮点数,则做实数除法
% :要求两个都必须为整数,否则会报错
int main()
{
int a = 3, b = 2;
float c = 3, d = 2;
printf("%d\n", a / b);
printf("%f\n", c / d);
return 0;
}
输出:
1
1.500000
可以看出,第一个作用与两个整数a, b中的 ‘ / ’ 意义应该是整除,而下面作用于c, d 的 ’ / ’ 才是我们熟悉的除法
复合运算符
运算符 | 实例 | 等价式 |
---|---|---|
+= | a += b | a = a + b |
-= | a -= b | a = a - b |
*= | a *= b | a = a * b |
/= | a /= b | a = a / b |
%= | a %= b | a = a % b |
复合运算符的结合方向为自右向左!
这里有两个例子:
int a = 4, b = 5, c = 6;
(1) a *= b -= c + 3
(2) a += b -= c *= 2
答案应该是:
(1) -16
(2) -3
自增、自减运算符
表达式 | "等效"表达式 | 注意 |
---|---|---|
i++ | i = i + 1 | 先使用i,再自增 |
i– | i = i – 1 | 先使用i,再自减 |
++i | i = i + 1 | 先自增,再使用i |
–i | i = i - 1 | 先自减,再使用i |
注意运算符前置与后置的区别!
int i = 1, j = 1;
printf("%d\n", i++);
printf("%d\n", ++j);
printf("%d %d\n", i, j);
这里的四个输出应该分别为:
1
2
2 2
“等效”并不代表真的完全相同!
位运算符
现有:
A:00000101 B:00001011
其他运算符
逻辑运算符
基本知识:
C语言中,0为假, 1为真
变量的逻辑含义:
bool变量 0假 1真 只有这两种取值
其他变量 0假 其余均为真
关系运算符
关系运算符 | 含义 |
---|---|
== | 两个等号,当左右两边相等的时候为真,不等的时候为假 |
!= | 不等号,当左右两边相等的时候为假,不等的时候为真 |
> | 大于号 |
< | 小于号 |
>= | 大于等于号 |
<= | 小于等于号 |
实例:
int main()
{
int a = 1, b = 2;
printf("%d\n", a == a);
printf("%d\n", a != b);
printf("%d\n", a >= b);
return 0;
}
输出:
1
1
0
逻辑运算符
逻辑与的写法是&&,而位运算中的与写法是&
逻辑或的写法是||,而位运算中的或写法是|
运算符之间的优先级
多个逻辑表达式
例:
int main()
{
int a = 1, b = 2;
printf("%d\n", a || b ++ );
printf("%d\n%d\n", a, b);
}
输出:
1
1
2
条件控制
if 语句
if 是最常见的条件分支语句
语法:
if (表达式1) {
语句组1;
}
if 语句是最常见的条件分支语句
表达式1是一个逻辑表达式,它的值可能是非0(真)或0(假)
当表达式1为真时,会执行下面的语句组1,否则不会执行。
if-else 语句
if (表达式1) {
语句组1;
} else {
语句组2;
}
else 常常搭配 if 出现
当表达式1为真时,只会执行下面的语句组1
当表达式1为假时,不会执行语句组1,并且会进入执行语句组2
多个 if-else 形成的多条件分支
if (表达式1) {
语句组1;
} else if (表达式2) {
语句组2;
} else if (表达式3) {
语句组3;
} else {
语句组4;
}
当表达式1为真时,只会执行语句组1,当表达式1为假时,会判断一下表达式2的真假值,当表达式2为真时,只会执行语句组2,否则接着判断表达式3的真假值,当表达式3为真时,只会执行语句组3,否则执行语句组4。
switch-case语句
switch (表达式) {
case 常量1: 语句1; break;
case 常量2: 语句2; break;
case 常量3: 语句3; break;
default: 语句n; break; // 结尾的 break; 可以省略
}
switch 语句是根据表达式的值来进行选择,看一看执行哪条语句
常量几和表达式相等就从语句几开始执行,直到语句中出现break才会中断
都没有的话就执行语句n。
例:
#include <stdio.h>
int main()
{
int day = 0;
scanf("%d", &day);
switch (day) {
case 1: printf("星期一\n");
case 2: printf("星期二\n");
case 3: printf("星期三\n");
case 4: printf("星期四\n"); break;
case 5: printf("星期五\n");
case 6: printf("星期六\n");
case 7: printf("星期天\n");
default: break;
}
return 0;
}
输入1:
5
输出1:
星期五
星期六
星期天
输入2:
1
输出2:
星期一
星期二
星期三
星期四
循环控制
while 语句
语法:
while (condition) {
// DoSomething
}
while 语句执行流程图:
例:
使用 while 语句打印 0 ~ 9
#include <stdio.h>
int main()
{
int a = 0;
while (a < 10) {
printf("%d ", a);
++a;
}
}
输出:
0 1 2 3 4 5 6 7 8 9
do-while 语句
语法:
do {
// DoSomething
} while (condition);
do-while 语句执行流程图:
例:
使用 do-while 循环打印 0 ~ 9
#include <stdio.h>
int main()
{
int a = 0;
do {
printf("%d ", a);
++a;
} while (a < 10);
}
输出:
0 1 2 3 4 5 6 7 8 9
for 语句
语法:
for (init; condition; increment) {
// DoSomething
}
for 语句执行流程图:
例:
使用 for 循环打印 0 ~ 9
#include <stdio.h>
int main()
{
// 考试时最好还是不要用 init 语句定义变量,将变量定义在 for 语句之前。
for (int a = 0; a < 10; ++a) {
printf("%d ", a);
}
}
输出:
0 1 2 3 4 5 6 7 8 9
init, condition, increment 语句都可以不写,不写 condition 则默认为真。(但是一般肯定还是要写的)
如果你想实现无限循环,可以这么写:
for (;;) {/* DoSomething */}
循环的嵌套
循环结构是可以嵌套的,比如下面的代码,外层是一层for循环,在循环中的每一次操作都会执行一次while循环。
例:
#include <stdio.h>
int main()
{
int i, j;
for (i = 1; i <= 5; ++i) {
j = 1;
while (j <= i) {
printf("*");
++j;
}
printf("\n");
}
}
输出:
*
**
***
****
*****