《C++程序设计上机实践及学习辅导》实验报告


《C++程序设计上机实践及学习辅导》实验报告

额…本人大一新生,刚接触C++,学期末作业是这本书的实验报告,其中有十几个实验内容,这是我们新生第一学期的课,所以内容也很基础。但我也是新接触,外加C++课上无数次走神加之课后作业迷迷糊糊,所以现在感觉还是很菜因此也是硬着头皮完成作业,相信会遇到很多障碍,便在这里记录一下自己的学习过程。还请各位大佬多多指教,希望自己能在这条路上一直走下去。
2020.12.30,19:35.


实验一、简单程序设计


1.编写程序,计算圆的面积,半径从键盘输入。


#include<iostream>
using namespace std;

int main()
{
	double r;					//定义半径r
	cin >> r;					//输入半径r
	const double Pi = 3.14;		//定义常量π为3.14
	double S;					//定义面积S
	S = Pi * r * r;				//计算S
	cout << "半径为 " << r << " 的圆的面积为 " << S << endl;
								//输出面积S	
	return 0;					// atFuRYh
}

运行结果如下在这里插入图片描述

这个挺简单的一个,毕竟第一个实验。

2.编写程序,已知三角形的三边a、b、c,求三角形的周长和面积。

#include <iostream>
#include<cmath>

using namespace std;
int main()
{
	double a=3, b=5, c=4;		//定义三边,且长度已知
	
	double C = a + b + c;		//定义周长C,为abc的和
	
	double CosC = (a * a + b * b - c * c) / (2 * a * b);

	double SinC = sqrt(1 - (CosC * CosC));
	double S = 1 / 2 * a * b * SinC;

	cout << "三角形的周长为" << C << endl;
	cout << "三角形的面积为" << S << endl;
	
	return 0;
}

这是第一次编写完成的,发现输出周长正常,面积为0,遂进行调试。调试发现SinC的值出了问题。
检查半天未果,叫舍友帮忙,结果发现SinC也没问题。。是我调试没调试对,然后发现问题出在了这里,原因是我没有加括号。

double S = 1 / 2 * a * b * SinC;

加上括号改成了这样,结果还是不对。。提示未定义标识符。。又搞了半天发现是用了中文输入法的括号搞的,所以出了问题。改后,OK。

double S = (a * b * SinC)/2;

贴上最终的代码

#include <iostream>
#include<cmath>

using namespace std;
int main()
{
	double a=3, b=5, c=4;		//定义三边,且长度已知
	
	double C = a + b + c;		//定义周长C,为abc的和
	
								//以下为求面积部分,将使用余弦定理计算。
	double CosC = (a * a + b * b - c * c) / (2 * a * b);	//利用余弦定理求CosC

	double SinC = sqrt(1 - (CosC * CosC));					//求SinC
	double S = (a * b * SinC)/2;							//求面积

	cout << "三角形的周长为" << C << endl;
	cout << "三角形的面积为" << S << endl;
	
	return 0;												    //atFuRYh

}

输出结果在这里插入图片描述


实验二 循环结构程序设计

1. 要求设计一个函数,求出一元二次方程ax2+bx+c=0的实根,系数a,b,c的值从键盘上输入,求方程根的计算公式为x=,当b2-4ac小于0时,输出“无实根!”;否则输出x的两个实根。

#include<iostream>
using namespace std;

void Gen(int a,int b,int c)
{
	double X1,X2;
	double De = b ^ b - 4 * a * c;
	X1 = (-b + sqrt(De)) / 2 * a;
	X2 = (-b - sqrt(De)) / 2 * a;
	if (De < 0)
		cout << "无实根" << endl;
	
	if (De ==0)
		cout << "X1=X2=" << X1 << endl;
	if (De > 0)
		cout << "X1=" << X1 << endl<<"X2=" << X2 << endl;
	
}

int main()
{
	Gen(1, -2, 1);
	return 0;
}

运行结果为X1=2,X2=0,显然不对劲…遂进行调试,发现De=4,显然出错了。。然后开始找原因。发现…是b*b打错打成了b^b,改掉后一切正常。

但是在此处报错,提示如图。虽然未发现此报错影响结果但还是尝试解决,遂去百度。在这里插入图片描述
百度了错误代码后发现看不懂。。。在知乎找到如下回答

这个意思是你两个float型相+之后,会再转换为double输入给函数,编译器认为既然你最后会转为double型、那么float型可能装不下你那两个float型的相+结果,存在溢出风险解决只需要float相+的两个数任一强转double就行了,不过你如果很清楚不会溢出的话只需无视即可另一常出现这个警告的情况是 地址+整*整
作者:袁方
链接:https://www.zhihu.com/question/352977886/answer/1187047126

可能还是因为我自己基础不扎实反正我还是看不懂,大概理解为float形的存储空间达到了上限制,改成double就好。但,我的本来就是double咋搞呢?于是看到了下面第二种解决方案,地址+整+整,于是猜想是不是我b*b让编译器误以为这是一个地址了呢?于是更改为b^2,报错解决。
题目中还要求abc通过键盘输入,更改后完整代码如下。

