【C++期末编程题题库】代码+详解18道

news2024/11/19 3:50:00

适合期末复习c++看,或者刚入门c++的小白看,有的题会补充知识点,期末复习题的代码一般比较简单,所以语法上没那么严谨。本文所有题目要求全在代码块的最上面。

目录

1、设计复数类

 2、设计Computer类

3、实现相加的函数模板

4、圆类的设计

5、学生类设计

6、求圆与直线位置关系

7、家庭账户共享

8、栈类的设计

9、主人召唤宠物

10、点圆圆柱单继承

11、点长方形长方体单继承

12、点圆球体运行时多态

13、学生数据写入文件和读取

14、图形抽象类派生具体类求多个图形面积

15、 除数为0的异常处理

 16、学生数据修改【文件操作】

17、分数的加减

 18、统计字符数组中某个字符出现次数


1、设计复数类

//设计复数类Complex和友元运算符重载>>及<<实现复数类对象的标准输入和输出
#include<iostream>
using namespace std;

class Complex
{
private:
	double real, imag;
public:
	Complex(double r = 0, double i = 0)
	{
		real = r;
		imag = i;
	}
	//下面是友元的声明,所以函数参数只写类型是可以的
	friend istream& operator>>(istream&, Complex&);
	friend ostream& operator<<(ostream&, Complex&);
};
istream& operator>>(istream& input, Complex& c)
{
	//输入实部和虚部
	input >> c.real >> c.imag;
	return input;//返回istream,符合operator>>的实现
}

ostream& operator<<(ostream& output, Complex& c)
{
	if (c.imag > 0)
		output << c.real << "i+" << c.imag;
	else if (c.imag < 0)
		output << c.real << "i" << c.imag;
	else
		output << c.real << "i";

	return output;
}

int main()
{
	Complex c;
	cin >> c;
	cout << c;
	return 0;
}


 2、设计Computer类

//计算机Computer的属性包括型号、生产厂家和价格,用文件流中write()函数将若干
//计算机中的信息写入文件Computer.dat中,然后用read()函数将Computer.dat中所有数据读出。
#include<iostream>
#include<string>
#include<fstream>
using namespace std;

//涉及文件读写操作了,肯定要访问成员变量,用struct即可
struct Computer
{
	int id;
	string manufacter;
	double price;
};

int main()
{
	Computer c;
	cout << "Please input the id, manufacter and price of Computer:";
	cin >> c.id >> c.manufacter >> c.price;
	ofstream out("Computer.dat", ios::binary | ios::out);
	if (!out.is_open())//如果文件打开不成功//也可写为if(!out)
	{
		cout << "fail to open the file\n" << endl;
		exit(-1);
	}
	out.write((const char*)&c, sizeof(c));//写入是const char*
	out.close();

	ifstream in("Computer.dat", ios::binary | ios::in);
	if (!in)
	{
		cout << "fail to open the file\n" << endl;
		exit(-1);
	}
	in.read((char*)&c, sizeof(c));//读取是char*
	in.close();
	
	cout << "the data of Computer is:" << endl;
	cout << c.id << " " << c.manufacter << " " << c.price << endl;

	return 0;
}


3、实现相加的函数模板

//编写两个相长度数值型一维数组对应元素相加的函数模板
#include<iostream>
using namespace std;

template<class T>
void add(T a[], T b[], T c[], int n)
{
	for (int i = 0; i < n; i++)
		c[i] = a[i] + b[i];
}

int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int b[5] = { 1, 2, 3, 4, 5 };
	int c[5];
	add(a, b, c, 5);
	for (int i = 0; i < 5; i++) cout << c[i] << " ";
	cout << endl;

	return 0;
}


4、圆类的设计

//1、圆类的设计:设计一个圆类,计算出它的周长,面积,
//并有圆心移动和半径移动(就是变化的意思)的操作,并打印出数据
#include<iostream>
using namespace std;

//这里最好不要用float,除非你写为3.14f,因为你写一个小数3.14默认为double
//如果你用float,这里就会发生截断,因为是从double到float
const double pi = 3.14;

class Circle
{
public:
	//也可采用c++11的初始化列表方式
	/*Circle(int x = 0, int y = 0, int r = 0)
		:_x(x)
		,_y(y)
		,_r(r)
	{}*/

	Circle(double x = 0, double y = 0, double r = 0)
	{
		_x = x; _y = y; _r = r;
	}
	double circum()
	{
		return 2 * pi * _r;
	}
	double area()
	{
		return pi * _r * _r;
	}
	void movep(double x, double y)
	{
		_x += x; _y += y;
	}
	void mover(double r)
	{
		_r += r;
	}
	void show()
	{
		cout << "圆心:(" << _x << "," << _y << ") 半径:" << _r << endl;
	}

private:
	double _x, _y, _r;
};

int main()
{
	Circle c(1.2, 1.3, 2.1);
	c.show();
	cout << "circum:" << c.circum() << "   " << "area:" << c.area() << endl;
	c.movep(1.1, 2.2);
	c.show();
	c.mover(1.2);
	c.show();

	return 0;
}


