课后作业
chao_smile 2024/1/13
# 第十一课
# 1. 编写一个 C++程序,创建并自定义初始化一个m x n
的二维整数数组(m
和n
都小于或等于10
)。找出数组中的最大元素及其所在的行和列。
自定义二维数组,不需要输入
// 自定义示例:(题解不可同示例相同)
int matrix[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 输出:
最大元素是 9,位于第 3 行第 3 列。
历史解析
- 数组越界:
for
循环中,i
和j
的循环条件设置为i <= 3
和j <= 3
。这是不正确的,因为数组的索引应该从0
到2
。所以正确的条件应该是i < 3
和j < 3
- 多余的循环:内部的
k
循环是多余的。你只需要比较maxc[i][j]
和high
的值即可,不需要额外的循环。 - 判断逻辑错误: 当前的循环判断并未找出数组中的最大元素,仅仅是不断循环后单纯的判断
high
与最里层循环k
的最终值,即只是单纯的比较1
与9
(还是在maxc[0][0]=1
的情况下) - 自行检查错误:当程序打印后应按题目要求更新示例数组尝试查看是否符合说明,当将
maxc[2][2]
或任意一项更新为更大的数时,程序依旧打印9
- 数组越界:
参考答案
#include <iostream>
using namespace std;
int main(){
int maxc[3][3] = {
{1, 2, 3},
{4, 15, 6},
{7, 8, 9}
};
int high = maxc[0][0];
int endi = 0, endj = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (maxc[i][j] > high) {
high = maxc[i][j];
endi = i;
endj = j;
}
}
}
cout << "最大元素是 " << high << ",位于第 " << (endi + 1) << " 行第 " << (endj + 1) << " 列" << endl;
return 0;
}
# 2. 编写一个 C++程序,创建并自定义初始化一个m x n
的二维整数数组(m
和n
都小于或等于10
)。计算并输出每一行元素的总和以及每一列元素的总和。
自定义二维数组,不需要输入
// 自定义示例:(题解不可同示例相同)
int matrix[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
// 输出:
行 1 的总和: 6
行 2 的总和: 15
列 1 的总和: 5
列 2 的总和: 7
列 3 的总和: 9
历史解析
- 运行错误:程序运行报错,完成程序编写后应至少自行运行检查一次
- 数组定义和初始化错误:在定义数组
maxc
时,元素列表之间应该用逗号分隔 - 数组越界:循环中数组的索引超出了其定义的范围。对于一个
2x3
数组,有效的索引是matrix[0][0]
到matrix[1][2]
- 计算逻辑错误:行和列的总和计算不正确。对于行总和,应遍历每一行的所有列;对于列总和,应遍历每一列的所有行
- 打印格式:建议用
cout
,避免发生format
错误
参考答案
#include <iostream>
using namespace std;
int main() {
int matrix[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
// 计算每一行的总和
for (int i = 0; i < 2; ++i) {
int rowSum = 0;
for (int j = 0; j < 3; ++j) {
rowSum += matrix[i][j];
}
cout << "行 " << i + 1 << " 的总和: " << rowSum << endl;
}
// 计算每一列的总和
for (int j = 0; j < 3; ++j) {
int colSum = 0;
for (int i = 0; i < 2; ++i) {
colSum += matrix[i][j];
}
cout << "列 " << j + 1 << " 的总和: " << colSum << endl;
}
return 0;
}
# 3. 编写一个 C++程序,创建一个n x n
的整数矩阵,并初始化它。然后计算并输出这个矩阵主对角线(从左上到右下)和副对角线(从右上到左下)上的元素之和。假设n
是一个小于或等于10
的正整数。
自定义二维数组,不需要输入
// 自定义示例:(题解不可同示例相同)
int matrix[4][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}
};
// 输出:
主对角线之和: 34
副对角线之和: 34
解析
- 主对角线之和计算:
- 主对角线是指矩阵从左上角到右下角的那条对角线
- 在一个
n x n
的矩阵中,主对角线上的元素都是那些行索引和列索引相等的元素,即元素matrix[i][i]
,其中i
是从0
到n-1
的索引 - 在此程序中,
n
是4
,所以我们需要计算matrix[0][0]
,matrix[1][1]
,matrix[2][2]
, 和matrix[3][3]
- 循环中使用
mainDiagonalSum += matrix[i][i];
做这个计算
- 副对角线之和计算:
- 副对角线是指矩阵从右上角到左下角的那条对角线
- 在一个
n x n
的矩阵中,副对角线上的元素是那些行索引和列索引之和等于n-1
的元素,即元素matrix[i][n-1-i]
。 - 在此程序中,对于
4x4
的矩阵,需要计算的是matrix[0][3]
,matrix[1][2]
,matrix[2][1]
, 和matrix[3][0]
- 循环中使用
secondaryDiagonalSum += matrix[i][3 - i];
做这个计算
- 主对角线之和计算:
参考答案
#include <iostream>
using namespace std;
int main() {
int matrix[4][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}
};
int mainDiagonalSum = 0, secondaryDiagonalSum = 0;
for (int i = 0; i < 4; ++i) {
mainDiagonalSum += matrix[i][i];
secondaryDiagonalSum += matrix[i][3 - i];
}
cout << "主对角线之和: " << mainDiagonalSum << endl;
cout << "副对角线之和: " << secondaryDiagonalSum << endl;
return 0;
}
# 4. 编写一个 C++程序,完成以下任务:
- 定义一个字符数组
char myArray[10];
并使用字符初始化数组,使其包含 "Hello"。
- 定义一个字符数组
- 使用循环输出数组
myArray
的每个字符。
- 使用循环输出数组
- 更改
myArray
中的第三个字符('l')为 'x',然后再次输出整个数组。
- 更改
// 输出示例
H e l l o
H e x l o
历史解析
- 运行错误:程序运行报错,完成程序编写后应至少自行运行检查一次
- 字符数组的初始化:当初始化字符数组时,应使用单引号
' '
而非双引号" "
, 因为双引号用于字符串字面量,而单引号用于单个字符。数组mychar
中包含超过5
个字符Hello!
,但题目只要求包含Hello
。 - 循环输出数组:循环条件应该是遍历数组的有效长度,即字符串
Hello
的长度,抑或是数组长度,而非固定的1
到8
。没有必要定义j
我们可以直接循环数组内容打印。检查if(i == "")
是无效的,因为i
是整数,不能与空字符串比较。 - 修改数组中的字符: 要将第三个字符(索引为 2)更改为
x
,应该使用单引号
参考答案
#include <iostream>
using namespace std;
int main() {
const int n=10;
char myArray[n] = "Hello";
// 输出数组的每个字符
for (int i = 0; i<n; i++) {
cout << myArray[i] << ' ';
}
cout << "\n";
myArray[2] = 'x'; // 更改第三个字符为 'x'
// 再次输出修改后的数组
for (int i = 0; i<n; i++) {
cout << myArray[i] << ' ';
}
cout << "\n";
return 0;
}
// 利用结束符
#include <iostream>
using namespace std;
int main() {
char myArray[10] = {'H', 'e', 'l', 'l', 'o', '\0'}; // 初始化数组,包含字符串 "Hello" 和结束符 '\0'
// 输出数组的每个字符
for (int i = 0; myArray[i] != '\0'; i++) {
cout << myArray[i] << ' ';
}
cout << "\n";
myArray[2] = 'x'; // 更改第三个字符为 'x'
// 再次输出修改后的数组
for (int i = 0; myArray[i] != '\0'; i++) {
cout << myArray[i] << ' ';
}
cout << "\n";
return 0;
}
# 5. 编写一个 C++程序,执行以下操作:
- 使用
string
类型定义一个字符串str
,并初始化为 "Welcome to C++ !"。
- 使用
- 输出字符串
str
的长度。
- 输出字符串
- 将
str
中的 "C++" 替换为 "Java"。
- 将
- 输出修改后的字符串
str
。
- 输出修改后的字符串
提示:使用 string 类型的 find 方法可以查找字符串位置, replace 方法可以更改字符串中的特定部分,
// 输出示例
字符串的长度: 16
修改后的字符串: Welcome to Java !
历史解析
- 字符串的初始化:题目要求
Welcome to C++ !
,你定义的Welcome to C++!
,初始变量错误,导致字符串的长度错误,方法没问题 - 替换字符串:在使用
replace
方法时,你直接替换了从索引11
开始的3
个字符。这种方法在当前的情境下有效,更好的方法是使用find
方法来确定C++
的确切位置。如果字符串str
发生变化,这种方法仍然有效 - 字符串输出:没必要创建新的字符串
latestStr
,replace
方法会修改原字符串str
,所以可以直接输出str
- 字符串的初始化:题目要求
参考答案
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Welcome to C++!";
int length = str.length();
cout << "字符串的长度: " << length << endl;
// size_t 是 C++ 中的一种无符号整数类型,用于表示对象的大小或索引
size_t pos = str.find("C++");
// 在 C++ 中,string::npos 是一个常量,用于表示 string 类中某些函数(如 find)返回的特殊值,
// 它表示没有找到指定的子字符串或字符
// 这个常量实际上是 string 类的最大可能长度,通常定义为 -1,
// (-1 但这不是一个安全的假设。在一些架构或编译器中,这种转换可能导致不同的结果,甚至可能是一个很大的正整数),
// 但由于它是无符号类型,所以它表现为最大的无符号值。
if (pos != string::npos) {
// replace 方法会修改原字符串 str,所以可以直接输出 str
str.replace(pos, 3, "Java");
}
cout << "修改后的字符串: " << str << endl;
return 0;
}
// 尝试打印 int pos = str.find("test"); pos值
// 可以发现为 -1 因为 str 中没有 "test" 且使用 int 定义进行了隐式转换
// 注意会受不同的编译器影响,故此建议使用 size_t & string::npos 写法
// 故此也可通过以下方式求解(仅作了解)
int pos = str.find("C++");
if (pos != -1) {
// ...code
}