#include<iostream>
using namespace std;

void Gen()							//定义函数Gen,求根函数
{
	int a,b,c;						//定义abc
	cin >> a;						//通过键盘输入abc
	cin >> b;
	cin >> c;
	double X1,X2;					//定义两根X1,X2
	double De = b^2- (4 * a * c);	//定义De
	X1 = (-b + sqrt(De)) / 2 * a;	//计算X1、X2
	X2 = (-b - sqrt(De)) / 2 * a;
	if (De < 0)						//<0
		cout << "无实根" << endl;
	
	if (De ==0)						//==0
		cout << "X1=X2=" << X1 << endl;
	if (De > 0)						//>0
		cout << "X1=" << X1 << endl<<"X2=" << X2 << endl;	       //atFuRYh
	
}

int main()
{
	Gen();
	return 0;
}

本次编程中还犯了一个错误,就是判断De=0时候没写成==,报错后才发现。

做到后面突然回头看这里,发现又有了错误。。改成b^2之后,计算出来的De不对,而且我不知道怎么出了问题。。改回去b*b之后又出现了上述报错但计算结果正确了。。然后想了一下才发现…C++中的 ^ 根本不是表示平方,得用pow函数。于是返回头cmath一下,然后pow(b,2)解决了这个问题。
感觉也是一个经常不注意就能犯了的错误吧…^ 可不是次方符号哈哈。

2. 编写程序,求出1~599中能被3整除,且至少有一位数字为5的所有整数。如15,51,513均是满足条件的整数。 运行结果为15 45 51 54 57 … 594 597等,共66个数。

能被3整除好说,主要是含有5有点复杂…于是大概思考,准备用与或非来写。表达含有5的部分大概思路为:如果除以10余数为5,那么说明最后一位是5.如果除以100为5,那么说明第一位为5,如果减去百位,再除以10的余数为5,那么说明十位为5。

#include<iostream>
using namespace std;
int main()
{
	int j = 0;
	for (int i = 1; i < 600; i++)
	{
		
		if (i % 3 == 0 && (i % 10 == 5 || i / 100 == 5 || (i - (i / 100)) / 10 == 5))
		{
			cout << i << endl;
			j++;
			
		}
	}
	cout << j << endl;
	return 0;
}

加了一个j,用来统计一共输出了多少位。便于校对答案正确与否。但发现…输出了53个,与题目告的66个差了不少,,所以又得回去检查- -(除了第一题仿佛没有哪个题一次对了)

发现错误在这里

(i - (i / 100)) / 10 == 5)

我i/100忘了乘以100…加上之后就OK了。去除掉j,得到最终代码如下

#include<iostream>
using namespace std;
int main()
{
	for (int i = 1; i < 600; i++)
		if (i % 3 == 0 && (i % 10 == 5 || i / 100 == 5 || (i - (i / 100) * 100) / 10 == 5))		//如果除以10余数为5,那么说明最后一位是5.如果除以100为5,那么说明第一位为5,如果减去百位,再除以10的余数为5,那么说明十位为5。
			cout << i << endl;																	//atFuRYh
	return 0;
}

我的作息比较奇葩,那天晚上大概十二点多开始肝到三点多。。现在是2021年第一天的早上6:30,跨年夜早早的睡了结果醒的格外的早就起床敲代码了。。这么神奇的作息我也要记录下来在这里插入图片描述


3.编写程序,求100~200内所有的素数。


想到的是双重循环,判断素数。如果i/j的余数为0,则说明除的尽,所以不是素数。反之则是。第一次敲出来代码如下。

#include<iostream>
using namespace std;
int main()
{
	for (int i = 100; i <= 200; i++)
	{
		for (int j = 2; j < i; j++)
		{
			if (i% j != 0)
				cout << i << endl;
			else
				break;
		}
	}
	
	return 0;
}

结果不对。。。发现给我输出了一大堆,然后检查了一会儿发现问题所在:在每次除不尽的时候都会输出一下,而应该改成全部除不尽再输出。
改为如下,结果发现啥都不输出了。。。

for (int i = 100; i <= 200; i++)
	{
		for (int j = 2; j < i; j++)
		{
			if (i% j == 0)
				break;
			else
				continue;
			cout << i << endl;
		}
	}

参考大佬的文章,发现自己问题所在。然后修改…
https://blog.csdn.net/qq_39778967/article/details/79998529
(大佬的代码如下)

#include <stdio.h> //引用文件
main()
{
int i,j; //定义循环变量
for(i=100;i<=200;i++) //定义从100-200之间的循环数字
{
for(j=2;j<i;j++) //判定条件从(2)—(i-1)之间能否被i整除
{
if(i%j==0) break; //如果可以则跳出循环,不是素数
}
if(j>=i) //如果j>=i则为素数,并输出
printf("%d\t",i); //用表格的形式输出结果
}
}

没认真看改了还错,再回去看才发现是自己又少了判断j>=i这步的判断,所以导致输出了老多东西。。想了想仿佛明白了…如果自己没有这一步的话那每次跳出来都会输出一下,所以几多了。。但没懂他为什么是大于等于,光等于不就行了么?
思考完了之后动手,发现这步判断时候还必须把for循环里面的j拿出去int一下。。自己还是太菜了啊。。。

