文章目录
1. 定义数字
通常,当需要用到数字时,我们会使用原始的数据类型,如 int、short、long、float 和 double 等等。
#include <iostream>
#include <iomanip> // 包含 iomanip 以便格式化输出
using namespace std;
int main() {
// 定义数值变量
int basePrice = 999; // 基本价格
float taxRate = 0.07f; // 税率
float tax = basePrice * taxRate; // 计算税金
float totalPrice = basePrice + tax; // 计算总价
// 格式化输出结果
cout << left << setw(15) << "基本价格 (元):" << basePrice << endl;
cout << left << setw(15) << "税率 (%):" << taxRate * 100 << "%" << endl;
cout << left << setw(15) << "税金 (元):" << fixed << setprecision(2) << tax << endl;
cout << left << setw(15) << "总价 (元):" << fixed << setprecision(2) << totalPrice << endl;
return 0;
}
输出结果:
基本价格 (元): 999
税率 (%): 7.00%
税金 (元): 69.93
总价 (元): 1068.93
2. 数学运算
在 C++ 中,除了可以创建各种函数,还包含了各种有用的函数供您使用。这些函数写在标准 C 和 C++ 库中,叫做内置函数。您可以在程序中引用这些函数。
C++ 内置了丰富的数学函数,可对各种数字进行运算。为了利用这些函数,需要引用数学头文件 <cmath>。
序号 | 函数 & 描述 |
---|---|
1 | double cos(double); 该函数返回弧度角(double 型)的余弦。 |
2 | double sin(double); 该函数返回弧度角(double 型)的正弦。 |
3 | double tan(double); 该函数返回弧度角(double 型)的正切。 |
4 | double log(double); 该函数返回参数的自然对数。 |
5 | double pow(double, double); 假设第一个参数为 x,第二个参数为 y,则该函数返回 x 的 y 次方。 |
6 | double hypot(double, double); 该函数返回两个参数的平方总和的平方根,也就是说,参数为一个直角三角形的两个直角边,函数会返回斜边的长度。 |
7 | double sqrt(double); 该函数返回参数的平方根。 |
8 | int abs(int); 该函数返回整数的绝对值。 |
9 | double fabs(double); 该函数返回任意一个浮点数的绝对值。 |
10 | double floor(double); 该函数返回一个小于或等于传入参数的最大整数。 |
代码示例:
#include <iostream>
#include <cmath> // 包含 cmath 以便使用数学函数
using namespace std;
int main() {
// 数组定义
double times[] = {1.0, 2.0, 3.0}; // 定义一个浮点型数组,表示时间(秒)
// 物理常量
const double g = 9.8; // 重力加速度(米/秒^2)
// 物理运算
for (int i = 0; i < 3; i++) {
double t = times[i];
double displacement = 0.5 * g * pow(t, 2); // 计算位移:1/2 * g * t^2
double velocity = g * t; // 计算速度:g * t
cout << "时间 (秒): " << t << endl;
cout << "位移 (米): " << fixed << setprecision(2) << displacement << endl;
cout << "速度 (米/秒): " << fixed << setprecision(2) << velocity << endl;
cout << "-------------------------------" << endl;
}
return 0;
}
-
这个示例通过计算自由落体运动中的位移和速度来展示内置数学函数的使用。以下是对这段代码的解释:
double times[] = {1.0, 2.0, 3.0};
:定义了一个浮点型数组,表示时间点。const double g = 9.8;
:定义了重力加速度常量。for
循环遍历时间点数组,计算位移和速度。- 使用
pow
函数计算位移时所需的平方。 - 使用
fixed
和setprecision
格式化输出结果。
3. 随机数
在许多情况下,需要生成随机数。关于随机数生成器,有两个相关的函数。一个是 rand(),该函数只返回一个伪随机数。生成随机数之前必须先调用 srand() 函数。
下面是一个关于生成随机数的简单实例。实例中使用了 time() 函数来获取系统时间的秒数,通过调用 rand() 函数来生成随机数:
代码示例:
#include <iostream>
#include <string>
using namespace std;
int main() {
string str1 = "Hello, ";
string str2 = "world!";
// 字符串连接
string str3 = str1 + str2;
cout << "连接后的字符串: " << str3 << endl;
// 查找子字符串
size_t found = str3.find("world");
if (found != string::npos) {
cout << "'world' 在索引 " << found << " 处找到" << endl;
} else {
cout << "未找到 'world'" << endl;
}
// 替换子字符串
str3.replace(found, 5, "C++");
cout << "替换后的字符串: " << str3 << endl;
// 获取字符串长度
cout << "字符串长度: " << str3.length() << endl;
// 将字符串转换为大写
for (char& c : str3) {
c = toupper(c);
}
cout << "大写字符串: " << str3 << endl;
return 0;
}
string str1 = "Hello, ";
和string str2 = "world!";
:定义了两个字符串。string str3 = str1 + str2;
:将两个字符串连接起来。str3.find("world");
:查找子字符串"world"在连接后的字符串中的索引。str3.replace(found, 5, "C++");
:将子字符串替换为"C++"。str3.length();
:获取字符串的长度。- 使用
toupper
函数将字符串转换为大写。
4. 数组
C++ 支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 numbers[0]、numbers[1]、...、numbers[99] 来代表一个个单独的变量。数组中的特定元素可以通过索引访问。
所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。
声明数组
在 C++ 中要声明一个数组,需要指定元素的类型和元素的数量,如下所示:
type arrayName [ arraySize ];
这叫做一维数组。arraySize 必须是一个大于零的整数常量,type 可以是任意有效的 C++ 数据类型。例如,要声明一个类型为 double 的包含 10 个元素的数组 balance,声明语句如下:
double balance[10];
现在 balance 是一个可用的数组,可以容纳 10 个类型为 double 的数字。
初始化数组
在 C++ 中,您可以逐个初始化数组,也可以使用一个初始化语句,如下所示:
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
大括号 { } 之间的值的数目不能大于我们在数组声明时在方括号 [ ] 中指定的元素数目。
如果您省略掉了数组的大小,数组的大小则为初始化时元素的个数。因此,如果:
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
您将创建一个数组,它与前一个实例中所创建的数组是完全相同的。下面是一个为数组中某个元素赋值的实例:
balance[4] = 50.0;
上述的语句把数组中第五个元素的值赋为 50.0。所有的数组都是以 0 作为它们第一个元素的索引,也被称为基索引,数组的最后一个索引是数组的总大小减去 1。
5. 访问数组元素
数组元素可以通过数组名称加索引进行访问。元素的索引是放在方括号内,跟在数组名称的后边。例如:
double salary = balance[9];
上面的语句将把数组中第 10 个元素的值赋给 salary 变量。下面的实例使用了上述的三个概念,即,声明数组、数组赋值、访问数组:
代码示例:
#include <iostream>
#include <iomanip> // 包含 iomanip 以使用 setw
using namespace std;
int main() {
const int ROWS = 5;
const int COLS = 10;
char grid[ROWS][COLS]; // 定义一个 5x10 的字符二维数组,代表图形界面
// 初始化网格数组,填充空格
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
grid[i][j] = ' ';
}
}
// 在网格中设置一些字符
grid[1][2] = '*'; // 在 (1, 2) 位置设置 '*'
grid[2][4] = '*'; // 在 (2, 4) 位置设置 '*'
grid[3][6] = '*'; // 在 (3, 6) 位置设置 '*'
grid[4][8] = '*'; // 在 (4, 8) 位置设置 '*'
// 输出表头
cout << " ";
for (int j = 0; j < COLS; j++) {
cout << setw(2) << j;
}
cout << endl;
// 输出网格中的每个字符
for (int i = 0; i < ROWS; i++) {
cout << setw(2) << i << " "; // 输出行号
for (int j = 0; j < COLS; j++) {
cout << setw(2) << grid[i][j]; // 按格式输出数组元素
}
cout << endl; // 换行
}
return 0;
}
const int ROWS = 5; const int COLS = 10;
:定义行和列的常量。char grid[ROWS][COLS];
:定义一个字符二维数组,表示图形界面。- 使用嵌套循环初始化网格,将其填充为空格字符。
- 在特定位置设置星号字符
'*'
。 - 输出列标题。
- 使用嵌套循环输出网格中的每个字符,带有行号和列对齐格式。
6. 数组类型
概念 | 描述 |
---|---|
多维数组 | C++ 支持多维数组。多维数组最简单的形式是二维数组。 |
指向数组的指针 | 您可以通过指定不带索引的数组名称来生成一个指向数组中第一个元素的指针。 |
传递数组给函数 | 您可以通过指定不带索引的数组名称来给函数传递一个指向数组的指针。 |
从函数返回数组 | C++ 允许从函数返回数组。 |
7. 多维数组
C++ 支持多维数组。多维数组声明的一般形式如下:
type name[size1][size2]...[sizeN];
下面的声明创建了一个三维 5 . 10 . 4 整型数组:
int threedim[5][10][4];
二维数组
多维数组最简单的形式是二维数组。一个二维数组,在本质上,是一个一维数组的列表。声明一个 x 行 y 列的二维整型数组,形式如下:
type arrayName [ x ][ y ];
其中,type 可以是任意有效的 C++ 数据类型,arrayName 是一个有效的 C++ 标识符。
一个二维数组可以被认为是一个带有 x 行和 y 列的表格。下面是一个二维数组,包含 3 行和 4 列:
因此,数组中的每个元素是使用形式为 a[ i , j ] 的元素名称来标识的,其中 a 是数组名称,i 和 j 是唯一标识 a 中每个元素的下标。
初始化二维数组
多维数组可以通过在括号内为每行指定值来进行初始化。下面是一个带有 3 行 4 列的数组。
int a[3][4] = {
{0, 1, 2, 3} , /* 初始化索引号为 0 的行 */
{4, 5, 6, 7} , /* 初始化索引号为 1 的行 */
{8, 9, 10, 11} /* 初始化索引号为 2 的行 */
};
内部嵌套的括号是可选的,下面的初始化与上面是等同的:
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
访问二维数组元素
二维数组中的元素是通过使用下标(即数组的行索引和列索引)来访问的。例如:
int val = a[2][3];
上面的语句将获取数组中第 3 行第 4 个元素。您可以通过上面的示意图来进行验证。让我们来看看下面的程序,我们将使用嵌套循环来处理二维数组:
代码示例:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
const int STUDENTS = 5;
const int SUBJECTS = 3;
// 定义一个 5 行 3 列的数组,并初始化为学生成绩
float scores[STUDENTS][SUBJECTS] = {
{85.0, 90.0, 78.0},
{76.0, 85.0, 88.0},
{90.0, 92.0, 85.0},
{70.0, 75.0, 80.0},
{88.0, 82.0, 84.0}
};
// 输出每个学生的成绩并计算平均分
for (int i = 0; i < STUDENTS; i++) {
float studentSum = 0.0; // 定义变量计算每个学生的成绩和
cout << "Student " << i + 1 << " scores: ";
for (int j = 0; j < SUBJECTS; j++) {
cout << setw(6) << scores[i][j] << " ";
studentSum += scores[i][j]; // 计算当前学生的成绩和
}
float studentAverage = studentSum / SUBJECTS; // 计算当前学生的平均分
cout << " Average: " << fixed << setprecision(2) << studentAverage << endl;
}
cout << "-------------------------" << endl;
// 计算每门课程的平均成绩
for (int j = 0; j < SUBJECTS; j++) {
float subjectSum = 0.0; // 定义变量计算每门课程的成绩和
for (int i = 0; i < STUDENTS; i++) {
subjectSum += scores[i][j]; // 计算当前课程的成绩和
}
float subjectAverage = subjectSum / STUDENTS; // 计算当前课程的平均分
cout << "Average score for Subject " << j + 1 << ": " << fixed << setprecision(2) << subjectAverage << endl;
}
return 0;
}
输出结果:
Student 1 scores: 85.00 90.00 78.00 Average: 84.33
Student 2 scores: 76.00 85.00 88.00 Average: 83.00
Student 3 scores: 90.00 92.00 85.00 Average: 89.00
Student 4 scores: 70.00 75.00 80.00 Average: 75.00
Student 5 scores: 88.00 82.00 84.00 Average: 84.67
-------------------------
Average score for Subject 1: 81.80
Average score for Subject 2: 84.80
Average score for Subject 3: 83.00
const int STUDENTS = 5; const int SUBJECTS = 3;
:定义学生和课程的常量。- 定义一个二维数组
float scores[STUDENTS][SUBJECTS]
并初始化为学生的成绩。 - 使用嵌套循环输出每个学生的成绩,并计算和输出每个学生的平均成绩。
- 使用嵌套循环计算和输出每门课程的平均成绩。
8. 指向数组的指针
数组名是指向数组中第一个元素的常量指针。
double runoobAarray[50];
runoobAarray 是一个指向 &runoobAarray[0] 的指针,即数组 runoobAarray 的第一个元素的地址。因此,下面的程序片段把 p 赋值为 runoobAarray 的第一个元素的地址:
double *p;
double runoobAarray[10];
p = runoobAarray;
使用数组名作为常量指针是合法的。因此,*(runoobAarray + 4) 是一种访问 runoobAarray[4] 数据的合法方式。
一旦把第一个元素的地址存储在 p 中,您就可以使用 *p、*(p+1)、*(p+2) 等来访问数组元素。
代码示例:
#include <iostream>
using namespace std;
// 函数声明
void multiplyByTwo(double *arr, int size);
int main() {
// 带有 5 个元素的双精度浮点型数组
double runoobArray[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
// 输出修改前的数组值
cout << "修改前的数组值:" << endl;
for (int i = 0; i < 5; i++) {
cout << "runoobArray[" << i << "] : " << runoobArray[i] << endl;
}
// 调用函数并传递数组
multiplyByTwo(runoobArray, 5);
// 输出修改后的数组值
cout << "\n修改后的数组值:" << endl;
for (int i = 0; i < 5; i++) {
cout << "runoobArray[" << i << "] : " << runoobArray[i] << endl;
}
return 0;
}
// 定义函数,通过指针参数修改数组值
void multiplyByTwo(double *arr, int size) {
for (int i = 0; i < size; i++) {
arr[i] *= 2;
}
}
修改前的数组值:
runoobArray[0] : 1000
runoobArray[1] : 2
runoobArray[2] : 3.4
runoobArray[3] : 17
runoobArray[4] : 50修改后的数组值:
runoobArray[0] : 2000
runoobArray[1] : 4
runoobArray[2] : 6.8
runoobArray[3] : 34
runoobArray[4] : 100
void multiplyByTwo(double *arr, int size);
:声明一个函数,该函数将接受一个指向双精度浮点数组的指针和数组的大小。- 在
main
函数中定义了一个包含 5 个元素的双精度浮点数组runoobArray
。 - 输出数组在修改前的值。
- 调用
multiplyByTwo
函数,并传递数组的起始地址和数组大小。 multiplyByTwo
函数遍历数组,并将每个元素的值加倍。- 输出数组在修改后的值。
9. 传递数组给函数
可以通过指定不带索引的数组名来传递一个指向数组的指针。C++ 传数组给一个函数,数组类型自动转换为指针类型,因而传的实际是地址。
如果想要在函数中传递一个一维数组作为参数,必须以下面三种方式来声明函数形式参数,这三种声明方式的结果是一样的,因为每种方式都会告诉编译器将要接收一个整型指针。同样地也可以传递一个多维数组作为形式参数。
方式 1
形式参数是一个指针:
void myFunction(int *param)
{
.
.
.
}
方式 2
形式参数是一个已定义大小的数组:
void myFunction(int param[10])
{
.
.
.
}
方式 3
形式参数是一个未定义大小的数组:
void myFunction(int param[])
{
.
.
.
}
代码示例:
下面这个例子展示了如何通过函数传递数组,并在函数中对数组进行排序。这里使用的是冒泡排序算法。
#include <iostream>
using namespace std;
// 函数声明
void bubbleSort(int arr[], int size);
int main() {
// 带有 6 个元素的整数数组
int numbers[6] = {64, 34, 25, 12, 22, 11};
// 输出排序前的数组
cout << "排序前的数组:";
for (int i = 0; i < 6; i++) {
cout << numbers[i] << " ";
}
cout << endl;
// 调用函数并传递数组
bubbleSort(numbers, 6);
// 输出排序后的数组
cout << "排序后的数组:";
for (int i = 0; i < 6; i++) {
cout << numbers[i] << " ";
}
cout << endl;
return 0;
}
// 定义函数,通过指针参数修改数组的顺序
void bubbleSort(int arr[], int size) {
for (int i = 0; i < size-1; i++) {
for (int j = 0; j < size-i-1; j++) {
if (arr[j] > arr[j+1]) {
// 交换相邻的元素
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
- 函数声明:
void bubbleSort(int arr[], int size);
并定义了bubbleSort
函数,该函数使用冒泡排序算法对数组进行排序。 - 初始化数组:
int numbers[6] = {64, 34, 25, 12, 22, 11};
。 - 输出排序前的数组:使用循环输出数组中每个元素的值。
- 调用排序函数:
bubbleSort(numbers, 6);
,传递数组及其大小给排序函数。 - 排序操作:
bubbleSort
函数使用嵌套循环进行冒泡排序,比较并交换相邻的元素直至数组完全排序。 - 输出排序后的数组:再次使用循环输出数组中每个元素的值。
排序前的数组:64 34 25 12 22 11
排序后的数组:11 12 22 25 34 64
就函数而言,数组的长度是无关紧要的,因为 C++ 不会对形式参数执行边界检查。
10. 从函数返回数组
C++ 不允许返回一个完整的数组作为函数的参数。但是可以通过指定不带索引的数组名来返回一个指向数组的指针。
如果想要从函数返回一个一维数组,必须声明一个返回指针的函数,如下:
int * myFunction() {
//. . .
}
代码示例:
int* myFunction()
{
int myArray[5] = {1, 2, 3,4,5};
return myArray;
}
注意:不能简单地返回指向局部数组的指针,因为当函数结束时,局部数组将被销毁,指向它的指针将变得无效。
C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。
为了避免以上情况,你可以使用静态数组或者动态分配数组。
使用静态数组需要在函数内部创建一个静态数组,并将其地址返回,例如:
int* myFunction()
{
static int myArray[5] = {1, 2, 3,4,5};
return myArray;
}
代码通过使用静态数组返回随机数列表,同时演示了如何通过指针来遍历和访问数组元素。
#include <iostream>
#include <cstdlib> // 包含 stdlib 以使用 rand 和 srand
#include <ctime> // 包含 ctime 以使用 time
using namespace std;
// 函数声明
int* generateRandomNumbers(int size);
int main() {
const int size = 10;
// 调用函数并获取返回的数组指针
int* randomNumbers = generateRandomNumbers(size);
// 输出生成的随机数
cout << "生成的随机数:" << endl;
for (int i = 0; i < size; i++) {
cout << "randomNumbers[" << i << "] : " << randomNumbers[i] << endl;
}
return 0;
}
// 定义函数生成随机数并返回指针
int* generateRandomNumbers(int size) {
static int r[10]; // 静态数组,确保返回后数组仍然存在
// 设置随机数种子
srand(static_cast<unsigned>(time(nullptr)));
// 生成随机数并存储在数组中
for (int i = 0; i < size; i++) {
r[i] = rand() % 100; // 生成 0 到 99 之间的随机数
cout << "Generated r[" << i << "] = " << r[i] << endl;
}
return r; // 返回数组的指针
}
-
静态数组的使用:
- 在函数
generateRandomNumbers
中,使用了静态数组r[10]
。静态数组在函数调用结束后仍然存在,因此可以安全地返回其指针。 - 这样做是为了避免返回局部变量的地址,该地址在函数退出后会被释放,从而导致未定义行为。
- 在函数
-
设置随机数种子:
- 使用
srand(static_cast<unsigned>(time(nullptr)));
为随机数生成器设置种子,确保每次运行程序时都会生成不同的随机数序列。 - 使用
rand() % 100
限制生成的随机数在 0 到 99 之间,增加了代码的实用性。
- 使用
-
随机数生成和输出:
- 在
generateRandomNumbers
函数中,随机数被生成并存储到数组中,同时输出每个生成的随机数,这有助于在调试时了解数组的内容。
- 在
-
使用指针遍历数组:
- 在
main
函数中,通过指针randomNumbers
遍历数组,并输出每个数组元素的值。这里展示了指针和数组的紧密关系,即数组名可以作为指针来使用。
- 在
输出结果:
Generated r[0] = 45
Generated r[1] = 78
Generated r[2] = 12
Generated r[3] = 34
Generated r[4] = 56
Generated r[5] = 89
Generated r[6] = 23
Generated r[7] = 67
Generated r[8] = 90
Generated r[9] = 11
生成的随机数:
randomNumbers[0] : 45
randomNumbers[1] : 78
randomNumbers[2] : 12
randomNumbers[3] : 34
randomNumbers[4] : 56
randomNumbers[5] : 89
randomNumbers[6] : 23
randomNumbers[7] : 67
randomNumbers[8] : 90
randomNumbers[9] : 11