C++是一种功能强大且广泛应用的编程语言,对于想要深入学习编程和算法的人来说,掌握C++是一个重要的里程碑。本文将带你逐步了解C++编程的基础知识,并介绍一些算法和编程技巧帮你入门c++算法。
在
c++算法入门教程(1)和c++算法入门教程(2)-中,我讲了什么是编程、安装编译环境、输出、变量、输入、for循环、if和switch选择语句、循环结构、数组、函数,没看第一、二篇的可以去看看。
这篇博文续接c++算法入门教程(2),再次深入数组和函数。
一、数组
数组是C++中一种基础而强大的数据结构,用于存储相同类型的一组元素。在之前的文章中,我们已经简要介绍了数组的概念,现在我们进一步探讨其使用细节和应用场景。
1. 定义与初始化
数组的定义需要指定元素类型、数组名以及元素数量。例如,创建一个包含五个整数的数组`nums`:
int nums[5]; // 声明一个长度为5的整数数组
初始化数组可以在声明时直接给出初始值,使用花括号 `{}` 包裹各个元素:
int scores[] = {85, 9½, 78, 92, 88}; // 初始化一个整数数组
若未指定数组长度,编译器会根据初始值的数量自动推断。另外,数组的索引是从0开始的,因此`scores[0]`对应第一个元素`85`,`scores[4]`对应最后一个元素`88`。
2. 访问与修改
通过数组名和索引来访问或修改数组中的元素:
cout << "First score is: " << scores[0] << endl; // 输出第一个分数
scores[2] = 80; // 将第三个分数改为80
3. 二维数组
数组还可以是多维的,最常见的是二维数组,相当于一个表格。例如,定义一个3行4列的整数数组`matrix`:
int matrix[3][4]; // 声明一个3行4列的二维整数数组
初始化和访问二维数组与一维数组类似,只需增加一个索引维度:
int chessboard[8][8] = {
{0, 1, 0, 1, 0, 1, 0, 1},
{1, 0, 1, 0, 1, 0, 1, 0},
// ...
};
cout << "Top-left square is: " << chessboard[0][0] << endl; // 输出左上角方格值
4. 数组操作注意事项
使用数组时务必注意以下几点:
1. 避免数组越界访问
数组的索引是从0开始的,这意味着一个长度为N
的数组其有效索引范围是0
到N-1
。试图访问超出此范围的元素会导致未定义行为,可能会引发程序崩溃、数据损坏,甚至安全漏洞。例如,对于数组int arr[5]
,正确的访问应该是arr[0]
至arr[4]
。对arr[-1]
、arr[5]
及更远位置的访问都是非法的:
int arr[5] = {1, 2, 3, 4, 5};
cout << arr[4]; // 合法:输出5
cout << arr[5]; // 非法:可能导致程序崩溃或意外行为
确保在编写涉及数组索引的代码时,始终对索引值进行有效的边界检查。尤其是在循环中遍历数组时,务必确保循环条件正确限制了索引范围。
2. 数组大小一旦确定,无法动态改变
在C++中,数组的大小在声明时就已经确定,且在程序运行期间无法更改。这意味着一旦创建了一个具有特定大小的数组,你无法在程序运行时增加或减少其元素数量。例如:
int arr[5]; // 创建一个长度为5的数组
arr[5] = 6; // 错误:尝试在数组尾部添加新元素,数组大小并未改变
// 或者
arr.resize(10); // 错误:C++数组没有resize方法,不能动态改变大小
如果需要动态调整元素数量,应该使用std::vector
,它是一个可变大小的数组类模板,提供了添加、删除元素以及动态调整容量的方法。
3. 数组名作为指针使用
在某些上下文中,数组名可以被视为指向其首元素的指针。这意味着可以使用数组名进行指针运算,如解引用或进行指针偏移。但是要注意,尽管数组名和指针在某些情况下可以互换使用,它们在语义上并不完全相同:
int arr[5] = {1, 2, 3, 4, 5};
int* ptr = arr; // 将数组名赋值给指针,ptr现在指向arr的第一个元素
cout << *ptr++; // 输出1,然后ptr指向arr的第二个元素
cout << *ptr; // 输出2
尽管数组名可以作为指针使用,但不能对数组名本身进行赋值操作,如arr = new int[10];
是非法的。
4. 数组复制与赋值
直接复制或赋值整个数组通常需要手动逐个元素复制,或者使用标准库提供的std::copy
函数。C++11引入了std::array
,它提供了拷贝构造函数和赋值运算符,使得数组的复制更为方便。对于std::vector
,则可以直接使用赋值运算符(=
)或std::vector::assign
方法进行数组的复制。
二、函数
函数是组织和复用代码的重要手段,它将一组相关操作封装在一个独立的单元中,便于管理和调用。在C++中,函数的定义和使用涉及以下几个方面:
1. 声明与定义
函数声明告诉编译器函数的存在、返回类型以及参数列表,而定义则提供了函数的具体实现。例如,声明一个计算两数之和的函数add
:
1int add(int a, int b); // 声明函数add,接收两个int参数,返回int类型
对应的函数定义:
1int add(int a, int b) {
2 return a + b; // 函数体实现两数相加,并返回结果
3}
2. 参数传递
函数参数可以通过值传递、引用传递或指针传递。值传递时,函数接收到参数的一个副本;引用传递和指针传递则允许函数直接修改原始变量的值。例如:
// 值传递
void incrementByValue(int num) {
num += 10; // 变量num的副本在函数内部增加10,不影响外部变量
}
// 引用传递
void incrementByRef(int& num) {
num += 10; // 直接修改传入的num变量
}
// 指针传递
void incrementByPtr(int* numPtr) {
*numPtr += 10; // 通过指针修改指向的变量
}
3. 返回值
函数可以返回一个值(如add
函数),也可以没有返回值(声明为void
)。如果函数有多条return
语句,仅最后一条被执行,其他return
语句通常用于提前结束函数执行。
4. 函数重载
C++允许同一作用域内具有相同名字但参数列表不同的函数,称为函数重载。重载有助于提高代码的可读性和一致性:
int max(int a, int b) {
return a > b ? a : b;
}
double max(double a, double b) {
return a > b ? a : b;
}
至此,我已全面介绍了C++中的if语句、switch语句、循环结构(for、while、do-while)、数组、函数。这些基础知识是构建复杂算法的基础。