最终代码如下

#include<iostream>
using namespace std;
int main()
{
	int j;					//定义j,在此处定义,否则最后一个if判断时候用不了
	for (int i = 100; i <= 200; i++)	//第一重循环,备选数i。
	{
		for ( j = 2; j < i; j++)		//用j来一个一个的除
			if (i% j == 0)				//除尽了则说明不是素数,跳出。如果一直除不尽则说明是素数,输出
				break;
		if(j==i)						//当j=i时,说明i已经除完了,确实是素数
			cout << i << endl;			                              //atFuRYh
	}
	
	return 0;
}

4.编写程序,用迭代公式求在这里插入图片描述

。迭代公式为在这里插入图片描述
要求初始值y=x,精度为在这里插入图片描述
求出当x=0.75时,对应的y值(答案:0.92856)。***

首先吐槽一句…那个字念die,不念zhu。然后word里面图片的公式添加过来有点别扭将就看(其实可能也就只有我日后回忆时候看看了哈哈)

然后开始做题,想法是用循环,当精度达到要求时候停止循环。然后还得用函数写出来那个公式,然后迭代。去编一下试试。

参考了百度上的这个案例

https://zhidao.baidu.com/question/1639198818115717660.html

#include<iostream>
#include<cmath>
using namespace std;
double GongShi(double y,double x)
{
	y = (2 / 3)*y + x / (3*y * y);
	return y;
}
int main()
{
	double y1, y0;
	do
	{
		y1 = y0;
		GongShi(y1, y0);

	} while (abs(y1 - y0) > 1e-5);

	cout << y1 << endl;

	return 0;
}

提示我y0没有初始化,但我不知道该初始化成几…然后随便初始化成1,2发现输出还是1,2。。。所以开始改。
断点调试,首先发现一个问题就是形参变了实参没变…所以加了个&符号。改成了这样

double GongShi(double &y,double &x)

继续调试发现y1的值每次更改之后都会被y0重新赋成初始值。自己调试了半天发现还是不会…然后放弃了函数,直接搞。

重新做了一下,做出来如图

#include<iostream>
using namespace std;
int main()
{
	double a,x1, x2, y;
	cin >> a;
	x1 = a;
	x2 = 0;
	while (abs(x2-x1)>1e-5)
	{
		
		x2 = x1;
		x1= (2 / 3) * x1 + a / (3 * x1 * x1);
	}
	cout << x2 << endl;
}

输出结果:
在这里插入图片描述
哦豁…bug了?百度这个inf,告我说是超出数据范围,浮点数溢出。一脸懵逼的去调试,发现好像没有能正确的终止循环…然后我盯着循环搞了半天,未果。
百度,参考此文,找到结果。因为我(2/3)=0.6666,编译器默认int型,所以被除数成了0 。所以就不对了。

https://zhidao.baidu.com/question/523420544.html

修改方案1:百度的方法,2改成2.0
修改方案2:与舍友讨论后,参考他的。将(2/3)*x改成了2y13,因为之前y1定义过是double型,所以这里也就成了double型,就不会认为是0。

修改后成品如下:
(x1,x2,a的看的麻烦…搞错了给,所以变量名字也改了一下)

#include<iostream>
#include<math.h>
using namespace std;
int main()
{
	double x,y1, y2;		//y1,y2为题目中yn,yn+1,x就是x。
	cin >> x;
	y1 = x;					//初始化y为x
	y2 = 0;
	while (fabs(y2-y1)>1e-5)		//没有用到do while,因为第一次的时候也满足条件进入循环
	{
		y2 = y1;
		y1= 2*y1/ 3 + x / (3 * y1 * y1);					      //atFuRYh
	}
	cout << y2 << endl;
}

这个题大概就这样结束了,不过上面那个想尝试利用函数的方法失败了…日后有空再回头研究一下。


实验三 函数的定义和调用



1. 利用弦截法求f(x)=0的一个实根。


在这里插入图片描述
按着去做,做出来如下。

#include<iostream>

using namespace std;
double Fx(double x)
{
	double y;
	y = x * x + 3*x - 4;
	return y;
}

int main()
{
	double x1, x2, x0;
	cin >> x1;
	cin >> x2;

	do
	{
		x0 = (x1 * Fx(x2) - x2 * Fx(x1)) / (Fx(x2) - Fx(x1));

	} while (fabs(Fx(x0)) > 1e-5);
	
	return 0;
}

运行后输入之后没反应…与舍友交流,发现问题所在,一来是我执行完循环之后没有输出(这个问题卡了他一天结果我俩交流了几分钟就发现了。。)二来是我完全没读懂题,题目中要求用弦截法。
数学知识不过关,所以开始自学弦截法是啥。。(其实书上有提示…)
按着书上的提示写出来代码如下:

#include<iostream>

using namespace std;
double Fx(double x)
{
	double y;
	y = x * x + 3*x - 4;
	return y;
}