5、学生类设计

//学生类设计求学生最高分最低分和平均分,并打印出学生信息
#include<iostream>
#include<string>
using namespace std;

class Student
{
private:
	int _id;
	string _name;
	double _score;

public:
	Student(int id = 0, string name = "", double score = 0.0)
	{
		_id = id;
		_name = name;
		_score = score;
	}

	void input(int id, string name, double score)
	{
		_id = id;
		_name = name;
		_score = score;
	}

	double Getscore()
	{
		return _score;
	}

	void show()
	{
		cout << "id:" << _id << " " << "name:" << _name << " " << "score:" << _score << endl;
	}
};

double maxscore(Student stu[], int n)
{
	double maximum = 0.0;
	for (int i = 0; i < n; i++)
		if (maximum < stu[i].Getscore()) maximum = stu[i].Getscore();
	return maximum;
}

double minscore(Student stu[], int n)
{
	double minimum = 100;
	for (int i = 0; i < n; i++)
		if (minimum > stu[i].Getscore()) minimum = stu[i].Getscore();
	return minimum;
}

double averscore(Student stu[], int n)
{
	double sum = 0.0;
	for (int i = 0; i < n; i++)
		sum += stu[i].Getscore();
	return sum / n;
}

int main()
{
	Student stu[3];
	int id; string name; double score;
	for (int i = 0; i < 3; i++)
	{
		cin >> id >> name >> score;
		stu[i].input(id, name, score);
	}

	for (int i = 0; i < 3; i++) stu[i].show();

	cout << "maxscore:" << maxscore(stu, 3) << endl;
	cout << "minscore:" << minscore(stu, 3) << endl;
	cout << "averscore:" << averscore(stu, 3) << endl;

	return 0;
}


6、求圆与直线位置关系

//定义直线类和圆类,求两者位置关系(相切、相交或相离)
#include<iostream>
#include<cmath>
using namespace std;

//直线:ax + by + c = 0
class Circle;//必须先声明Circle类,不然友元函数找不到Circle
class Line
{
private:
	double _a, _b, _c;
public:
	Line(double a = 0, double b = 0, double c = 0)
	{
		_a = a;
		_b = b;
		_c = c;
	}
	//这里不用友元也可以,你可以用一个geta等等来获取私有成员,对于圆类同理
	friend int position_relation(const Line&, const Circle&);
};

class Circle
{
private:
	double _x, _y, _r;//圆心和半径
public:
	Circle(double x = 0, double y = 0, double r = 0)
	{
		_x = x;
		_y = y;
		_r = r;
	}
	friend int position_relation(const Line&, const Circle&);
};

//圆与直线位置关系公式:d=ax+by+c/根号下a*a+b*b【其中abc均为直线的,x和y是圆的圆心】
//如果d>r:相离 d==r:相切 d<r:相交
int position_relation(const Line& l, const Circle& c)
{
	double d = l._a * c._x + l._b * c._y + l._c / sqrt(l._a * l._a + l._b * l._b);
	//因为d是算出来的,浮点数会有精度损失,所以比较的时候要靠精度来比
	if (fabs(d - c._r) > 0.000001) return -1;     //相离
	else if (fabs(d - c._r) < 0.000001) return 1; //相交
	else return 0;							//相切
}

int main()
{
	Line l(2.1, 2.2, 2.3);
	Circle c(1.1, 1.2, 1.3);
	int ret = position_relation(l, c);
	if (ret == -1) cout << "相离" << endl;
	else if (ret == 1) cout << "相交" << endl;
	else cout << "相切" << endl;

	return 0;
}

回顾友元:

在C++中,友元函数(Friend Function)是一种特殊的函数,它可以访问并操作类的私有成员,即使它不是类的成员函数。通过友元函数,我们可以实现对类的私有成员的非成员函数访问权限。友元提供了一种突破封装的方式。友元函数提供了一种在需要时访问类的私有成员的机制,但应该慎重使用,因为过多的友元函数可能破坏类的封装性。

友元函数特性:

  • (1) 友元函数可以访问类的私有和保护成员,但不是类的成员函数。
  • (2) 友元函数不能被const修饰。由于友元函数不属于任何类的成员函数,它们无法被 const 修饰。
  • (3) 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
  • (4) 一个函数可以是多个类的友元函数。
  • (5) 友元函数的调用与普通函数的调用和原理相同。
  • (6)友元函数/友元类是单向的,A在B类中被声明为友元函数/友元类,表示A是B的友元函数/友元类,但B不是A的友元类函数/友元类;
  • (7)友元函数在类中声明时用friend修饰,但是在定义时不需要用friend修饰;
  • (8)友元函数不能被继承:父类的友元函数,继承后并不会成为子类的友元函数;
  • (9)友元函数不具有传递性:A类和B类都是C类的友元类,但是A类和B类并不是友元类;

7、家庭账户共享

//家庭银行账户共享,即一个家庭几个成员共享财产,设计一个Familymember类
//实现钱财的支出和存钱,并显示剩余钱额【定义静态成员实现】
#include<iostream>
#include<string>
using namespace std;

