实验五 数组、指针与字符串

实验五 数组、指针与字符串

一、实验目的

1.学习使用数组处理相同类型的批量元素。

2.学习使用指针操作元素。

3.学习动态分配内存new和delete运算符。

4.学习用动态数组vector方式创建动态数组,学习使用指针和引用传递参数。

5.学习string类的常用方法。

二、实验内容

1.创建两个包含5个整数元素一维数组a[5]、b[5],及一个包含10个元素的数组c,实现以下操作(30分):

(1)手动输入元素(数值范围在1-100之间)初始化两个数组中的元素。

(2)编写选择法排序函数order(int a[],int n)。将a、b两个数组元素按照升序排序,然后打印到屏幕。

(3)复制数组a,b元素依次填充数组c。

2.使用new运算符创建具有10个元素的一维数组,实现以下操作(20分):

(1) 编写子函数bubbleSort(int arr[],int x)实现用冒泡排序算法将数组升序排序。

(2) 统计在排序过程中元素有多少次交换。

3.创建点的对象数组,包含10个点,编写函数对数组元素排序(按照各点距离原点的远近排列),在主函数中输出排序后的点及其距离值(25分)。10个点的坐标分别为: (-1,-3),(-2,-4),(1,3),(7,8),(-2,5),(3,-4),(5,3),(1,7),(6,3),(4,4)

4.用vector创建字符串数组对象,长度为5(30分)。

(1)手动输入以下5个英文句子,存入数组对象:

Do one thing at a time, and do well.

vAction speak louder than words.

Never put off what you can do today until tomorrow.

Like author, like book.

Knowledge makes humble, ignorance makes proud.

(2)编写函数,使得数组中的字符串按大小排序(按字符串比较的规则)。

(3)输出排序后的句子,并显示其长度。

5.请解释书上例题6-21与6-22中动态数组类深复制与浅复制的区别,并谈谈例题6-21发生了何种错误,应如何避免(5分)。

三、实验步骤及结果

题目1:

解题思路:

1.手动输入数组元素可以利用for循环来输入,但是注意需要判断输入值是否合法 要求整型数据1~100

2.选择排序升序即可 加上一个for循环来打印排序后的数组元素

3.复制数组并填充 可以用两个for循环来实现

程序代码:

/*
程序名:题目1.cpp
功能:创建两个包含5个整数元素一维数组a[5]、b[5],及一个包含10个元素的数组c,实现以下操作(30分):
(1)手动输入元素(数值范围在1-100之间)初始化两个数组中的元素。
(2)编写选择法排序函数order(int a[],int n)。将a、b两个数组元素按照升序排序,然后打印到屏幕。
(3)复制数组a,b元素依次填充数组c。                                            
日期:2021.11.24
版本:1.0
*/
#include <iostream>
using namespace std;
int a[5],b[5],c[10];//创建整形数组 
void order(int *a,int n)//选择法排序函数order(升序) 
{
	int min,i,j;
	for(i=0;i<n;i++)
	{
		min=i;
		for(j=i+1;j<n;j++)
		{
			if(a[j]<a[min])
			{
				min=j;
			}
		}
		if(j!=min)
		{
			int temp=a[min];
			a[min]=a[i];
			a[i]=temp;
		} 
	} 	
	cout <<"The swapped array is:" <<endl;
	for(int i=0;i<n;i++)//输出数组元素 
	{
	cout << a[i] << " ";
	}
	cout << endl;
}
void input(int *a)//input函数输入数组元素 
{
	cout << "Enter an array of length 5:"<< endl;
	for(int i=0;i<5;i++)//输入数组中的元素 
	{	
	re_enter:cin >> a[i] ;
		if(a[i]<1||a[i]>100) //判断输入数据是否合法1~100 如果不合法则重新输入 
		{
			cout<<"Illegal data was entered!"<< endl;
			cout<<"Please enter again!"<< endl;
			goto re_enter;//利用goto语句实现重新输入 
		}
	}
}
void fill(int *a,int *b,int *c) //fill函数实现将a b数组元素填充到c 
{
	for(int i=0;i<5;i++)//利用for循环将a b元素填充到c中 
	{
		c[i]=a[i];
	}
	for(int j=0;j<5;j++)
	{
		c[j+5]=b[j];
	}
	cout<< "The elements of array C are:"<<endl;
	for(int i=0;i<10;i++)//输出c数组元素 
	{
	cout << c[i] << " ";
	}
	cout << endl;
}
int main()
{
	input(a);//调用input函数输入数组a 
	order(a,5);//调用order函数对数组a进行排序并输出排序后数组元素 
	input(b); //调用input函数输入数组b 
	order(b,5);//调用order函数对数组b进行排序并输出排序后数组元素 
	fill(a,b,c);//调用fill函数将a b元素依次填充c 
	system("pause");
	return 0;
}