int main()
{
	double x1, x2, x0;
	cin >> x1;
	cin >> x2;

	do
	{
		x0 = (x1 * Fx(x2) - x2 * Fx(x1)) / (Fx(x2) - Fx(x1));
		if (Fx(x0) * Fx(x1) < 0)
			x2 = x0;
		else
			x1 = x0;
	} while (fabs(Fx(x0)) > 1e-5);
	cout << x0 << endl;

	return 0;
}

运行,发现无论如何输出的都是1…调试,发现仿佛函数那里该加上&。加上之后还不对。。然后继续试,与舍友交流之后发现自己又少了一步,判断这个输入的值是否正确,加了一些。
再百度参考了另一篇文章,将程序写的更加模块化了一些。但还是不对…调试了半天也没用找到问题所在,遂放弃。。等改日再研究研究知道了再改。

#include<iostream>
#include<cmath>
using namespace std;
double x1, x2, x0,x;
double Fx(double x)	
{
	double m;
	m = x * x + 3*x - 4;
	return m;
}
double Root(double x1, double x2)
{
	do {
		x0 = (x1 * Fx(x2) - x2 * Fx(x1)) / (Fx(x2) - Fx(x1));
		if (Fx(x0) * Fx(x1) < 0)
			x2 = x0;
		else
			x1 = x0;
	} while (fabs(Fx(x0)) > 1e-5);
	return Fx(x0);
}
int main()
{

	do{
		cin >> x1;
		cin >> x2;
		if (Fx(x1) * Fx(x2) >= 0)
			cout << "输错了,请重输" << endl;
	} while (Fx(x1) * Fx(x2) >= 0);
	Root(x1, x2);
	cout << x0 << endl;
	return 0;
}

2. 用递归调用的方法编写本题,用牛顿迭代法求f(x)=0的一个实根。


在这里插入图片描述
…???牛顿迭代什么玩意,,感谢C++让我意识到了学好高数的重要性。下学期高数一定认真听讲…!

先跳过了等等再写这题

1.4回头搞这道题,其实书上就有提示那天知识太晚懒得鼓捣…按书上提示,需要用到导数,所以我定义了Fx之后又定义了一个Dx(Fx的导数)

代码如下:

#include<iostream>
using namespace std;
double Fx(double x)					//Fx
{
	double a;
	a = x * x + 3 * x - 4;
	return a;
}
double Df(double x)					//Dx
{
	return (2 * x + 3);
}
double DiGui(double x)
{
	x = x - Fx(x) / Df(x);
	if (fabs(Fx(x)) < 1e-5)				//此句用来确认精度
		return x;

	else
		return DiGui(x);
}
int main()
{
	double x = 0;							//atFuRYh
	cout << DiGui(x)<<endl;
}

输出答案是对的。结束!


实验四 函数参数传递机制


编写程序验证哥德巴赫猜想

一个不小于6的偶数可以表示两个素数之和,如6=3+3,8=3+5,10=3+7,…。在主函数中输入一个不小于6的偶数n,程序运行后输出一下形式的结果:
若输入34,则程序输出为:
34=3+31
34=5+29
34=11+23
34+17+17
编写程序,编译、运行,当输入为56↙时,输出为;
当输入122↙时,输出为:

验证哥德巴赫猜想,那么…应该先是写一个函数,判断数是否为素数。然后再用把输入的数成两半,分开判断是不是素数。如果是就输出,不是就重新分。
按此思路写出来结果如下:

#include<iostream>
using namespace std;

bool Su(int x)
{
	bool m = true;
	if (x <= 2)
		m=false;
	else
	{
		for (int i = 2; i < x; i++)
		{
			if (x % i == 0)
				m=false;
			else
				continue;
		}
	}
	return m;
}
int main()
{
	int Num;
	while (1)
	{
		cin >> Num;
		if (Num < 6 || Num % 2 != 0)
			cout << "请重新输入" << endl;
		else
		{
			break;
		}
	}
	
	for (int i = 1; i < Num; i++)
	{
		int a = i;
		int b = Num - i;
		if (Su(a) == 1 || Su(b) == 1)
			cout <<Num<< "=" << a <<"+"<<b<< endl;
		else
			continue;

	}
}

输出结果如下:
在这里插入图片描述
可以看到仿佛问题挺大…
首先1不是素数,其次9也不是素数,最后应该5+7和7+5只输出一次。
所以返回去检查程序。
发现第一个问题。。。||是或,&&才是且。。看来还是基础不扎实,默默担心五天后的C++期末…
改掉第一个问题后,这样的话剩下的问题只有5+7和7+5输出了两次这里。于是想,输出一次之后,直接结束程序是不是就可以了呢?
在这里插入图片描述搞定,完事!
最终代码如下

#include<iostream>
using namespace std;