class Familymember
{
private:
	string _name;
public:
	Familymember(string name = "");
	static double money;
	static void save(double m);
	static void expend(double m);
	static void show();
};
//类外初始化静态成员变量不要加static
double Familymember::money = 0;//类內声明,类外定义

Familymember::Familymember(string name)
{//类內声明已经有默认参数,类外就不能给了,否则就重定义默认参数了
	_name = name;
}
//类外定义静态成员函数不能加static
void Familymember:: save(double m)
{
	money += m;
}

void Familymember::expend(double m)
{
	money -= m;
}

void Familymember::show()
{
	cout << "remained money:" << money << endl;
}

int main()
{
	Familymember wife("zhu"), husband("jiang");
	wife.save(10000);
	husband.expend(5000);
	husband.save(20000);
	wife.show();//对象可以访问静态成员函数,但静态成员函数没有this指针
	husband.show();
	Familymember::show();

	return 0;
}


8、栈类的设计

//设计一个静态栈类,内有构造函数,且有压栈和入栈操作,并返回栈顶元素,输入数据
//以0表示结束
//学校期末要求不高,我以前的博客写过动态栈,想了解的可以看看
#include<iostream>
using namespace std;

//这里不要定义为size,因为size是一个关键字,用于定义类型大小,如果你这里
//常量名称定义为size就会冲突!但是在devc++就能跑过去,可能dev不严谨,vs下是过不去的
const int stackSize = 100;

class Stack
{
private:
	int sta[stackSize];
	int _top;//栈顶

public:
	Stack();
	int push(int x);//入栈
	int pop();//出栈
};

Stack::Stack()
{//直接置空即可
	_top = 0;
}

int Stack::push(int x)
{
	if (_top == stackSize)
		return 0;//栈满返回0

	sta[_top++] = x;
	return x;
}

int Stack::pop()
{
	if (_top == 0)
		return 0;//栈空返回0
	//返回删除之后的栈顶
	return sta[--_top];
}

int main()
{
	Stack s;
	int x;
	cout << "Please input pushed data:" << endl;
	cin >> x;
	while (x && s.push(x))
	{
		cout << "Please input pushed data:" << endl;
		cin >> x;
	}
	
	while (x = s.pop())
		cout << "the poped data is :" << x << endl;

	return 0;
}

​​​​​​​


9、主人召唤宠物

//主人召唤宠物,宠物有名字和应答语,主人也有名字,他可以召唤宠物,看召唤名字与宠物
//的名字是否一致,若一致,宠物就会回应应答语
#include<iostream>
#include<string>
using namespace std;
class Pet
{
private:
	string _name;
	string _ans;

public:
	Pet(string name = "", string ans = "")
	{
		_name = name;
		_ans = ans;
	}

	void answer(string name) const
	{
		if (name == _name)//调用string的operator==
			cout << _ans << endl;
		else
			cout << "dear host, you are not calling me!" << endl;
	}
};

class Host
{
private:
	string _name;

public:
	Host(string name = "")
	{
		_name = name;
	}
	
	void call(const Pet& p, string name)
	{
		p.answer(name);
	}
};

int main()
{
	Host h("MeiZhu");
	Pet dog("huihui", "wangwang");
	Pet cat("huahua", "miaomiao~");
	h.call(dog, "huihui");
	h.call(cat, "huahuaya");

	return 0;
}


10、点圆圆柱单继承

//点圆圆柱单继承,即圆类继承点【圆心】类,再由圆柱类继承圆类,求出面积和体积
#include<iostream>
using namespace std;

const double pi = 3.14;

class Point
{
private://private即可,圆类求面积和体积用不到圆心
	double _x, _y;
public:
	Point(double x = 0, double y = 0)
	{
		_x = x;
		_y = y;
	}
	double area()
	{
		return 0.0;
	}
	double volume()
	{
		return 0.0;
	}
};

class Circle : public Point
{
protected://这里若用private的话,Cylinder求面积和体积就无法使用了
	double _r;

public:
	Circle(double r = 0.0, double x = 0.0, double y = 0.0)
		:Point(x, y)
	{
		_r = r;
	}
	double area()
	{
		return pi * _r * _r;
	}
	double volume()
	{
		return 0.0;
	}
};

class Cylinder : public Circle
{
private:
	double _h;

public:
	Cylinder(double x = 0.0, double y = 0.0, double r = 0.0, double h = 0.0)
		:Circle(r, x, y)
	{
		_h = h;
	}
	double area()
	{	//上下底圆的面积+侧面积:长方形面积
		return 2 * pi * _r * _r + 2 * pi * _r * _h;
	}
	double volume()
	{	//圆柱体积为底面积*高
		return Circle::area() * _h;
	}
};

int main()
{
	Circle cir(2.1, 1.1, 2.2);
	Cylinder cy(2.2, 2.3, 2.4, 1.2);
	cout << cir.area() << "    " << cir.volume() << endl;
	cout << cy.area() << "    " << cy.volume() << endl;

	return 0;
}