运行结果截图:
图片描述

题目2:

解题思路:

1.创建数组然后进行冒泡排序

2.交换次数可以在冒泡排序内部最里层循环中加一个count++,在主函数输出即可

程序代码:

/*
程序名:题目2.cpp
功能:使用new运算符创建具有10个元素的一维数组,实现以下操作(20分):
(1) 编写子函数bubbleSort(int arr[],int x)实现用冒泡排序算法将数组升序排序。
(2) 统计在排序过程中元素有多少次交换。
日期:2021.11.25
版本:1.0
*/
#include <iostream>
using namespace std;
int count=0;//用count来记录排序次数 
bubbleSort(int arr[],int x)//冒泡排序 
{
	for(int i=0;i<x;i++)
	{
		for(int j=0;j<x-1-i;j++)
		{
			int temp=arr[j];
			arr[j]=arr[j+1];
			arr[j+1]=temp;
			count++;
			 
		}
	}
} 
input(int arr[],int x)//输入数组元素 
{
	for(int i=0;i<x;i++)
	cin>> arr[i];
}
print(int arr[],int x)//打印数组元素 
{
	for(int i=0;i<x;i++)
	{
		cout << arr[i] << " " ;
	}
	cout << endl;
}
int main()
{
	int *p=new int[10];//使用new运算符创建具有10个元素的一维数组
	cout << "Please enter an array of five elements" << endl;
	input(p,10);//输入数组元素 
	cout << "The initial array is:" << endl;
	print(p,10);//打印初始数组 
	bubbleSort(p,10);//进行冒泡排序 
	cout << "The swapped array is:" << endl;
	print(p,10);//打印排序后的数组 
	cout << "The swap time are:" << endl;
	cout << count << endl;//打印排序次数 
	system("pause");
	return 0;
}

运行结果截图:
图片描述

题目3:

解题思路:

1.创建一个对象数组

2.首先计算每个点对应的distance,然后以distance来进行冒泡排序

3.打印坐标和距离

程序代码:

/*
程序名:题目3.cpp
功能:创建点的对象数组,包含10个点,编写函数对数组元素排序(按照各点距离原点的远近排列),在主函数中输出排序后的点及其距离值(25分)。
10个点的坐标分别为: (-1,-3),(-2,-4),(1,3),(7,8),(-2,5),(3,-4),(5,3),(1,7),(6,3),(4,4)
日期:2021.11.24
版本:1.0
*/
#include <iostream>
#include <math.h>
using namespace std;
class Point//Point类定义 
{
private://私有数据成员
	int x, y;
	double distance;
public://外部接口
	Point() {}//无参构造函数 
	Point(int xx, int yy) :x(xx), y(yy) {}//构造函数
	~Point() {}//析构函数
	void CalDistance(Point *point);//计算到原点的距离 
	void bubblesort(Point *point);//冒泡排序 
	void printarr(Point *point);//打印点的坐标和距离

};
void Point::CalDistance(Point *point)//计算到原点的距离 
{
	for (int i = 0; i < 10; i++)
	{
		point[i].distance = sqrt(point[i].x*point[i].x + point[i].y*point[i].y);
	}
}
void Point::bubblesort(Point *point)//冒泡排序 
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 9 - i; j++)
		{
			if (point[j].distance > point[j + 1].distance)
			{
				Point temp;
				temp = point[j];
				point[j] = point[j + 1];
				point[j + 1] = temp;
			}
		}
	}
}
void Point::printarr(Point *point)//打印点的坐标和距离
{
	for (int i = 0; i < 10; i++)
	{
		cout << "(" << point[i].x << "," << point[i].y << ")" << ":" << point[i].distance << endl;
	}
	cout << endl;
}
Point point[10] = { Point(-1,-3),Point(-2,-4),Point(1,3),Point(7,8),Point(-2,5),Point(3,-4),Point(5,3),Point(1,7),Point(6,3),Point(4,4) };//对象数组
int main()
{
	cout << "The original array is:" << endl;
	point[0].CalDistance(point);//计算到原点的距离
	point[0].printarr(point);//打印点的坐标和距离
	cout << "The following array is:" << endl;
	point[0].bubblesort(point);//根据距离对点进行冒泡排序
	point[0].CalDistance(point);//计算到原点的距离
	point[0].printarr(point);//打印点的坐标和距离
	system("pause");
	return 0;
}