bool Su(int x)				//判断一个数是否为素数,如果是则返回true,反之返回false。
{
	bool m = true;
	if (x <= 2)				
		m=false;
	else
	{
		for (int i = 2; i < x; i++)
		{
			if (x % i == 0)
				m=false;
			else
				continue;
		}
	}
	return m;
}
int main()
{
	int Num;	
	cout << "请输入一个不小于6的偶数" << endl;
	while (1)							//判断输入的数是否符合题意,为大于6的偶数
	{									//循环条件设置为1,即一直进行,直到跳出
		cin >> Num;
		if (Num < 6 || Num % 2 != 0)
			cout << "请重新输入" << endl;			
		else
			break;
	}
	
	for (int i = 1; i < Num; i++)			//验证部分	
	{	
		int a = i;							//将Num分成ab两个整数。
		int b = Num - i;
		if (Su(a) == 1 && Su(b) == 1)		//判断ab是否均为素数
		{										//atFuRYh
			cout << Num << "=" << a << "+" << b << endl;
			break;							//如果不跳出,则会输出两次。例如5+7,7+5两次
		}
		else
			continue;					
	}
	return 0;
}

实验五 一维数组的定义和使用



用选择法对数组元素进行从小到大的排序。请完善程序,编译、连接,并写出运行结果。


先是去百度了一下什么叫个选择法…(其实书上讲的很详细,哈哈)

第一次敲出来的如下:(请忽略这个输出数组的方式,测试一下就没敲循环)

#include<iostream>
using namespace std;

int main()
{
	int a[6] = { 5,9,8,3,7,2 };		//定义一个6长度的数组,随机放几个数。没按书上的数字来
	int min=0;						//min,用于存放最小数的下标,初始化为0
	int t;							//t,交换时候中间变量
	for (int i = 1; i < 6; i++)
	{
		if (a[min] < a[i])
			continue;
		else
		{
			t = a[min];
			a[min] = a[i];
			a[i] = t;
		}		
	}
	cout << a[0] << endl;
	cout << a[1] << endl;
	cout << a[2] << endl;
	cout << a[3] << endl;
	cout << a[4] << endl;
	cout << a[5] << endl;

	return 0;
}

输出结果为
2,9,8,5,7,3。百思不得其解…咋排的???遂去调试,发现问题所在,min本应是存储一组中最小的一个,而我却错误的将它存储上了第一个比他小的。所以运行下来5与3交换,3再与2交换,就得到了这个错误的结果…
开始改代码,再读一次课本的提示发现自己错误挺大,还是没有吃透这个方法。。于是 重新去看,发现他应该用两个循环,分开处理下标和数组元素。修改后结果如下:

在这里插入代码片#include<iostream>
using namespace std;

int main()
{
	int a[6] = { 5,9,8,3,7,2 };		//定义一个6长度的数组,随机放几个数。没按书上的数字来
	int min;						//min,用于存放最小数的下标,初始化为0  atFuRYh
	int t;							//t,交换时候中间变量
	for (int i = 0; i < 5; i++)				//处理元素的循环
	{
		min = i;
		for (int j =i+1; j < 6; j++)		//用于处理下标的循环
			if (a[min] > a[j])
				min = j;					//交换下标
		
			t = a[min];						//交换元素
			a[min] = a[i];
			a[i] = t;	
	}
	for (int x = 0; x < 6; x++)				//输出
		cout << a[x] << endl;
	return 0;
}

最终成功输出。


实验六 二维数组的定义和使用



将二维数组的各列按其所有元素的和从小到大进行排列,每一列元素的相对位置保持不变。

在这里插入图片描述


好家伙…看到这个题的时候是一脸迷茫的,多读了几次题感觉理解了点他的意思然后开始敲。自己编了三个函数,分别是求和、排序、交换xy列。排序的代码来自上一个实验中一位数组的选择法排序。大致思路是这样的,先每一列去求和,求出来之后按要求将和从小到大排序,然后拍完得到一个新的数组k。再用二维数组每一列的和与k数组比较,如果不一样就交换,交换到一样位置。那么这时候得到的新数组即为所求。

卡了我好久的一个地方是…忘了把排序注释掉了,所以拿着没排序的k研究了半天为何if不对。。。

#include<iostream>
using namespace std;
int k[4];
int sum(int b[3][4], int k)			//计算3行4列的二维数组中第k列的和
{
	int sum=0;
	for (int i = 0; i < 3; i++)
		sum += b[i][k];
		return sum;
}

void PaiXu(int k[4])			//此段代码复制自上一个实验,并略加修改
{
	int min;						//min,用于存放最小数的下标,初始化为0  atFuRYh
	int t;							//t,交换时候中间变量
	for (int m = 0; m < 3; m++)				//处理元素的循环
	{
		min = m;
		for (int n = m + 1; n < 4; n++)		//用于处理下标的循环
			if (k[min] > k[n])
				min = n;					//交换下标

		t = k[min];						//交换元素
		k[min] = k[m];
		k[m] = t;
	}
}

void Swapxy(int b[3][4], int x, int  y)		//交换数组的X、Y列
{
	int a[3];
	for (int i = 0;i < 3;i++)
	{
		a[i] = b[i][x];
		b[i][x] = b[i][y];
		b[i][y] = a[i];
	}
}