11、点长方形长方体单继承

//点长方形长方体单继承,长方形继承点类,长方体继承长方形类,求面积和体积
#include<iostream>
using namespace std;

class Point
{
private:
	double _x, _y;

public:
	Point(double x = 0.0, double y = 0.0)
	{
		_x = x;
		_y = y;
	}
	double area()
	{
		return 0.0;
	}
	double volume()
	{
		return 0.0;
	}
};
//长方形
class Rectangle : public Point
{
protected://不能设为private,不然长方体类中用不了了
	double _length, _width;

public:
	Rectangle(double x = 0.0, double y = 0.0, double l = 0.0, double w = 0.0)
		:Point(x, y)
	{
		_length = l;
		_width = w;
	}
	double area()
	{
		return _length * _width;
	}
	double volume()
	{
		return 0.0;
	}
};
//长方体
class Cuboid : public Rectangle
{
private:
	double _h;

public:
	Cuboid(double x, double y, double l, double w, double h)
		:Rectangle(x, y, l, w)
	{
		_h = h; 
	}
	double area()
	{//长方体表面积:2长*宽+2长*高+2宽*高
		return 2 * _length * _width + 2 * _length * _h + 2 * _width * _h;
	}
	double volume()
	{//长方体体积:底面积*高
		return _length * _width * _h;
	}
};

int main()
{
	Rectangle rec(1.1, 2.0, 2.3, 2.4);
	Cuboid cub(1.2, 2.2, 2.4, 4.5, 1.1);
	cout << "area of rectangle is :" << rec.area()  << "\t" << "volume of rectangle is:" << rec.volume() << endl;
	cout << "area of cuboid is :" << cub.area() << "\t" << "volume of cuboid is:" << cub.volume() << endl;

	return 0;
}


12、点圆球体运行时多态

//点圆球体运行时多态:由圆类继承点类,球类继承圆类,实现求面积和体积,要求多态实现
#include<iostream>
using namespace std;

const double pi = 3.14;

class Point
{
private:
	double _x, _y;
public:
	Point(const double& x, const double& y)
	{//这种加const写法的才是最标准的,因为应付期末,没有那么高的要求的
		_x = x;
		_y = y;
	}
	virtual double area() = 0;
	virtual double volume() = 0;
};

class Circle : public Point
{
protected:
	double _r;
public:
	Circle(double x, double y, double r)
		:Point(x, y)
	{
		_r = r; 
	}
	virtual double area()
	{	//圆的面积:π*r*r
		return pi * _r * _r;
	}
	virtual double volume()
	{
		return 0.0;
	}
};
//球体类
class Sphere : public Circle
{
private:
	double _z; //因为球体的是三维的,所以它的圆心应该再增加一个维度
public:
	Sphere(double x, double y, double r, double z)
		:Circle(x, y, r)
	{
		_z = z;
	}
	double area()
	{
		return 4 * pi * _r * _r;
	}
	double volume()
	{   //V=(4/3)πr^3
		return 4 * pi * _r * _r * _r / 3;
	}
};


int main()
{
	Point* p;
	Circle c(1.1, 1.2, 1.3);
	Sphere s(1.2, 1.3, 1.4, 1.5);
	p = &c;
	cout << " circle: " << p->area() << "\t\t" << p->volume() << endl;
	p = &s;
	cout << " sphere: " << p->area() << "\t" << p->volume() << endl;

	return 0;
}


13、学生数据写入文件和读取

//学生数据写入文件,并读取文件数据到程序中【使用read和write实现】
#include<iostream>
#include<fstream>
using namespace std;

struct Student
{
	char name[20];
	int id;
	int age;
	char gender[5];
};

int main()
{
	//创建一个输出流对象,并打开文件,以二进制的方式写
	//写法1:
	//ofstream outfile;
	//outfile.open("test.txt", ios::binary | ios::trunc);
	//trunc:如果文件存在先删除,再创建【一般是不用的】
	//写法2:更简洁!
	ofstream outfile("test.txt", ios::binary | ios::trunc);
	if (!outfile)//或写为if(!outfile.is_open())
	{//判断文件是否打开成功
		cout << "file open error!" << endl;
		exit(1);//exit(非0)都代表异常退出
	}

	Student stu[3];
	cout << "Please input the data of 3 students" << endl;
	for (int i = 0; i < 3; i++)
	{
		cin >> stu[i].name >> stu[i].id >> stu[i].age >> stu[i].gender;
		//写入文件,以二进制形式写入
		outfile.write((const char*)&stu[i], sizeof(stu[i]));
	}
	outfile.close();//关闭文件以便以下一次的读出数据

	//再把学生数据读出
	Student tmp[3];//保存从文件中读出的数据
	ifstream infile("test.txt", ios::binary);

	//读取方法一:直接读取整个数组的数据中
	//infile.read((char*)tmp, sizeof(tmp));
	//或写为infile.read((char*)&tmp[0], sizeof(tmp));//因为都是首元素的地址,读取的是一整个数组

	cout << "The Student data read from file is:" << endl;
	for (int i = 0; i < 3; i++)
	{//读取方法二:读取数据一个一个数组元素来读取
		infile.read((char*)&tmp[i], sizeof(tmp[i]));
		cout << tmp[i].name << " " << tmp[i].id << " " << tmp[i].age
			<< " " << tmp[i].gender << endl;
	}
	infile.close();

	return 0;
}

