--- config: look: handDrawn themeVariables: fontSize: 28px --- flowchart TD 类型系统 --> 基础类型 类型系统 --> 复合类型 基础类型 --> 整型 基础类型 --> 浮点型 基础类型 --> 字符型 基础类型 --> 布尔型 复合类型 --> 数组 复合类型 --> pointer["指针/引用"] 复合类型 --> struct["结构/类"] 复合类型 --> 枚举 复合类型 --> 联合
《计算机程序设计》
计算机学院计算机研究所编译系统研究室
~/course
~/course/main.cpp
main.cpp
,随堂编程练习的代码请直接在此文件中编辑考考你
阅读下列程序,判断程序输出是什么?
#include <iostream>
void maxmin(double a, double b, double c, double &max, double &min) {
max = min = a;
if (b > max) max = b;
if (c > max) max = c;
if (b < min) min = b;
if (c < min) min = c;
return;
}
double max, min;
int main() {
double a = 1.0, b = 2.0, c = 3.0;
maxmin(a, b, c, max, min);
std::cout << "max = " << max << std::endl;
std::cout << "min = " << min << std::endl;
return 0;
}
学习目标
--- config: look: handDrawn themeVariables: fontSize: 28px --- flowchart TD 类型系统 --> 基础类型 类型系统 --> 复合类型 基础类型 --> 整型 基础类型 --> 浮点型 基础类型 --> 字符型 基础类型 --> 布尔型 复合类型 --> 数组 复合类型 --> pointer["指针/引用"] 复合类型 --> struct["结构/类"] 复合类型 --> 枚举 复合类型 --> 联合
考考你
C++数组与Python列表有什么区别?
数组在内存中的连续存储(一个方格代表4字节)
code/arraysize.cpp:2:16: error: size of array ‘numbers’ is not an integral constant-expression
2 | double numbers[n];
| ^
code/arraysize.cpp: In function ‘int main()’:
code/arraysize.cpp:5:18: error: narrowing conversion of ‘-1’ from ‘int’ to ‘long unsigned int’ [-Wnarrowing]
5 | char negtive[-1];
| ^
code/arraysize.cpp:5:16: error: size ‘-1’ of array ‘negtive’ is negative
5 | char negtive[-1];
| ^~
考考你
{}
括起来初始化表达式列表数组初始化示例
#include <iostream>
void printArray(const char *name, int a[], int n) {
std::cout << name << ": ";
for (int i = 0; i < n; i++)
std::cout << a[i] << ' ';
std::cout << std::endl;
}
int main() {
int a[5] = {1, 2, 3, 4, 5}; // 为每个元素赋初值
int b[5] = {1, 2, 3}; // 为前三个元素赋初值,其余为0
int c[] = {1, 2}; // 自动推导数组长度为2
printArray("a", a, 5); printArray("b", b, 5); printArray("c", c, 2);
return 0;
}
a: 1 2 3 4 5
b: 1 2 3 0 0
c: 1 2
code/arrayassign.cpp: In function ‘int main()’:
code/arrayassign.cpp:4:5: error: invalid array assignment
4 | b = a;
| ~~^~~
code/arrayassign.cpp:5:5: error: assigning to an array from an initializer list
5 | b = {1, 2, 3, 4, 5};
| ~~^~~~~~~~~~~~~~~~~
避坑
数组作为整体是不允许赋值的!
考考你
当对一般变量进行读写操作时,本质上是通过变量名对变量所在的内存空间进行读写,那么数组名的本质是什么?
[]
运算符,下标从0开始
数组访问示例
1
10
1610973184 21943
for
循环遍历数组最为常见数组遍历示例
1 2 3 4 5
sum: 15
测一测
编写程序,计算两个n维向量\(x = (x_1, \ldots, x_n)\)和\(y = (y_1, \ldots, y_n)\)的笛卡尔距离 \(d = \sqrt{\sum_{i=1}^{n} (x_i - y_i)^2}\)
n维向量的笛卡尔距离
#include <iostream>
#include <cmath>
int main() {
int n = 0;
std::cin >> n;
double x[n], y[n];
for (int i = 0; i < n; i++) {
x[i] = i; y[i] = 2 * n - i;
}
double distance = 0;
// ============= begin =============
// ============= end =============
std::cout << std::sqrt(distance) << std::endl;
return 0;
}
考考你
数组元素作为函数参数时,在函数内修改参数的值,外界是否能感知?
数组元素作为函数参数
1
2
明察秋毫
数组元素可以作为普通参数和引用参数传递,其行为与普通变量相同
元素类型 数组名[]
数组作为函数参数
1 2 3 4 5
Try it!
试试给数组形式参数[]
中加上长度信息,看看会发生什么?思考能否通过这种方式传递数组长度?为什么?
明察秋毫
数组作为函数参数时,传递的是数组的首地址!再想想,这个首地址是传值还是传引用?
sizeof
运算符sizeof
运算符返回整个数组的字节数sizeof运算符
#include <iostream>
int foo(int x[3]) { return sizeof(x) / sizeof(int); }
int main() {
int a[4]; static double b[2];
int n; std::cin >> n; char c[n];
std::cout << "length of a/b/c: " << sizeof(a) / sizeof(int) << " " << sizeof(b) / sizeof(double) << " " << sizeof(c) / sizeof(char) << std::endl;
std::cout << "length of x:" << foo(a) << std::endl;
return 0;
}
code/arraysizeof.cpp: In function ‘int foo(int*)’:
code/arraysizeof.cpp:2:35: warning: ‘sizeof’ on array function parameter ‘x’ will return size of ‘int*’ [-Wsizeof-array-argument]
2 | int foo(int x[3]) { return sizeof(x) / sizeof(int); }
| ~^~
code/arraysizeof.cpp:2:13: note: declared here
2 | int foo(int x[3]) { return sizeof(x) / sizeof(int); }
| ~~~~^~~~
length of a/b/c: 4 2 12
length of x:2
考考你
如何声明一个外部数组变量?从数组名的本质出发进行思考
arraydecl.cpp
考考你
对于int a[10]
数组,计算机如何在常数时间内访问第5个元素a[4]
?为什么数组可以随机访问?
线性查找
Found 4 at index 3
Not found
二分查找
#include <iostream>
int main() {
int arr[1024];
for (int i = 0; i < 1024; i++) arr[i] = i;
int target;
std::cin >> target;
// 二分查找
int left = 0, right = 1023, count = 0;
while (left <= right) {
int mid = (left + right) / 2;
++count;
if (arr[mid] == target) {
std::cout << "Found " << target << " at the " << count << " try\n";
return 0;
} else if (arr[mid] < target)
left = mid + 1;
else
right = mid - 1;
}
std::cout << "Not found" << std::endl;
return 0;
}
选择排序
#include <cstdlib>
#include <iostream>
int main() {
int numbers[1024];
for (int i = 0; i < 1024; i++)
numbers[i] = std::rand() % 1024;
// 选择排序
for (int i = 0; i < 1024; i++) {
int min = i;
for (int j = i + 1; j < 1024; j++)
if (numbers[j] < numbers[min])
min = j;
// 交换numbers[i]和numbers[min]
int temp = numbers[i];
numbers[i] = numbers[min];
numbers[min] = temp;
}
return 0;
}
冒泡排序
#include <cstdlib>
#include <iostream>
int main() {
int numbers[1024];
for (int i = 0; i < 1024; i++)
numbers[i] = std::rand() % 1024;
// 冒泡排序
for (int i = 0; i < 1024; i++) {
for (int j = 0; j < 1024 - i - 1; j++) {
if (numbers[j] > numbers[j + 1]) {
// 交换numbers[j]和numbers[j + 1]
int temp = numbers[j];
numbers[j] = numbers[j + 1];
numbers[j + 1] = temp;
}
}
}
return 0;
}
--- config: look: handDrawn themeVariables: fontSize: 20px --- mindmap 数组初步 数组定义与初始化 连续内存布局 静态长度与动态长度 数组初始化 数组名为首地址 数组访问 索引运算符 遍历数组 数组参数 查找与排序 随机访问 线性查找 二分查找 选择排序 冒泡排序 插入排序
学习目标
计算机程序设计