int main()
{
	int arr[3][4] = { 5,8,10,15,17,6,4,8,6,15,9,12 };

	for (int j = 0; j < 4; j++)		//将每列的和赋给数组k[]
		k[j] = sum(arr, j);
	PaiXu(k);						//把求和出来的值进行排序
	//交换xy列,直到交换出来的四列各列之和与k【】相等				atFuRYh
	for (int i = 0; i < 4; i++)
		for (int j = 0;j<4 ; j++)
			if(sum(arr, i) != k[i])
				Swapxy(arr, i, j);

	for (int i = 0; i < 3; i++)					//输出部分
		for (int j = 0; j <4; j++)
			cout << arr[i][j] << endl;

	return 0;
}

本实验感悟:传参时候数组名后面不用加【】【】直接传数组名就好

好家伙好家伙,现在是2021年1月2日凌晨4:54分,我感觉自己作息好奇怪…1.1早上6:30起床敲,然后到中午吃个饭,回来玩了一会儿一觉睡到晚上七点半。。。起床吃个饭玩一下十一点开始肝到现在…然后准备睡觉去了,再一次打破我上大学以来最晚睡觉的记录。。上一次是CTF新生校赛时候肝到四点半,现在是敲代码到五点。。。目测一觉睡到十二点吧,然后吃饭下午有事出去晚上继续!
在这里插入图片描述

果不其然一觉十二点。。起床吃饭下午有事然后晚上回来休息一下。现在九点半接着搞,吐槽一下江苏这鬼天气,空调坏了冻死人。。手脚冰凉,穿的俩毛衣+羽绒服敲代码。。。。


实验七 类和对象的定义与访问



编写Money类,数据成员为Yuan、Jiao、Fen,函数成员包括两笔Money的加和减。


#include<iostream>
using namespace std;
class money
{
public:
	int Yuan;
	int Jiao;
	int Fen;
	money operator+(money a)
	{
		money g;
		g.Yuan = a.Yuan + Yuan;
		g.Jiao = a.Jiao + Jiao;
		g.Fen = a.Fen + Fen;
		return g;
	}
	money operator-(money a)
	{
		money g;
		g.Yuan = Yuan - a.Yuan;
		g.Jiao = Jiao - a.Jiao;
		g.Fen = Fen - a.Fen;
		return g;
	}
};

其实说实话没看懂这个题是要干嘛。。。去百度看了看类似的案例,发现应该还有一个功能,就是实现进位,即 十角表示成一元 这样。。所以返回进行修改。加了检查是否大于9,和输出两个函数。代码如下

#include<iostream>
using namespace std;
class money
{
public:
	int Yuan;
	int Jiao;
	int Fen;

	money operator+(money a)
	{
		void CheckDate(money m);

	
		money g;
		g.Yuan = a.Yuan + Yuan;
		g.Jiao = a.Jiao + Jiao;
		g.Fen = a.Fen + Fen;
		CheckDate(g);
		return g;
	}
	money operator-(money a)
	{
		void CheckDate(money m);
		money g;
		g.Yuan = Yuan - a.Yuan;
		g.Jiao = Jiao - a.Jiao;
		g.Fen = Fen - a.Fen;
		return g;
		CheckDate(g);
	}
};
void CheckDate(money m)
{
	if (m.Fen >= 10)
	{
		m.Jiao += m.Fen / 10;
		m.Fen = m.Fen % 10;
	}
	if (m.Jiao >= 10)
	{
		m.Yuan += m.Jiao / 10;
		m.Jiao = m.Jiao % 10;
	}
}
void print(money m)
{
	cout << m.Yuan << "元" << m.Fen << "角" << m.Fen << "分" << endl;
}
int main()
{
	money m1{ 1, 2, 3 };
	money m2{ 2,9,8 };
	money m3{};
	m3 = m1 + m2;
	print(m3);
}

但随便输了一个数字测试一下…发现CheckDate函数还是出了,遂 返回检查修改。在这里插入图片描述

哦豁…回去修改了半天,无果。。。调试时候发现问题,感觉还是函数传值的时候没有加&,导致没成功修改。但加了之后发现报错,如图。然后修改了半天不知道咋办。。。。百度也没有解决,遂放着日后再看吧。。。在这里插入图片描述
1.3中午,开工开工!
与舍友交流后作出了修改,将函数改到了类内,然后就解决了上述问题。
但是遇到的新问题是…print出来的不对,然后设断点调试了半天,发现数据没错,CheckDate函数也正常运行,但是打印的不对。。去问老师,然后老师提醒我去print函数里面看,我进去一看发现…自己打印的东西错了。。。丢脸丢大发的一个错误。
贴上最终成功运行的代码。

#include<iostream>
using namespace std;
class money
{
public:
	int Yuan;
	int Jiao;
	int Fen;