测试结果如下:

 此时打开test.txt文件可以看出是二进制的形式,我们看不懂,但是从文件中读入到程序当中就能看出来了,主要是因为这种二进制读写方式很方便


14、图形抽象类派生具体类求多个图形面积

//用图形类派生圆类和三角形类,分别求面积,并求出面积之和【多态实现】
#include<iostream>
using namespace std;

const double pi = 3.14;

class Graph
{
public:
	virtual double area() = 0;
};

class Circle : public Graph
{
private:
	double _x, _y, _r;
public:
	Circle(const double& x, const double& y, const double& r)
		:_x(x)
		,_y(y)
		,_r(r)
	{}
	double area()
	{
		return pi * _r * _r;
	}
};

class Triangle : public Graph
{
private:
	double _bottom, _h;
public:
	Triangle(const double& bottom, const double& h)
		:_bottom(bottom)
		,_h(h)
	{}
	double area()
	{
		return 0.5 * _bottom * _h;
	}
};

double sumarea(Graph* g[], int n)
{
	double sum = 0.0;
	for (int i = 0; i < n; i++)
		sum += g[i]->area();

	return sum;
}

int main()
{
	Circle c1(1.1, 1.2, 1.3), c2(1.2, 1.3, 1.4);
	Triangle t1(2.1, 3.1), t2(1.1, 3.4);
	Graph* g[4] = { &c1, &c2, &t1, &t2 };
	cout << sumarea(g, 4) << endl;

	return 0;
}


15、 除数为0的异常处理

建议先看我写过的异常文章:【C++】异常【完整版】-CSDN博客

//写一个实现除法的函数,主函数利用异常处理除数为0的情况
#include<iostream>
#include<string>
using namespace std;

//division:除法,dividend:被除数,divisor:除数
double division(double x, double y)
{
	if (y == 0)
	{
		//我们不建议写为throw 0.0, 因为这种处理方式和之前讲的错误码一样,没什么意义
		//不如直接用错误码了
		throw string("发生除0错误!");
	}
	return x / y;
}

int main()
{
	try
	{
		double x, y;
		cin >> x >> y;
		cout << "x / y = " << division(x, y) << endl;
		cin >> x >> y;
		cout << "x / y = " << division(x, y) << endl;
	}
	catch (const string& err)
	{
		cout << err << endl;
	}
	//下面用基类捕获的方式,若除数为0,会直接报错!
	//但有时如出现数组越界问题等,会直接打印出错误信息
	//catch (exception& e)
	//{
	//	cout << e.what() << endl;
	//}

	return 0;
}


 16、学生数据修改【文件操作

//建立学生类,将学生数据写入文件,然后读取回程序中,并修改第3个学生的信息,然后写入文件
//然后再读取到程序中并打印【要求:read和write实现,并使用文件指针定位的seekp和seekg】
#include<iostream>
#include<fstream>
#include<string>
using namespace std;

struct Stu
{
	int id;
	char name[20];//不能用string,不然会报错:读取访问权限冲突,除非用c_str,原因下面解释
	double score;
};

int main()
{
	Stu stu[20];
	//为什么要用fstream呢?因为下面有读指针和写指针操作同时进行的,这里定义fstream对象
	//既可以读又可以写,很方便,省得下面你又得关闭文件,然后又打开文件...
	fstream io("stu.txt", ios::binary | ios::out | ios::in);
	if (!io)
	{
		cout << "Fail to open the file!" << endl;
		exit(-1);
	}

	cout << "Please input the datas of students:" << endl;
	for (int i = 0; i < 3; i++)
		cin >> stu[i].id >> stu[i].name >> stu[i].score;
	io.write((const char*)stu, sizeof(stu));//一次性把整个数组全都写入文件中
	io.close();

	io.open("stu.txt", ios::binary | ios::in | ios::out);
	if (!io)
	{
		cout << "Fail to open the file!" << endl;
		exit(-1);
	}
	Stu tmp;
	cout << "Please input the updated datas of the third student:" << endl;
	cin >> tmp.id >> tmp.name >> tmp.score;
	io.seekp(2 * sizeof(tmp), ios::beg);//写文件指针定位,从原来第3个学生的位置开始
	io.write((const char*)&tmp, sizeof(tmp));//把修改后的数据放回文件中第3个学生的位置
	io.close();

	io.open("stu.txt", ios::binary | ios::out | ios::in);
	io.read((char*)stu, sizeof(stu));//修改完第3个学生数据后读回数组中
	io.close();//一定要关闭文件!

	cout << "The students' datas read from file are:" << endl;
	for (int i = 0; i < 3; i++)
		cout << stu[i].id << " " << stu[i].name << " " << stu[i].score << endl;

	return 0;
}

