C 语言
C 语言
开发工具选择
自行下载 | 阿里云盘获取 |
---|---|
-
基本环境配置
1
2
3不登陆 QQ 时: ctrl + alt + s
File -> Settings -> Build,.. -> Toolchains -
编译器下载
自行下载 阿里云盘获取 -
添加
Mingw
的环境变量 -
测试环境
环境测试 输出结果 g++ -v
gcc -v
-
文件切换运行:
manin
函数切换临时方式 -
插件安装
用于快速添加项目启动
1
2
3C/C++ Single File Execution
安装完成后快捷键: ctrl + alt + shift + e -
去除
scanf
波浪线
语法
基础部分
程序框架
-
c
语言基本框架 1
2
3
4
5
6
int main()
{
return 0;
} -
输出
1
printf("双引号的内容将会被原位输出");
-
基本运算
1
2
3
4
5
6
int main()
{
printf("30+91=%d", 30 + 91);
return 0;
} -
输入
1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
printf("请输入两个整数: ");
int num1,
num2;
scanf("%d %d", &num1, &num2);
printf("输入整数的和为: %d + %d = %d", num1, num2, num1 + num2);
return 0;
} -
表达式
1
一个表达式是一系列运算符和算子的组合,用来计算一个值。 -
计算时间差
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main()
{
// 计算时间差
int hour1,
minute1;
int hour2,
minute2;
scanf("%d %d", &hour1, &minute1);
scanf("%d %d", &hour2, &minute2);
int t1 = hour1 * 60 + minute1; // 2*60+20 = 140 min
int t2 = hour2 * 60 + minute2; // 3*60+20 = 200 min
int t = t2 - t1; // 200 - 140 = 60 min 60/60=1h,60%60=0min
printf("时间差是: %d小时 %d 分", t / 60, t % 60); // 1 小时 0 分
return 0;
} -
运算符优先级
优先级 运算符 运算 结合关系 举例 1 +
单目不变 自右向左 a*+b
1 -
单目取负 自右向左 a*-b
2 *
乘 自左向右 a*b
2 /
除 自左向右 a/b
2 %
取余 自左向右 a%b
3 +
加 自左向右 a+b
3 -
减 自左向右 a-b
4 =
赋值 自右向左 a=b
-
交换两个变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
// 计算时间差
int a = 10;
int b = 20;
int temp = 0;
printf("交换前: a=%d b=%d\n", a, b);
// 交换两个数
temp = a;
a = b;
b = temp;
printf("交换后: a=%d b=%d", a, b);
return 0;
}
除法与取模运算符
-
除法
/
的运算结果对象的数据类型有关,两个数都是 int
,则商就是int
,若商有小数,则截取小数部分, 被除数和除数中只要有一个或两个都是浮点型数据, 则商也是浮点型, 不截取小数部分 1
216 / 5 == 3
16 / 5.0 == 3.200000 -
取余
%
的运算必须是整数, 结果是整除后的数, 其余数的符号与被除数相同 1
2
313 % 3 == 1
13 % -3 == 1
-13 % 3 == -1
C 语言对真假的处理
1 |
// |
符号常量
-
基本使用
1
2// 定义字符常量
数组与函数相关练习
-
插入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24【问题描述】编写程序,向有序序列中插入一个元素。设一个大小为
10 的一维数组中保存了一个有 9 个元素的非递减有序的整数序列,从键盘输入一个整数,将该整数插入到有序序列中,插入之后序列仍保持有序。输出插入前的序列和插入后的序列。
说明:有序序列通过键盘输入得到,且输入过程通过程序控制,只能输入非递减序列,若输入过程中,某元素比前一元素小,则该元素输入视为无效,需要重新输入此元素。
【输入形式】输入非递减的9 个整数,输入待插整数
【输出形式】插入前的序列和插入后的序列
【样例输入】
3 3 4 5 3 7 8 10 12 15
6
【样例输出】
Before:3 3 4 5 7 8 10 12 15
After:3 3 4 5 6 7 8 10 12 15
【样例说明】
输入有序序列过程中,第5 个整数 3 因小于前一个整数 5,为无效输入,重新输入第 5 个整数为 7 第 2 行输入待插入整数为 6 输出时,每个数据占 4 列列宽左对齐 -
解决方案阅读
数组动态分配内存
1 |
// |
1 |
|
指针
-
就是保存地址的变量
-
语法
1
2
3
4
5
6
7
8
9
10
11
12
int main() {
/* 定义变量 i */
int i;
/* 定义指针变量 *p,并将 i 的地址值交给 p */
int *p = &i; /* p 不是 i,更准确的说: 修改 p 的值不影响 i 的值,修改 i 的值也不会改变 i */
/* 定义指针 *n,整形变量 q(而q 并非是 指针变量) */
int *n, q;
return 0;
}1
2
3
4
5
6
7/* p 不是 i,
更准确的说: 修改 p 的值不影响 i 的值,修改 i 的值也不会改变 i */ 如果一个指针变量指向了某个普通变量, 则 * 指针变量 就完全等同于 普通变量
例子:
如果 p 是个指针变量, 并且存放了普通变量 i 的地址,则 p 指向了普通变量 i,*p 就完全等同于 i
或者说: 在所有出现 *p 的地方都可以替换成 i
在所有出现 i 的地方都可以替换成 *p -
通过指针交换两个变量的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22//
// Created by coder-itl on 2021/9/26.
//
void swap(int *pa, int *pb) {
int t;
t = *pa;
*pa = *pb;
*pb = t;
};
int main() {
int a = 10, b = 20;
swap(&a, &b);
printf("a = %d\nb = %d", a, b);
return 0;
} -
*
号的三重含义 1
2
3
4
5
61. 乘法
2. 定义指针变量
3. 指针运算符
该运算符放在已经定义好的指针变量的前面,
如果 p 是一个已经定义好的指针变量
则 *p 表示 以 p 的内容为地址的变量 -
变量的值是内存的地址
- 普通变量的值是实际的值
- 指针变量的值是具有实际值的变量的地址
-
指针作为参数传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/* 输入数组的函数声明 */
int *inputArray();
/* 排序数组函数声明 */
int *sortArray(int *p);
/* 输出数组函数声明 */
void printfArray(int *p);
// TODO: 1. 缺少倒序排序 输出格式问题
int main() {
int *p, *q;
p = inputArray();
printf("Before sort:");
printfArray(p);
q = sortArray(p);
printf("\nAfter sort:");
printfArray(q);
return 0;
}
int *inputArray() {
/* 数组容量和变量 i */
int i, num;
scanf("%d", &num); /* maloc() */
/* 定义整形数组 */
static int array[5];
/* 动态获取数组长度 */
int length = sizeof(array) / sizeof(array[0]);
for (i = 0; i < length; i++) {
scanf("%d", &array[i]);
}
return array;
}
int *sortArray(int *p) {
int i, j;
for (i = 0; i < 5 - 1; i++) {
for (j = 0; j < 5 - 1 - i; j++) {
if (p[j] > p[j + 1]) {
int temp = p[j];
p[j] = p[j + 1];
p[j + 1] = temp;
}
}
}
return p;
}
void printfArray(int *p) {
int i;
for (i = 0; i < 5; ++i) {
printf("%-4d", *(p + i));
}
}
深入了解指针
-
使用:
1
2
3
4
5
6疑问: *p 和 p 选取的时机问题?
如何通过被调函数修改主调函数普通变量的地址:
1. 实参必须为该普通变量的地址
2. 形参必须为指针变量
3. 在被调函数中通过 *形参名 = ... 的方式就可以修改主调函数相关变量的值
指针与一维数组的关系
-
指针和数组
1
一维数组名: 一维数组名是一个指针常量, 它存放的是一维数组第一个元素的地址 -
下标和指针的关系
1
如果 P 是个指针变量, 则 p[i] 永远等价于 *(p+1) -
确定一个一维数组需要几个参数
[ 如果一个函数要处理一个一维数组,
]则需要接受该数组的那些信息? 1
21. 数组名
2. 数组长度 -
指针变量的运算
1
2
3指针变量不能相加 不能相乘 不能相除
如果两个指针变量指向的是同一块连续空间中的不同存储单元,则这两个指针变量才可以相减 -
数组与指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30//
// Created by coder-itl on 2021/10/3.
//
/* 形参含义:
* "*p" = 数组名
* length: 数组长度
* */
void printfArray(int *p, int length);
int main() {
int arrayA[] = {1, 3, 5, 7, 10};
int arrayB[] = {2, 3, 6, 7, 10};
int arrayC[] = {4, 1, 5, 7, 10};
/* 将数组强制转换为 (int *) 类型 */
printfArray((int *) &arrayC, 5);
return 0;
}
void printfArray(int *p, int length) {
int i;
for (i = 0; i < length; i++) {
printf("%d ", p[i]);
}
}
结构体
-
定义
1
为了减少内存的消耗, 也为了提高执行的速度, 推荐 "地址传递" -
具体使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//
// Created by coder-itl on 2021/9/26.
//
/* 布尔值的库 */
/* 字符串的库 */
struct stuBirthday {
/* 年 */
int year;
/* 月 */
int month;
/* 日 */
int day;
};
struct StuScore {
/* 平时成绩 */
int normalGrades;
/* 实验成绩 */
int experimentalGrades;
/* 期末成绩 */
int finalGrades;
/* 总评成绩 */
int generalCommentGrades;
};
struct Members {
/* 限制学号 为 7 位数 */
int stuNo;
/* 学生姓名 限制长度为: 4*/
char stuName[9];
/* 学生出生日期 格式: 年/ 月 / 日 */
struct stuBirthday birthday;
/* 总评成绩= 平时成绩 *0.2+ 实验成绩 *0.3+ 期末成绩 *0.5 */
struct StuScore stuScore;
};
int main() {
int num, i;
/*
* 结构体赋值:
* 1. 点域"." 的方式
* 2. 地址: ->
* */
/* 输入数量 */
scanf("%d", &num);
struct Members members[num];
for (i = 0; i < num; i++) {
/* 结构体赋值 */
scanf("%d", &members[i].stuNo);
/* 结构体字符数组元素的输入赋值 */
scanf("%s", members[i].stuName);
/* 输入年月日 */
scanf("%d %d %d",
/* 年 */
&members[i].birthday.year,
/* 月 */
&members[i].birthday.month,
/* 日 */
&members[i].birthday.day);
/* 输入成绩 */
scanf("%d %d %d",
/* 输入学生的平时成绩 */
&members[i].stuScore.normalGrades,
/* 输入学生的实验成绩 */
&members[i].stuScore.experimentalGrades,
/* 输入学生的期末成绩 */
&members[i].stuScore.finalGrades
);
}
printf("%-10s%-10s%-12s%-4s%-4s%-4s%-4s\n", "num", "name", "birthday", "s1", "s2", "s3", "sum");
/* 结构体输出 */
for (i = 0; i < num; i++) {
/* 总评成绩 = 平时成绩*0.2+ 实验成绩 *0.3+ 期末成绩 *0.5 */
members[i].stuScore.generalCommentGrades =
(members[i].stuScore.normalGrades * 0.2) + (members[i].stuScore.experimentalGrades * 0.3) +
(members[i].stuScore.finalGrades * 0.5);
/* 学号10 列列宽,左对齐;
* 姓名10 列列宽,左对齐;
* 出生日期的年份原样输出,月份为2 列列宽右对齐,日为 4 列列宽左对齐;
* 平时成绩、实验成绩、期末成绩和总评成绩均为4 列列宽,左对齐
* */
printf("%-10d%-10s%-4d/%2d/%-4d%-4d%-4d%-4d%-4d",
/* 输出学号 */
members[i].stuNo,
/* 输出学生姓名 */
members[i].stuName,
/* 输出学生出生的年分 */
members[i].birthday.year,
/* 输出学生出生的月分 */
members[i].birthday.month,
/* 输出学生出生的 天数 */
members[i].birthday.day,
/* 平时成绩 */
members[i].stuScore.normalGrades,
/* 实验成绩 */
members[i].stuScore.experimentalGrades,
/* 期末成绩 */
members[i].stuScore.finalGrades,
/* 总评成绩= 平时成绩 *0.2 + 实验成绩 *0.3 + 期末成绩 *0.5 */
members[i].stuScore.generalCommentGrades
);
/* 完成一个学生信息后换行 */
printf("\n");
}
return 0;
}
C 语言练习题
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 coder-itl!
评论