	money operator+(money a)				//重载,加
	{
		money g;
		g.Yuan = a.Yuan + Yuan;
		g.Jiao = a.Jiao + Jiao;
		g.Fen = a.Fen + Fen;
		g.CheckDate();
		return g;
	}
	money operator-(money a)					//重载,减
	{
		void CheckDate(money m);
		money g;
		g.Yuan = Yuan - a.Yuan;
		g.Jiao = Jiao - a.Jiao;
		g.Fen = Fen - a.Fen;
		g.CheckDate();
		return g;
	}
	void CheckDate()						//检查数字是否正确,11分则表示成1角1分
	{
		if (Fen >= 10)
		{
			Jiao += Fen / 10;
			Fen = Fen % 10;
		}
		if (Jiao >= 10)
		{
			Yuan += Jiao / 10;
			Jiao = Jiao % 10;
		}
	}
};

void print(money m)								//输出
{
	cout << m.Yuan << "元" << m.Jiao << "角" << m.Fen << "分" << endl;			//atFuRYh
}
int main()
{
	money m1{ 1, 2, 3 };
	money m2{ 2,9,8 };
	money m3{};									//测试,用m3存放m1,m2相加后结果
	m3 = m1 + m2;
	print(m1);
	cout << "加上" << endl;
	print(m2);
	cout << "等于" <<endl ;
	print(m3);
}

实验八 构造函数与析构函数



定义一个类STR,将一个字符串中指定位置的连续字符拼接到另一个字符串的尾部

具体要求如下:
(1)私有数据成员。
char *p;存放一个字符串。
(2)公有成员函数。
STR(char *s):构造函数。为数据成员p动态内存分配空间,并利用参数s初始化数据成员p。
void fun(char *s,int nl, int n2):将字符串s从第n1(从0开始计数)个字符开始的连续n2个字符拼接到数据成员p所指向的字符串之后,形成第一个新的字符串。注意,必须为p重新分配内存空间。
Void print():按输出指示例格式输出数据成员p。
~STR():析构函数,释放动态内存。
(3)在主函数中完成对该类的测试。
输入输出示例(下画线部分为键盘输入):
字符串1:abcdefg
字符串2:12345678
输入起始位置和字符个数:2 5↙
处理后的字符串1为:abcdefg34567


哦豁…好长的任务要求,不过按部就班的一步一步来吧。先敲一下试试。

第一版如下:

#include<iostream>
#include<string>
using namespace std;

class STR
{
private:
	char *p=0;


public:
	STR(char* s)
	{
		char *p = new char[10];
		p = s;
	}
	void fun(char* s, int n1, int n2)
	{
		char m[20] = {};
		char* p = new char[20];
			for (int i = 0; i < n2-n1; i++)
			{
				m[i] = s[n1 + i];
			}
			
			//定义一个数组m,用于存放s中n1---n2段的字符串。然后用strcpy函数链接p和m

		   p = strcat(p, m);

	}
	void print(char* p)
	{
		cout<<"拼接后的字符串为:"<<p << endl;
	}

	~STR()
	{
		delete p;
	}
};

int main()
{
	char* a = "abcdefg";
	char* b = "12345678";

	STR s1(a);
	/*STR s2(char *b);*/
	s1.fun(b, 2, 5);
	s1.print(a);
	return 0;
}

运行报错,C4996。。按照此文所说,关闭之后出现了其他问题。。。

https://blog.csdn.net/weixin_44171004/article/details/86675605

所以猜测是自己strcat函数用错了。。就去百度这个函数教程。百度的一半恍然大悟,,仿佛我这道题本来就不是字符串啊。。。应该是个数组?所以应该用数组赋值的方法来做。遂返回重新修改。

改完之后如下:

#include<iostream>
#include<string>
using namespace std;

class STR
{
private:
	char *p=0;

public:
	STR(char* s)
	{
		char *p = new char[10];
		p = s;
	}
	void PinJie(char *a,char *b)
	{
		int Len_a=sizeof(a);
		int Len_b = sizeof(b);

		a = (char*)malloc(sizeof(a) + sizeof(b));
		for (int i = 0; i < Len_b; i++)
		{
			a[Len_a + i] = b[i];
		}
		/*return a;*/
	}
	void fun(char* s, int n1, int n2)
	{
		char m[10] = {};
		char* p = new char[20];
			for (int i = 0; i < n2-n1; i++)
			{
				m[i] = s[n1 + i];
			}
			
			//定义一个数组m,用于存放s中n1---n2段的字符串。然后用strcpy函数链接p和m
			//修改:恍然大悟我用的不是字符串。。所以不能用strcut,该按照数组来处理。
			PinJie(s, m);
	}
	void print(char* p)
	{
		cout<<"拼接后的字符串为:"<<p << endl;
	}

	~STR()
	{
		delete p;
	}
};

int main()
{
	char* a = "abcdefg";
	char* b = "12345678";

	STR s1(a);
	/*STR s2(char *b);*/
	s1.fun(b, 2, 5);
	s1.print(a);
	return 0;
}

成功运行但是输出的字符串就是a。。。没有进行拼接,所以设断点返回调试。发现问题出在了初始化那里。。。p没有被成功的赋值为s,所以后续拼接也不对,。不会解决,等明天舍友醒了商讨一下再解决这个。(我又是阴间作息- -现在凌晨2点)

第二天醒后的修改:malloc那里sizeof改成了strlen,析构里面改成了delete[]p; 然后pinjie函数改成了char型,返回a。。。但还是不行,现在运行不了了。提示触发一个断点,百度发现研究这个问题所需知识过多。。放弃,等再与其他人交流。