问题①、C++中文件读写类对象时,如果类对象中有string类型的成员变量,如何处理?

在C++中,对于类对象的二进制读写,涉及到对象的内存布局和成员变量的特性。而对于`string`这样的对象,它的内部实现复杂,包括指针指向堆上的动态内存,涉及到分配和释放内存等操作。因此,直接进行二进制读写可能会导致读取权限冲突。当你尝试将包含`string`成员变量的对象写入文件时,实际上只会将指针的值写入文件,而不是字符串的内容。而在读取文件时,再次加载这个对象,那个指针就指向了一个无效的内存地址。这会导致访问非法内存,进而出现读取权限冲突。为了避免这个问题,你可以考虑使用序列化和反序列化来实现文件的读写操作。序列化是指将对象转换为序列化的字节流,而反序列化则是将字节流重新转换为对象。通过序列化和反序列化操作,可以确保对象的完整性和正确性。你可以使用C++的一些库(如Boost.Serialization、Protocol Buffers)来实现对象的序列化和反序列化。这些库提供了易于使用和强大的功能,让你可以方便地进行对象的读写操作,而不会发生读取权限冲突的问题。

在C++中,文件读写类对象时,是可以包含string类型的成员变量的。C++的文件读写操作对于大多数基本类型和标准库类型(包括string)都有支持。当你将一个自定义的类对象写入文件时,包含了string类型成员变量的类实例将被完整地写入文件中。但需要注意的是,string对象的存储是动态的,所以仅将类对象的二进制数据写入文件是不够的,还需要将string的内容一并写入文件,并在读取时进行相应处理。你可以使用C++标准库中的fstream类进行文件读写操作。例如,可以使用ofstream类对象将类对象写入文件,再使用ifstream类对象从文件中读取类对象。在写入时,可以使用成员函数c_str()将string类型转换为C风格字符串,并使用成员函数write()写入文件;在读取时,可以使用成员函数getline()读取文件中的字符串,并重新构造string对象。

注意,在进行文件读写操作时,需要保证文件的打开和关闭操作正确执行,并处理可能出现的异常情况,以确保数据的完整性与安全性。同时,为了确保跨平台的文件读写兼容性,建议在二进制读写时使用文本模式(例如使用"rb"和"wb"参数)。

以下是一个简单的示例代码,演示了如何进行文件读写操作:

#include <fstream>
#include <iostream>
#include <string>

class MyClass {
public:
    std::string name;
    int age;
};

int main() {
    MyClass obj;
    obj.name = "Alice";
    obj.age = 20;

    std::ofstream outfile("data.txt", std::ios::binary);
    if (outfile.is_open()) {
        outfile.write(obj.name.c_str(), obj.name.length() + 1);
        outfile.write(reinterpret_cast<char*>(&obj.age), sizeof(obj.age));
        outfile.close();
        std::cout << "对象写入文件成功" << std::endl;
    } else {
        std::cout << "打开文件失败" << std::endl;
        return 1;
    }

    std::ifstream infile("data.txt", std::ios::binary);
    if (infile.is_open()) {
        std::string name;
        std::getline(infile, name, '\0');
        obj.name = name;
        infile.read(reinterpret_cast<char*>(&obj.age), sizeof(obj.age));
        infile.close();

        std::cout << "从文件中读取的对象:" << std::endl;
        std::cout << "name: " << obj.name << std::endl;
        std::cout << "age: " << obj.age << std::endl;
    } else {
        std::cout << "打开文件失败" << std::endl;
        return 1;
    }

    return 0;
}

该示例中,定义了一个包含string类型成员变量的MyClass类,通过ofstream对象将类的实例写入文件,再通过ifstream对象从文件中读取类对象。在写入时,使用了成员函数c_str()获取string对象的C风格字符串;在读取时,使用了成员函数getline()读取字符串,并重新构造了string对象。最后,将读取到的类对象的成员变量输出到控制台。

问题②、c++中,在文件操作中,为什么读取完数据后,要关闭文件,才能写入数据到文件?  

在C++中,关闭文件的目的不是为了读取完数据后才能写入数据到文件,而是为了确保对文件进行完整的操作并释放相关资源。

文件在被打开后会占用一些系统资源,如文件描述符等。当读取完数据后,如果不关闭文件,文件依然保持打开状态,此时其他程序可能无法对该文件进行操作或者文件的状态可能不会及时更新。此外,一些操作系统可能会限制同时打开的文件数量,如果不关闭文件,可能会达到限制而导致其他文件无法正常打开。最重要的是,关闭文件还可以确保数据的完整性和正确性。在写入数据时,操作系统会将数据缓存到内存中,然后根据一定的策略将数据写入到文件中,这个过程是异步的。如果在写入数据的过程中突然关闭文件,可能会导致数据丢失或不完整。

因此,为了保证文件操作的正确性和系统资源的释放,我们通常会在读取完数据后关闭文件,然后再进行写入操作。这样可以确保文件的状态正确、数据的完整性并释放相关的资源。


17、分数的加减