运行结果截图:
图片描述

题目4:

解题思路:

1.用vector创建字符串数组对象

2.由于cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格、制表符或换行符)。一旦它接触到第一个非空格字符即开始阅读,当它读取到下一个空白字符时,它将停止读取。所以需要用getline函数来进行句子的输入,此函数可读取整行,包括前导和嵌入的空格,并将其存储在字符串对象中。配合for循环来输入

3.使用冒泡排序进行排序,其中字符串比较大小可以直接使用string类中已经重载好的操作符

4.string类中包含length()函数可以直接调用来获取字符串长度

5.输出句子以及长度即可
程序代码:

/*
程序名:题目4.cpp
功能:用vector创建字符串数组对象,长度为5(30分)。
(1)手动输入以下5个英文句子,存入数组对象:
 Do one thing at a time, and do well.
 vAction speak louder than words.
 Never put off what you can do today until tomorrow.
 Like author, like book.
 Knowledge makes humble, ignorance makes proud.
(2)编写函数,使得数组中的字符串按大小排序(按字符串比较的规则)。
(3)输出排序后的句子,并显示其长度。
日期:2021.11.25
版本:1.0
*/
#include <iostream>
#include <string>
#include <vector>
using namespace std;

void BubbleSort(vector<string>&str,int n)//冒泡排序
{
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (str[j] > str[j + 1])//string类中已经对操作符进行重载,可以直接用
			{
				string temp = str[j];
				str[j] = str[j + 1];
				str[j + 1] = temp;
			}
		}
	}
}
void printf(vector<string>str,int n)//打印数组 
{
	for (int i = 0; i < n; i++)
	{
		cout << str[i] << " length:" <<str[i].length() << endl;
	}
}

int main()
{
	vector<string>str(5);//创建字符串数组对象 
	cout << "Please enter English sentences:" << endl;
	for (int i = 0; i < 5; i++)
	{
		getline(cin, str[i]);//使用getline函数读取整行,包括前导和嵌入的空格,并将其存储在字符串对象中。
	}
	BubbleSort(str,5);//对数组进行排序 
	cout << "******************************************" << endl;
	cout << "The sorted sentences and their lengths are:" << endl; 
	printf(str, 5);//打印数组 
	system("pause");
	return 0;

}

运行结果截图:
图片描述

题目5:

请解释书上例题6-21与6-22中动态数组类深复制与浅复制的区别,并谈谈例题6-21发生了何种错误,应如何避免(5分)。

回答:

1.浅层复制:实现对象间数据元素的一一对应复制。

深层复制:当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指对象进行复制。

2.错误:默认复制构造函数实现的是浅层复制,复制的时候把指针里的内容原样搬到了数组2的指针里面,size的值也搬到里面,只实现了一一对应,导致两个指针存同一个地址,指向同一个数组内存单元,数组根本没有复制,只是把地址给复制了。这样移动数组对象1中的点,数组对象2的点也会被影响,同时析构数组对象1的时候已经把这个数组的内存单元释放了,析构数组对象2的时候又delete一遍,程序就出错了

3.解决方法:在类中增加一个复制构造函数,不使用系统默认的复制构造函数,程序实现深层拷贝。

例:

ArrayOfPoints(const ArrayOfPoints& v){
	size = v.size;
	points = new Point[size];
	for(int  i = 0;i<size;i++)
	points[i] = v.points[i];
}

四、实验小结

问题与解决办法:

问题1:输出浮点数的时候没有正确输出,输出数据变成了"non"

解决:nan :not a number等同于#IND:indeterminate (windows),一般是因为得到的数值,超出浮点数的表示范围,这个时候检查一下自己计算的时候有没有输错算术符号导致数据错误

问题2:在类的成员函数实现中无法调用私有数据成员

解决:忘记了成员函数在类外实现需要加类作用域符,成员函数无法调用私有数据成员

问题3:使用string字符串时候报错

解决:使用string类需要加头文件

心得体会:

1.在写类的时候还是会犯低级错误,比方说忘记加类作用域等低级错误,还是需要多去刷题来加强自己熟练度。

2.做题的时候想到了一种做题方法,但是其中的一步不会实现,这个时候应该通过查书,上csdn,或者问同学等方式去解决,比如如何输入字符串同时包括中间的空格,通过上网查询知道可以使用getline函数来输入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是一只大狸子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值