实验九 继承和派生的应用



编写顺序表类,由顺序表类派生出栈类。


看到这个题目一脸懵逼。。。线性表上课提过,是存储数据的一片连续的空间。但栈表…??百度了半天依旧懵逼,然后懵逼的我看着懵逼的题敲出了懵逼的代码,没报错就撤了 。。。有大神的话还请指导一下,万分感谢。

#include<iostream>
using namespace std;
class SqList
{
public:
	int* pdate;
	int top;
	int size;
	SqList()
	{
		top = -1;
		size = 100;
		pdate = new int[size];
	}
	~SqList()
	{
		top = -1;
		for (int i = 0; i < size; i++)
			pdate[i] = 0;
		delete[]pdate;
	}
};
class StackList :private  SqList
{
public:
	StackList()
	{
		top = -1;
	}
	StackList(int m)
	{
		pdate = new int[100];
		top = m;
		size = 100;
	}
	~StackList()
	{
		top = -1;
		for (int i = 0; i < size; i++)
			pdate[i] = 0;
		delete[]pdate;
	}
	int gettop()
	{
		if (top == -1)
			cout << "top==-1" << endl;
		return top;
	}
	bool empty()
	{
		if (top == -1)
			return true;
		else
			return false;
	}
	void tianjia(int x)
	{

		if (top == size - 1)
			cout << "top==size-1";
		else
			pdate[top++] = x;
	}
	void daying()
	{
		if (top == -1)
		{
			cout << "top==-1";
			return;
		}
		for (int i = 0; i < top; i++)
		{
			cout << pdate[i] << endl;
		}
		return;
	}
};

实验十 虚函数与多态性

编写多边形类,具备每边长度的数据成员和计算周长的函数成员、计算面积的纯虚函数成员。由多边形类派生出正多边形类(非抽象类)。

#include<iostream>
using namespace std;
class dbx					//定义多边形类
{
public:
	int num;				//边数
	int size_long;			//边长
	virtual int zhouchang() = 0;		//求周长的函数
	dbx()
	{
		num = 100;
		size_long = 100;
	}
};
class zdbx :public dbx				//派生,正多边形
{
public:
	zdbx(int x, int y)
	{
		dbx::num = x;
		dbx::size_long = y;
		
	}
	int zhouchang()					//正多边形边长,顺便输出了
	{
		cout << "该正多边形的长度是:" << zdbx::num * zdbx::size_long << endl;
		return 0;			//随便返回一下。。void的话会报错 					//atFuRYh
	}
};
int main()
{
	zdbx a(3, 4);
	a.zhouchang();
}

实验十一 文件操作


建立一个有若干个字符串的文本文件str.txt,形式如图1.42所示,文件用“End of String”字符串结尾,计算出字符串的个数,同时对这些字符串进行排序,将排序的结果输出至文本文件strout.txt中,如图1.43所示。

在这里插入图片描述
文件读取,基本没讲过的内容。。。百度自学外加借鉴同学。。参考此文:

https://blog.csdn.net/qq_34097715/article/details/79970860
代码如下:

#include<iostream>
#include<fstream>
using namespace std;
int main()
{
	ifstream infile("C:\\Users\\76138\\Desktop\\str.txt");	//打开文件
	ofstream outfile("C:\\Users\\76138\\Desktop\\str_out.txt", ios::app);		//输出文件			
	char string[100][30], temp[30];
	if (!infile.is_open())
	{		//此行代码参考自百度
		cout << "未成功打开文件" << endl;
	}
	int i = 0;
	infile.getline(string[i], 30);
	while (strcmp(string[i], "end of string"))
	{
		i++;
		infile.getline(string[i], 30);
	}
	int n = 0;
	for (i; i < n - 1; i++)
		for (int j = 0; j < n - i - 1; j++)
			if (strcmp(string[j], string[j + 1]) > 0)
			{
				strcpy(temp, string[j]);
				strcpy(string[j], string[j + 1]);
				strcpy(string[j + 1], temp);
			}
	outfile << "字符串个数:" << n << endl;
	outfile << "排序后字符串:" << endl;
	for (int i = 0; i < n; i++)
		outfile << string[i] << endl;

	infile.close();
	outfile.close();
	return 0;

}

不过感觉这块还是懵逼的。。。准备寒假再看看C+。

历时半个多星期十几个小时肝完了这个作业,最大感悟是学会了调试…原来在学RE在IDA中用过几次调试,然后现在在VS继续用了用感觉更顺了哈哈。其次就是继续认识到了“百度”的重要性…当然最重要的还是感慨要上课好好听讲啦…秦爷yyds,可惜我这学期的课走神无数错过了很多精彩。。最后导致做起来的时候好多东西都似曾相识结果还得百度的去学。
第一次尝试认真的写一个博客,没指望有什么人来看只是当做一个学习的记录。大神莫嘲笑哈。

2020.1.4.16:22,距离1.7考试还有…两三天,保佑自己不要挂科吧,哈哈!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值