//定义分数类,内有构造函数和显示分数的show函数,并利用友元函数实现分数的加减
#include<iostream>
using namespace std;

class Fraction
{
private:
	double dividend, divisor;//dividend:被除数,即分子 divisor:除数,即分母
public:
	Fraction(const double& divid = 0.0, const double& divir = 0.0)
		:dividend(divid)
		,divisor(divir)
	{}

	void show()
	{
		cout << dividend << "/" << divisor << endl;
	}

	friend Fraction operator+(const Fraction&, const Fraction&);
	friend Fraction operator-(const Fraction&, const Fraction&);
};

Fraction operator+(const Fraction& f1, const Fraction& f2)
{
	return Fraction(f1.dividend * f2.divisor + f1.divisor * f2.dividend
		, f1.divisor * f2.divisor);
}

Fraction operator-(const Fraction& f1, const Fraction& f2)
{
	return Fraction(f1.dividend * f2.divisor - f1.divisor * f2.dividend
		, f1.divisor * f2.divisor);
}

int main()
{
	Fraction f1(2, 3), f2(1, 2), f3;
	f3 = f1 + f2;
	f3.show();
	f3 = f1 - f2;
	f3.show();
	
	return 0;
}


 18、统计字符数组中某个字符出现次数

//定义求一个字符数组中某字符有多少个的函数sum(),用c++实现
#include<iostream>
using namespace std;

int sum(char* arr, char target)
{
	int cnt = 0;
	int i = 0;
	while (arr[i] != '\0')
	{
		if (arr[i] == target)
			cnt++;
		i++;
	}

	return cnt;
}

