面向对象程序设计——Visual C++
第4章 数组
1、在C++中如何实现两个大小相同的整型数组间的赋值?对字符数组又该如何处理?
在C++中,可以使用循环遍历两个大小相同的整型数组,将一个数组的元素赋值给另一个数组的对应元素。例如:
int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5];
for (int i = 0; i < 5; i++) {
arr2[i] = arr1[i];
}
对于字符数组,可以使用字符串库函数strcpy()
或memcpy()
来进行赋值操作。例如:
char str1[10] = "hello";
char str2[10];
strcpy(str2, str1); // 使用strcpy()函数
// 或者
memcpy(str2, str1, sizeof(str1)); // 使用memcpy()函数
需要注意的是,使用字符串库函数进行字符数组的赋值操作时,需要保证目标字符数组有足够的空间来存储源字符数组的内容。
2、在C++中,数组a[3][4]中元素在内存中是按怎样的顺序存放的?
在C++中,多维数组的元素在内存中是按照行优先的顺序存放的,也就是说,对于数组a[3][4],它的元素在内存中的存放顺序是a[0][0]、a[0][1]、a[0][2]、a[0][3]、a[1][0]、a[1][1]、a[1][2]、a[1][3]、a[2][0]、a[2][1]、a[2][2]、a[2][3]。这是因为在内存中,数组的元素是按照一维数组的方式存储的,而多维数组可以看作是一维数组的扩展,因此在存储时也是按照一维数组的方式进行存储的。在行优先的存储方式中,每一行的元素都是连续存储的,因此可以提高访问效率。
3、在C++中,数组作为函数的参数有什么特点?如何将一个数组传递给它?
在C++中,数组作为函数的参数有以下特点:
- 数组作为函数参数时,实际上传递的是数组的地址,而不是数组本身。
- 数组作为函数参数时,数组的大小必须在函数定义时指定,否则无法正确访问数组元素。
- 数组作为函数参数时,可以使用指针或引用来传递。 将一个数组传递给函数的方法有以下几种:
- 使用指针传递数组:在函数定义时,将数组参数声明为指针类型,然后将数组的地址作为实参传递给函数。
- 使用引用传递数组:在函数定义时,将数组参数声明为引用类型,然后将数组作为实参传递给函数。
- 使用数组名传递数组:在函数定义时,将数组参数声明为数组类型,然后将数组名作为实参传递给函数。在函数内部,可以通过下标访问数组元素。
例如,下面是使用指针传递数组的示例代码:
void printArray(int *arr, int size) {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
printArray(arr, 5);
return 0;
}
在上面的代码中,printArray函数接受一个指向int类型的指针和一个整数参数,表示数组的大小。在main函数中,定义了一个包含5个元素的整型数组arr,并将其作为实参传递给printArray函数。在printArray函数内部,使用指针访问数组元素并输出。
4、在C++中应用函数strcpy()和strcat()时,都要注意什么问题?
在C++中应用函数strcpy()和strcat()时,需要注意以下问题:
- 目标字符数组必须有足够的空间来存储源字符数组的内容,否则会导致内存溢出和程序崩溃。
- 源字符数组必须以空字符'\0'结尾,否则会导致字符串拼接错误。
- 在使用strcat()函数时,需要保证目标字符数组已经包含了一个完整的字符串,否则会导致字符串拼接错误。
- 在使用strcpy()和strcat()函数时,需要注意字符数组的长度,避免越界访问。
- 在使用strcpy()和strcat()函数时,需要注意字符数组的类型,避免类型不匹配导致的编译错误。
- 在使用strcpy()和strcat()函数时,需要注意字符数组的编码方式,避免出现乱码问题。
习题
1、判断下列各题是否正确。如果不正确,请说明原因。
(1)数组可以存放许多不同类型的数值。
(2)数组下标可以为float数据类型。
(3)如果初始值表中的初始化值少于数组元素个数,则其余元素自动初始化为零。
(4)初始值表中的初始值的数量可以多余数组元素个数。
(5)将某个数组元素传递给函数并修改该元素值,那么在被调用函数执行结束时仍保留修改后的值。
(1) 不正确。
数组是一组相同类型的数据的集合,不能存放不同类型的数值。
(2) 不正确。
数组下标必须是整数类型,float数据类型无法作为数组下标。
(3) 正确。
如果初始值表中的初始化值少于数组元素个数,则其余元素自动初始化为零。
(4) 不正确。
如果初始值表中的初始值的数量多于数组元素个数,编译器将会报错。
(5) 正确。
将数组元素传递给函数并修改该元素值,可以在被调用函数执行结束时保留修改后的值。
2、设计一个程序,输入数组int a[10]的每一个元素,并求该数组中奇数的个数和平均值以及偶数的个数和平均值。
#include <iostream>
using namespace std;
int countOdd(int a[], int n, double& oddAvg) { // 统计奇数的个数和平均值
int count = 0;
double sum = 0;
for (int i = 0; i < n; i++) {
if (a[i] % 2 == 1) {
count++;
sum += a[i];
}
}
if (count > 0) {
oddAvg = sum / count;
}
return count;
}
int countEven(int a[], int n, double& evenAvg) { // 统计偶数的个数和平均值
int count = 0;
double sum = 0;
for (int i = 0; i < n; i++) {
if (a[i] % 2 == 0) {
count++;
sum += a[i];
}
}
if (count > 0) {
evenAvg = sum / count;
}
return count;
}
int main() {
int a[10];
double oddAvg = 0, evenAvg = 0;
int oddCount, evenCount;
for (int i = 0; i < 10; i++) {
cout << "请输入第" << i + 1 << "个数:";
cin >> a[i];
}
oddCount = countOdd(a, 10, oddAvg);
evenCount = countEven(a, 10, evenAvg);
cout << "奇数的个数是:" << oddCount << endl;
cout << "奇数的平均值是:" << oddAvg << endl;
cout << "偶数的个数是:" << evenCount << endl;
cout << "偶数的平均值是:" << evenAvg << endl;
return 0;
}
请输入第1个数:1
请输入第2个数:2
请输入第3个数:3
请输入第4个数:4
请输入第5个数:5
请输入第6个数:6
请输入第7个数:7
请输入第8个数:8
请输入第9个数:9
请输入第10个数:10
奇数的个数是:5
奇数的平均值是:5
偶数的个数是:5
偶数的平均值是:6
3、设计一个程序,输入数组a[10]的每一个元素,再输入一个数x,检查a中是否有值为x的元素,若有,则输出其下标,否则,输出-1。
#include <iostream>
using namespace std;
const int ARRAY_SIZE = 10;
int main() {
int a[ARRAY_SIZE], x, index = -1;
// 输入数组a的每一个元素
cout << "Please input " << ARRAY_SIZE << " elements of the array:" << endl;
for (int i = 0; i < ARRAY_SIZE; i++) {
cin >> a[i];
}
// 输入数x
cout << "Please input a number:" << endl;
cin >> x;
// 在数组a中查找x的下标
for (int i = 0; i < ARRAY_SIZE; i++) {
if (a[i] == x) {
index = i;
break;
}
}
// 输出结果
if (index != -1) {
cout << "The index of " << x << " is " << index << endl;
} else {
cout << "No element equals to " << x << " in the array." << endl;
}
return 0;
}
4、求200以内所有素数之和。
#include <iostream>
using namespace std;
const int MAX_NUM = 200;
int main() {
bool is_prime[MAX_NUM + 1] = {false};
int sum = 0;
// 筛选法判断素数
for (int i = 2; i <= MAX_NUM; i++) {
if (!is_prime[i]) {
sum += i; // 累加素数
for (int j = i * 2; j <= MAX_NUM; j += i) {
is_prime[j] = true;
}
}
}
// 输出结果
cout << "The sum of prime numbers between 2 and " << MAX_NUM << " is " << sum << endl;
return 0;
}
5、17人围成圈,依次编号为1~17,从第1号开始报数,报到3的倍数的人离开,一直数下去,直到最后只剩下1人。求此人的编号。
# 使用链表
#include <iostream>
using namespace std;
const int NUM_PEOPLE = 17;
const int MULTIPLE = 3;
// 循环链表结构体定义
struct Node {
int val;
Node* next;
};
int main() {
Node* head = new Node(); // 创建循环链表
head->val = 1;
head->next = head;
// 添加其他节点
Node* cur = head;
for (int i = 2; i <= NUM_PEOPLE; i++) {
Node* node = new Node();
node->val = i;
node->next = head;
cur->next = node;
cur = node;
}
// 模拟报数过程
Node* prev = cur;
cur = head;
while (cur->next != cur) {
for (int i = 1; i < MULTIPLE; i++) {
prev = cur;
cur = cur->next;
}
prev->next = cur->next;
delete cur;
cur = prev->next;
}
// 输出结果
cout << "The last person's number is " << cur->val << endl;
return 0;
}
# 使用数组
#include <iostream>
using namespace std;
const int NUM_PEOPLE = 17;
const int MULTIPLE = 3;
int main() {
bool people[NUM_PEOPLE] = {true}; // 初始化,所有人都在圈内
int count = 0; // 计数器,从0开始计数
int remaining = NUM_PEOPLE; // 剩余人数,初始为总人数
// 模拟报数过程
int i = 0;
while (remaining > 1) {
if (people[i]) {
count++;
if (count == MULTIPLE) {
people[i] = false;
count = 0;
remaining--;
}
}
i = (i + 1) % NUM_PEOPLE; // 取余实现循环
}
// 输出结果
for (int i = 0; i < NUM_PEOPLE; i++) {
if (people[i]) {
cout << "The last person's number is " << (i + 1) << endl;
break;
}
}
return 0;
}
6、设计一个程序,利用插入排序算法,对具有n个元素的数组a排序(升序)。
#include <iostream>
using namespace std;
const int MAX_SIZE = 100; // 定义数组的最大容量
int main() {
int n; // 元素个数
int a[MAX_SIZE]; // 定义数组a
cout << "Enter the number of elements: ";
cin >> n;
// 输入n个元素
cout << "Enter " << n << " elements:" << endl;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
// 插入排序算法
for (int i = 1; i < n; i++) {
int temp = a[i]; // 当前元素
int j = i - 1; // 已排序序列的最后一个元素的下标
// 比较并插入当前元素
while (j >= 0 && a[j] > temp) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = temp;
}
// 输出排序后的数组
cout << "The sorted array is:" << endl;
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
cout << endl;
return 0;
}
7、设计一个函数:
void reverse(int a[], int n);
颠倒数组a的前n个元素的顺序。例如对于数组a,假设其初始值为{1,2,3,4,5,6,7,8},则经过函数调用reverse(a,5)之后,数组a变为:{5,4,3,2,1,6,7,8}.
#include <iostream>
using namespace std;
void reverse(int a[], int n) {
int left = 0; // 左指针
int right = n - 1; // 右指针
// 双指针交换元素
while (left < right) {
int temp = a[left];
a[left] = a[right];
a[right] = temp;
left++;
right--;
}
}
int main() {
int a[] = {1, 2, 3, 4, 5, 6, 7, 8}; // 定义数组a
int n = 5; // 前n个元素
cout << "Before reverse: ";
for (int i = 0; i < 8; i++) {
cout << a[i] << " ";
}
cout << endl;
reverse(a, n); // 颠倒前n个元素顺序
cout << "After reverse: ";
for (int i = 0; i < 8; i++) {
cout << a[i] << " ";
}
cout << endl;
return 0;
}
8、设计一个函数:
void add(int a[],int b[],int n);
将数组b的前n个元素加到数组a的相应的前n个元素上。
#include <iostream>
using namespace std;
void add(int a[], int b[], int n) {
for (int i = 0; i < n; i++) {
a[i] += b[i]; // 将b[i]加到a[i]上
}
}
int main() {
int a[] = {1, 2, 3, 4, 5}; // 定义数组a
int b[] = {5, 4, 3, 2, 1}; // 定义数组b
int n = 3; // 前n个元素
cout << "Before add: ";
for (int i = 0; i < 5; i++) {
cout << a[i] << " ";
}
cout << endl;
add(a, b, n); // 将b的前n个元素加到a的前n个元素上
cout << "After add: ";
for (int i = 0; i < 5; i++) {
cout << a[i] << " ";
}
cout << endl;
return 0;
}
9、设计一个函数:
bool removeFirst(float a[], int n, float x); 该函数从数组a的查找x。如果找到x,则删除找到的第一个x,该位置以后所有元素依次向前移动一位,并返回true表示删除成功。如果为找到x,则数组不变,并返回false。
#include <iostream>
using namespace std;
bool removeFirst(float a[], int n, float x) {
int i, j;
bool found = false;
// 在数组中查找第一个值为x的元素
for (i = 0; i < n; i++) {
if (a[i] == x) {
found = true; // 找到了值为x的元素
break;
}
}
if (!found) {
return false; // 没有找到值为x的元素,返回false表示删除失败
}
// 找到了值为x的元素,将其删除
for (j = i; j < n - 1; j++) {
a[j] = a[j + 1]; // 将元素依次向前移动一位
}
return true; // 删除成功,返回true
}
int main() {
float a[] = {1.1, 2.2, 3.3, 4.4, 5.5}; // 定义数组a
int n = 5; // 数组a的元素个数
float x = 3.3; // 要查找的值
cout << "Before removeFirst: ";
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
cout << endl;
bool success = removeFirst(a, n, x); // 在数组a中查找并删除第一个值为x的元素
if (success) {
n--; // 删除成功,将数组a的元素个数减1
cout << "After removeFirst: ";
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
cout << endl;
} else {
cout << "Failed to remove " << x << endl;
}
return 0;
}
10、求矩阵Amn与Bmn的和矩阵Cmn和差矩阵Dmn。
#include <iostream>
using namespace std;
const int MAX_SIZE = 100;
void matrixSum(int A[][MAX_SIZE], int B[][MAX_SIZE], int C[][MAX_SIZE], int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
C[i][j] = A[i][j] + B[i][j];
}
}
}
void matrixDiff(int A[][MAX_SIZE], int B[][MAX_SIZE], int D[][MAX_SIZE], int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
D[i][j] = A[i][j] - B[i][j];
}
}
}
int main() {
int m, n;
cout << "请输入矩阵的行数和列数:";
cin >> m >> n;
int A[MAX_SIZE][MAX_SIZE], B[MAX_SIZE][MAX_SIZE];
cout << "请输入矩阵A:" << endl;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cin >> A[i][j];
}
}
cout << "请输入矩阵B:" << endl;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cin >> B[i][j];
}
}
int C[MAX_SIZE][MAX_SIZE], D[MAX_SIZE][MAX_SIZE];
matrixSum(A, B, C, m, n);
matrixDiff(A, B, D, m, n);
cout << "A + B = " << endl;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cout << C[i][j] << " ";
}
cout << endl;
}
cout << "A - B = " << endl;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cout << D[i][j] << " ";
}
cout << endl;
}
return 0;
}
11、设计一个程序,求5*5矩阵两对角线元素之和。
#include<iostream>
using namespace std;
int main() {
const int size = 5; // 矩阵的大小
int matrix[size][size]; // 定义二维数组表示矩阵
int sum = 0; // 两对角线元素之和
// 输入矩阵元素
cout << "请输入矩阵元素:" << endl;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
cin >> matrix[i][j];
}
}
// 计算两对角线元素之和
for (int i = 0; i < size; i++) {
sum += matrix[i][i]; // 主对角线上的元素
sum += matrix[i][size - i - 1]; // 副对角线上的元素
}
// 输出结果
cout << "两对角线元素之和为:" << sum << endl;
return 0;
}
12、设计一个函数:int strlen(char s[]);
求出字符串s中所包含的字符的个数,并作为函数的返回值(要求不使用库函数strlen())。
#include<iostream>
using namespace std;
int strlen(char s[]) {
int length = 0; // 字符串的长度
while (s[length] != '\0') { // 当前字符不是字符串的结尾标志 '\0',就继续往后遍历
length++; // 字符串长度加1
}
return length; // 返回字符串长度
}
int main() {
char str[] = "Hello, world!"; // 测试字符串
int length = strlen(str); // 求字符串长度
cout << "字符串 " << str << " 的长度为:" << length << endl;
return 0;
}
13、设计一个函数:void strcpy(char s1[], char s2[]);
实现将字符串s2拷贝给字符串s1(要求不要使用库函数strcpy())。
#include<iostream>
using namespace std;
void strcpy(char s1[], char s2[]) {
int i = 0; // 下标从0开始
while (s2[i] != '\0') { // 当前字符不是字符串的结尾标志 '\0',就继续往后拷贝
s1[i] = s2[i]; // 拷贝字符
i++; // 下标加1
}
s1[i] = '\0'; // 拷贝完后在字符串s1的末尾加上结尾标志 '\0'
}
int main() {
char str1[100]; // 目标字符串
char str2[] = "Hello, world!"; // 源字符串
strcpy(str1, str2); // 将源字符串拷贝给目标字符串
cout << "拷贝后的字符串为:" << str1 << endl;
return 0;
}
14、设计一个函数:void strcat(char s1[], char s2[]);
实现将字符串s2加到字符串s1的末尾(要求不使用库函数strcat())。
#include<iostream>
using namespace std;
void strcat(char s1[], char s2[]) {
int i = 0, j = 0; // 下标从0开始
while (s1[i] != '\0') { // 找到字符串s1的结尾标志 '\0'
i++; // 下标加1
}
while (s2[j] != '\0') { // 将字符串s2的每个字符加到s1的末尾
s1[i] = s2[j];
i++;
j++;
}
s1[i] = '\0'; // 在字符串s1的末尾加上结尾标志 '\0'
}
int main() {
char str1[100] = "Hello"; // 目标字符串
char str2[] = ", world!"; // 待加入的字符串
strcat(str1, str2); // 将str2加入str1
cout << "拼接后的字符串为:" << str1 << endl;
return 0;
}
实验题
2、完成下列程序,并上机验证其正确性。
该程序重新排列a[N]的元素,使相等的元素放在一起,并保持它们在数组中第一次出现的相对位置。例如:
原数组:2 4 3 5 2 3 4 5 2 3
重排后:2 2 2 4 4 3 3 3 5 5
采用的算法是:统计各不同元素出现的次数(存放在数组c中),并依次记录下这些不同的元素,用数组b[j]标识a的第j个元素是否在前面出现过。最后按各元素重复排列的次数写回到数组a中。
#include <iostream.h>
#define N 10
void main(){
int a[N],b[N],c[N], i, j, k, j;
cout<<”输入数组a中的各元素:\n”;
for(i=0;i<N;i++){
b[i]=c[i]=i;
cin>>a[i];
}
k=0;
for(i=0;i<N;i++)
if(___________){
a[k]=a[i];
for(_____;j<N;j++)
if(a[j]==a[i])
b[j]=0;c[k]++;
__________;
}
t=N-1;
for(i=k-1;i>=0;i--)
for(j=0;__________;j++)
__________;
for(i=0;i<N;i++)
cout<<a[i]<<’\t’;
cout<<’\n’;
}
3、完成下列程序,并上机验证其正确性。
该程序的功能是输入正整数num,按从小到大的次序输出它的所有的因子。所利用的算法是:i从2开始,如果num能整除i,则可以得到一大一小两个因子,将它们分别放在数组a的两端。
#define N 40
void main(){
int num, t, i, j=0, k, a[N];
cout<<”请输入一个正整数:\n”;
cin>>num;
i=2, t=num;
k=N-1;
a[0]=1, a[N-1]=num;
while(i<t){
if(__________){
t=num/i;
a[++j]=i;
if(i<t)
__________;
}
__________;
}
cout<<”整数”<<num<<”的因子依次为:”;
for(i=0;i<=j;i++)cout<<a[i]<<’\t’;
for(i=k;i<N;i++)cout<<a[i]<<’\t’;
cout<<’\n’;
}
第一空:num%i==0;
第二空:a[--k]=t
第三空:i++
程序的主要思路是:
- 从2开始遍历到num的平方根,如果num能够整除i,则num除以i就是另一个因子。
- 将两个因子分别放在数组a的两端。
- 输出数组a。 程序的正确性可以通过以下测试验证:
- 输入:12。输出:1 2 3 4 6 12。
- 输入:25。输出:1 5 25。
- 输入:27。输出:1 3 9 27。
- 输入:35。输出:1 5 7 35。
- 输入:50。输出:1 2 5 10 25 50。