int main()
{
	char arr[] = "hello world!";
	char target = 'o';
	int ret = sum(arr, target);
	cout << target << "出现了:" << ret << "次" << endl;

	return 0;
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1358826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全网最简单vscode使用Makefile调试多文件的C/C++代码

前言 vscode调试C/C教程很多&#xff0c;操作麻烦&#xff0c;这里试图找到一个最简单的使用vscode调试C/C代码的方法。这里是使用Makefile的多文件方式。 测试文件 tree . ├── func.c ├── func.h ├── main.c └── Makefilefun.c #include <stdio.h> #in…

对低效的会议说“不!”

根据微软对全球 31, 000 名员工开展的一项调查&#xff0c;低效的会议是影响工作效率的第一大干扰因素&#xff0c;其次是召开过多的会议。 大大小小的同步会、讨论会、审查会、复盘会不仅将工作时间拆解得支离破碎&#xff0c;还会让成员因「会议恢复综合症」而无法立即从无效…

Certum与Geotrust的OV多域名证书

Certum和Geotrust都是知名的CA认证机构&#xff0c;旗下的SSL证书产品丰富&#xff0c;有单域名SSL证书、多域名SSL证书以及通配符SSL证书。这些SSL数字证书作为一种重要的网络安全产品&#xff0c;能够实现数据加密和身份验证&#xff0c;保障网站的安全性和隐私性。OV多域名S…

【快速全面掌握 WAMPServer】14.各种组件的升级方法

网管小贾 / sysadm.cc WAMPServer 更新很快&#xff0c;这是件好事&#xff01; 但是 WAMPServer 更新快是因为他很勤劳吗&#xff1f; 其实这个问题的原因并不是出自 WAMPServer 自身&#xff0c;而是来自它的各个组件。 是的&#xff0c;你能想像得到&#xff0c;比如 PHP…

数据结构和算法-数据结构的基本概念和三要素和数据类型和抽象数据类型

文章目录 总览数据结构的基本概念总览数据早期和现代的计算机处理的数据数据元素-描述一个个体数据对象-一类数据元素什么是数据结构小结 数据结构的三要素总览逻辑结构-集合结构逻辑结构-线性结构逻辑结构-树形结构逻辑结构-图形结构逻辑结构-小结数据的运算物理结构&#xff…

Struts2 远程代码执行漏洞S2-001分析

自 Struts2 在 2007 年爆出第一个远程代码执行漏洞 S2-001 以来&#xff0c;在其后续的发展过程中不断爆出更多而且危害更大的远程代码执行漏洞&#xff0c;而造成 Struts2 这么多 RCE 漏洞的主要原因就是 OGNL 表达式。这里以 Struts2 的第一个漏洞 S2-001 为例来对 Struts2 远…

新年启新程 | 开门红!菊风中标重庆三峡银行双录及产品销售可回溯系统项目

INTRODUCTION 近年来&#xff0c;随着人们需求的转变和金融科技的高速发展&#xff0c;银行开始朝着数智化方向转型。为顺应客户行为变迁&#xff0c;银行同业积极构建远程银行云服务生态。同时&#xff0c;面对业务的升级以及新的监管要求&#xff0c;现有音视频功能难以满足…

第三届先进控制、自动化与机器人国际会议(ICACAR 2024) | Ei、Scopus双检索

会议简介 Brief Introduction 2024年第三届先进控制、自动化与机器人国际会议(ICACAR 2024) 会议时间&#xff1a;2024年5月24-26日 召开地点&#xff1a;中国重庆 大会官网&#xff1a;ICACAR 2024-2024 3rd International Conference on Advanced Control, Automation and Ro…

yolov8 tracking编码为web 和 rtsp流输出

1 基础工作 打开cmd 输入 conda env list 输入 conda activate py38 查看 nvidia-smi 查看 nvcc&#xff0c;如下图所示 cuda为11.7 &#xff0c;为确认可以查看program files 下面的cuda 安装&#xff0c;看到11.7 就行了&#xff0c;读者可以自行确认自己的版本。 查看nvid…

第 378 场 LeetCode 周赛题解

A 检查按位或是否存在尾随零 枚举&#xff1a;枚举两个元素的组合即可 class Solution { public:bool hasTrailingZeros(vector<int> &nums) {int n nums.size();for (int i 0; i < n; i)for (int j 0; j < i; j)if ((nums[i] | nums[j]) % 2 0)return tru…

无痛迁移:图解 Kubernetes 集群升级步骤

本文探究了Kubeadm集群升级工作流程&#xff0c;并以可视化方式展现。着重介绍了控制平面节点和工作节点的升级步骤&#xff0c;涵盖了kubeadm升级、节点清空、kubelet和kubectl升级&#xff0c;以及解除节点封锁的关键步骤。 这个简明扼要的指南可帮助用户理解和执行Kubernete…

视频号掀起内容新风向,这几类账号为何爆红?

12月初&#xff0c;视频号就迎来了好消息&#xff0c;官方发布消息称&#xff0c;视频号作者加入互选的门槛由10000粉调整为5000粉&#xff0c;其他条件不变。此举旨在激励更多创作者积极投入视频内容创作&#xff0c;从而获得更多商业合作的机会和收益。 为帮助大家更好地洞察…

lf 的年终总结(2023)

这一年&#xff0c; 我没有进行总结&#xff0c; 只有年终的回顾。 是的&#xff0c; 我又长了一岁&#xff0c; 同时也度过了三年的开发经历&#xff0c; 即将进入五年 Android 开发的阶段。 我只希望在新的一年里能够好好学习&#xff0c;期待有所提升。 回顾过去的生活&…

51单片机四位数码管计算器 Proteus仿真程序

目录 概要 仿真图 部分代码 资料下载地址&#xff1a;51单片机四位数码管计算器 Proteus仿真程序 概要 1.系统通过4x4的矩阵键盘输入数字及运算符。 2.可以进行4位十进制数以内的加法运算&#xff0c;如果计算结果超过4位十进制数&#xff0c;则屏幕显示E 3.可以进行加法以外…

工作中人员离岗识别摄像机

工作中人员离岗识别摄像机是一种基于人工智能技术的智能监控设备&#xff0c;能够实时识别员工离岗状态并进行记录。这种摄像机通常配备了高清摄像头、深度学习算法和数据处理系统&#xff0c;可以精准地监测员工的行为&#xff0c;提高企业的管理效率和安全性。 工作中人员离岗…

DevOps搭建(十二)-Jenkins推送镜像到Harbor详解

什么是Harbor&#xff1f;Harbor 是一个开源的企业级容器镜像仓库&#xff0c;它提供了安全、可靠、高效的镜像管理和分发功能。 Harbor 支持 Docker 镜像和 Helm Chart&#xff0c;可以与其他云原生工具和平台集成&#xff0c;如 Kubernetes、Docker Swarm 等。 使用 Harbor&a…

多线程和JVM

一&#xff0c;多线程实现的四种方式 1. 实现Runnable接口 普通实现&#xff1a; public class MyRunnable implements Runnable {Overridepublic void run() {System.out.println("线程执行中...");} }public class Main {public static void main(String[] arg…

CSS基本知识

文章目录 1. CSS 是什么2. 基本语法规范3. 引入方式3.1 内部样式表3.2 行内样式表3.3 外部样式 4. 选择器4.1 选择器的功能4.2 选择器的种类4.3 基础选择器4.3.1 标签选择器4.3.2 类选择器4.3.3 id 选择器4.3.4 通配符选择器 4.4 复合选择器4.4.1 后代选择器4.4.2 伪类选择器 5…

Flink Connector 开发

Flink Streaming Connector Flink是新一代流批统一的计算引擎&#xff0c;它需要从不同的第三方存储引擎中把数据读过来&#xff0c;进行处理&#xff0c;然后再写出到另外的存储引擎中。Connector的作用就相当于一个连接器&#xff0c;连接Flink计算引擎跟外界存储系统。Flin…

查看进程对应的路径查看端口号对应的进程ubuntu 安装ssh共享WiFi设置MyBatis 使用map类型作为参数,复杂查询(导出数据)

Linux 查询当前进程所在的路径 top 命令查询相应的进程号pid ps -ef |grep 进程名 lsof -I:端口号 netstat -anp|grep 端口号 cd /proc/进程id cwd 进程运行目录 exe 执行程序的绝对路径 cmdline 程序运行时输入的命令行命令 environ 记录了进程运行时的环境变量 fd 目录下是进…