C++编程出错笔记

strcpy出错问题

  • 代码:
#include<iostream>
using namespace std;
class String {
private:
	char* str;
public:
	String() :str(new char[1]) { str[0] = 0; }
	const char* c_str() { return str; };
	String& operator=(const char* s );
	~String( ) { delete[]str; }
};
String& String::operator=(const char* s) {
			//重载“=”以使得obj="hello"能够成立
	delete[]str;
	str = new char[strlen(s) + 1];
	strcpy_s(str, strlen(s) + 1, s);
	return *this;
}
int main() {
	String s;
	s = "Good Luck,"; //等价于s.operator=("Good Luck,");
	cout << s.c_str() << endl;
	//String s2="hello!";  //这条语句要是不注释掉就会出错
	s = "shenzhou 8!"; //等价于s.operator=("shenzhou 8!");
	cout << s.c_str() << endl;
	return 0;
}

正常来说,语法上没有任何问题,但是运行时,Visual Studio 2019 会报错,显示如下:

在这里插入图片描述

  • 出错原因:

    系统认为strcpy()函数不够安全

  • 修改:

strcpy(str,  s);

改为:

strcpy_s(str, s);

再出错:
在这里插入图片描述

  • 出错原因:

    使用new来分配储存空间时,不能保证缓冲区大小

  • 再修改:

使用3个参数的版本。在 str 和 s 之间,加上一个参数,标识长度。

一般的做法就是将长度定为被复制的字符串长度+1。

因为strlen()返回字符串长度,但是不包括字符串末尾的空字符,所以+1。

strcpy_s(str, strlen(s) + 1, s);
  • 运行成功:
    在这里插入图片描述

CArray函数

  • 代码:
#include<iostream>
using namespace std;
class CArray {
	int size; //数组元素的个数
	int* ptr; //指向动态分配的数组
public:
	CArray(int s = 0); //s代表数组元素的个数
	CArray(CArray& a);
	~CArray();
	void push_back(int v); //用于在数组尾部添加一个元素v
	CArray& operator=(const CArray& a);
	//用于数组对象间的赋值
	int length() { return size; }//返回数组元素个数
	int&operator[](int i){ //返回值为int不行!不支持a[i]=4
		//用以支持根据下标访问数组元素,
		//如n=a[i]和a[i]=4;这样的语句
		return ptr[i];
	}
};
CArray::~CArray() {
	if (ptr)delete[]ptr;
}
CArray& CArray::operator=(const CArray& a) {
	//赋值号的作用是使“=”左边对象里存放的数组,大小和内容都和右边的对象一样
	if (ptr == a.ptr) //防止a=a这样的赋值导致出错
		return *this;
	if (a.ptr == NULL) { //如果a里面的数组是空的
		if (ptr)delete[]ptr;
		ptr = NULL;
		size = 0;
		return*this;
	}
	if (size < a.size) { //如果原有空间够大,就不用分配新的空间
		if (ptr)
			delete[]ptr;
		ptr = new int[a.size];
	}
	memcpy(ptr, a.ptr, sizeof(int) * a.size);
	size = a.size;
	return*this;
} //CArray& CArray::operator=(const CArray& a)
void CArray::push_back(int v) {
	//在数组尾部添加一个元素
	if (ptr) {
		int* tmpPtr = new int[size + 1]; //重新分配空间
		memcpy(tmpPtr, ptr, sizeof(int) * size); //拷贝原数组内容
		delete[]ptr;
		ptr = tmpPtr;
	}
	else //数组本来是空的
		ptr = new int[1];
	ptr[size++] = v; //加入新的数组元素
}
CArray::CArray(int s) :size(s) {
	if (s == 0)
		ptr = NULL;
	else
		ptr = new int[s];
}
CArray::CArray(CArray& a) {
	if (!a.ptr) {
		ptr = NULL;
		size = 0;
		return;
	}
	ptr = new int[a.size];
	memcpy(ptr, a.ptr, sizeof(int) * a.size);
	size = a.size;
}
int main() { //要编写可变长整型数组类,使之能如下使用:
	CArray a; //开始里的数组是空的
	for (int i = 0; i < 5; ++i)
		a.push_back(i);     //要用动态分配的内存来存放数组元素,需要一个指针成员变量
	CArray a2, a3;
	a2 = a;     //要重载“=”
	for (int i = 0; i < a.length(); ++i)
		cout << a2[i] << " ";   //要重载“[]”
	a2 = a3; //a2是空的
	for (int i = 0; i < a2.length(); ++i) //a2.length()返回()
		cout << a2[i] << " ";
	cout << endl;
	a[3] = 100;
	CArray a4(a);   //要自己写复制构造函数
	for (int i = 0; i < a4.length(); ++i)
		cout << a4[i] << " ";
	return 0;
}
// 输出结果:
// 0 1 2 3 4
// 0 1 2 100 4
  • 问题:
    在这里插入图片描述
  • 解决:
    删去 CArray::
int&operator[](int i)
  • 运行:
    在这里插入图片描述
  • 原因:
    在这里插入图片描述
  • 解决:
    在这里插入图片描述
  • 运行:
    在这里插入图片描述

函数仅声明未定义

学藉管理系统

#include<iostream>
#include<string>
using namespace std;
class CStudent {
private:
	string name;
	string id; //学号
	char gender; //性别,‘F’代表女,‘M’代表男
	int age;
public:
	void PrintInfo();
	void SetInfo(const string& name_, const string& id_,int age_, char gender_);
	string GetName() { return name; }
};
class CUndergraduateStudent :public CStudent {
	//本科生类,继承了CStudent类
private:
	string department; //学生所属的系的名称
public:
	void QualifiedForBaoyan() { //给予保研资格
		cout << "qualified for baoyan" << endl;
	}
	void PrintInfo() {
		CStudent::PrintInfo(); //调用基类的PrintInfo
		cout << "Department:" << department << endl;
	}
	void SetInfo(const string& name_, const string& id_,int age_, char gender_, const string& department_) {
		CStudent::SetInfo(name_, id_, age_, gender_); //调用基类的SetInfo
		department = department_;
	}
};
int main() {
	CUndergraduateStudent s2;
	s2.SetInfo("Harry Potter", "118829212", 19, 'M', "Computer Science");
	cout << s2.GetName() << " ";
	s2.QualifiedForBaoyan();
	s2.PrintInfo();
	return 0;
}

运行出错,函数仅声明未定义:

void PrintInfo();
	void SetInfo(const string& name_, const string& id_,
		int age_, char gender_);

定义函数:

void CStudent::PrintInfo() {
	cout << "Name:" << name << endl;
	cout << "ID:" << id << endl;
	cout << "Age:" << age << endl;
	cout << "Gender:" << gender << endl;
}
void CStudent::SetInfo(const string& name_, const string& id_,int age_, char gender_) {
	name = name_;
	id = id_;
	age = age_;
	gender = gender_;
}

完整代码:

#include<iostream>
#include<string>
using namespace std;
class CStudent {
private:
	string name;
	string id; //学号
	char gender; //性别,‘F’代表女,‘M’代表男
	int age;
public:
	void PrintInfo();
	void SetInfo(const string& name_, const string& id_,
		int age_, char gender_);
	string GetName() { return name; }
};
class CUndergraduateStudent :public CStudent {
	//本科生类,继承了CStudent类
private:
	string department; //学生所属的系的名称
public:
	void QualifiedForBaoyan() { //给予保研资格
		cout << "qualified for baoyan" << endl;
	}
	void PrintInfo() {
		CStudent::PrintInfo(); //调用基类的PrintInfo
		cout << "Department:" << department << endl;
	}
	void SetInfo(const string& name_, const string& id_,
		int age_, char gender_, const string& department_) {
		CStudent::SetInfo(name_, id_, age_, gender_); //调用基类的SetInfo
		department = department_;
	}
};
void CStudent::PrintInfo() {
	cout << "Name:" << name << endl;
	cout << "ID:" << id << endl;
	cout << "Age:" << age << endl;
	cout << "Gender:" << gender << endl;
}
void CStudent::SetInfo(const string& name_, const string& id_,int age_, char gender_) {
	name = name_;
	id = id_;
	age = age_;
	gender = gender_;
}
int main() {
	CUndergraduateStudent s2;
	s2.SetInfo("Harry Potter", "118829212", 19, 'M', "Computer Science");
	cout << s2.GetName() << " ";
	s2.QualifiedForBaoyan();
	s2.PrintInfo();
	return 0;
}

没有与这些操作数匹配的 “>>” 运算符cin >> number;

解决方案:

因为number为string[]类型,所以改成
for (int i=0; i < 100; i++) {
cin >> number[i];
}

怎么让程序中的类按顺序执行

写了好几个类,以CarManager类为基类,派生出Car类,之后以Car类为基类派生出几个功能类。想让这些类从CarManager类开始往下

解决方案:

在网上查来查去,最后发现要大改。详细看了自己在博客上的C++网课知识学习笔记后,觉得多态比较适合,就按照笔记上的知识来改动。
先将CarManager类的两个成员函数都改成虚函数,在main中调用。Car类保持不变,以其为基类派生出CarInfo类,在CarInfo类中创建一个carinfo函数来输入车辆信息并计算不同车型时长的停车费用。之后,将几个功能类都转化成CarInfo类的虚函数,在main里调用。

虚函数的调用出错

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解决方案:

1、 将虚函数里的参数去掉,在函数体内定义标识符。
2、 在main函数体内的ID和KEY后增加()
在这里插入图片描述
在这里插入图片描述

可用车位的统计时灵时不灵

在这里插入图片描述
在这里插入图片描述

解决方案:

1、在基类Car类增加int num=0;
2、在virtual void carinfo()函数内增加
cout << “车辆数:”;
cin >> num;
3、 将number->size()改为sumps-num
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

未初始化数组

在这里插入图片描述
在这里插入图片描述

解决方案:

在相关数组后增加= {0.0},使其初始化即可。
在这里插入图片描述

停车管理系统的汽车入场离场信息不分开处理

原代码:

#include <iostream>
using namespace std;
class CarManager {		//管理员类
public:
	 void ID() {			//账户
		string id;
		cout << "输入id: ";
		cin >> id;
		while (id != "admin") {
			cout << "输入错误,重新输入id:\n";
			cin >> id;
		}
	};
	 void KEY() {			//密码
		string key;
		cout << "输入密码: ";
		cin >> key;
		while (key != "1234") {
			cout << "输入错误,重新输入密码:\n";
			cin >> key;
		}
		cout << "登陆成功!" << endl;
	};
};

class Car {					//汽车类
public:							
	string number[10];					//车牌号
	string model[10];					//车型
	double enterTime[10] = { 0.0 };				//进场时间
	double quitTime[10] = { 0.0 };				//离场时间
	double totalTime[10] = { 0.0 };				//停车时长
	double price[10] = { 0.0 };					//每小时收费价
	double cost[10] = { 0.0 };					//停车费用
	double sumps = 10;					//总车位
	int num = 0;							//车辆数
};

class CarInfo :public Car {		 //汽车相关信息类
public:
	 void carinfo() {
		cout << "车辆数:";
		cin >> num;
		cout << "车牌号" << "\t" << " 车型 " << "\t" << "入场时间" << "\t" << "离场时间:\n";
		for (int i = 0; i < num; i++) {
			cin >> number[i] >> model[i] >> enterTime[i] >> quitTime[i];	//输入车辆信息
			while ( enterTime[i] > 24 || enterTime[i] < 0 || quitTime[i]>24 || quitTime[i] < 0) {
				cout << "输入错误,重新输入:\n";
				cin >> number[i] >> model[i] >> enterTime[i] >> quitTime[i];
			}
			totalTime[i] = quitTime[i] - enterTime[i];
			if (model[i] == "大型车") {			//不同车型的停车费用不同
				price[i] = 20;
				cost[i] = totalTime[i] * price[i];
			}
			else if (model[i] == "中型车") {
				price[i] = 15;
				cost[i] = totalTime[i] * price[i];
			}
			else if (model[i] == "小型车") {
				price[i] = 10;
				cost[i] = totalTime[i] * price[i];
			}
			cout << "车辆信息登记成功!" << endl; 
		}
	}
	 void parkingsapce();			//可用车位统计与查询
	 void noparkingsapce();			//零车位提示
	 void parkingtime();			//停车时长统计
	 void carcast();				//按车型时长收费 
	 void totalcost();				//管理员收费累计
};

void CarInfo::parkingsapce() {				//可用车位统计与查询
	cout << "可用车位: " << sumps - num << endl;
}

void CarInfo::noparkingsapce() {			//零车位提示

	if (num == sumps)
		cout << "车位已满!" << endl;
	else
		cout << "车位未满!" << endl;
}

void CarInfo::parkingtime() {				//停车时长统计
	for (int i = 0; i < num; i++) {
		cout << number[i] << "\t" << "停车时长: " << totalTime[i] << endl;
		if (number[i + 1] == "0")break;		//停止且防止number[i]==0时的干扰
	}
}

void CarInfo::carcast() {					//按车型时长收费
	for (int i = 0; i < num; i++) {
		cout << number[i] << "\t" << model[i] << "\t" << "停车费用: " << cost[i] << endl;
		if (number[i + 1] == "0")break;
	}
}

void CarInfo::totalcost() {					//管理员收费累计
	double addcost = 0;
	for (int i = 0; i < num; i++) {
		addcost += cost[i];
		if (cost[i + 1] <= 0)break;			//停止且防止cost[i]==0时的干扰
	}
	cout << "管理员收费累计: " << addcost << endl;
}

int main() {
	CarManager cm;			
	cm.ID();
	cm.KEY();
	CarInfo ci;
	cout << "==========================================" << endl;
	cout << endl;
	cout << " ***************功能菜单***************** " << endl;
	cout << endl;
	cout << "=          1.车辆信息登记                =" << endl;
	cout << "=          2.可用车位统计与查询          =" << endl;
	cout << "=          3.零车位提示                  =" << endl;
	cout << "=          4.停车时长统计                =" << endl;
	cout << "=          5.按车型时长收费              =" << endl;
	cout << "=          6.管理员收费累计              =" << endl;
	cout << "=          7.退出菜单                    =" << endl;
	cout << endl;
	cout << "==========================================" << endl;
	cout << "请选择:" << endl;
	int n;
	while (1) {
		cin >> n;
		if (0 < n && n < 7)		//限定n的范围
			switch (n) {				//调用函数,实现功能		
			case 1:ci.carinfo(); break;
			case 2:ci.parkingsapce(); break;
			case 3:ci.noparkingsapce(); break;
			case 4:ci.parkingtime(); break;
			case 5:ci.carcast(); break;
			case 6:ci.totalcost(); break;
			}
		else break;				//退出
	}
	return 0;
}

解决方案:

将carinfo函数去掉,新增入场和离场两个函数,在将函数完善。

注意:

  • 区分开入场车牌号和离场车牌号
  • 入场信息和离场信息一起使用时,信息的处理
 for (int j = 0; j < num2; j++) {
		for (int i = 0; i < num1; i++) {
			if (number1[i] == number2[j]) {
				totalTime[i] = quitTime[j] - enterTime[i];
			}
		}
	}

完善后的代码

#include <iostream>
using namespace std;
class CarManager {		//管理员类
private:
	string id;
	string key;
public:
	 void ID() {			//账户
		cout << "输入id: ";
		cin >> id;
		while (id != "admin") {
			cout << "输入错误,重新输入id:\n";
			cin >> id;
		}
	};
	 void KEY() {			//密码
		cout << "输入密码: ";
		cin >> key;
		while (key != "1234") {
			cout << "输入错误,重新输入密码:\n";
			cin >> key;
		}
		cout << "登陆成功!" << endl;
	};
};

class Car {					//汽车类
private:							
	string number1[10];							//入场车牌号
	string number2[10];							//离场车牌号
	string model[10];							//车型
	double enterTime[10] = { 0.0 };				//进场时间
	double quitTime[10] = { 0.0 };				//离场时间
	double totalTime[10] = { 0.0 };				//停车时长
	double price[10] = { 0.0 };					//每小时收费价
	double cost[10] = { 0.0 };					//停车费用
	int sumps = 10;							//总车位
	int num1 = 0;							//入场车辆数
	int num2 = 0;							//离场车辆数
public:
	void carin();					//车辆进场
	void carout();					//车辆离场
	void parkingtime();				//停车时长统计
	void carcast();					//按车型时长收费 
	void parkingsapce();			//可用车位统计与查询
	void noparkingsapce();			//零车位提示
	void totalcost();				//管理员收费累计
};

void Car::carin() {				//车辆进场
	cout << "入场车辆数:";
	cin >> num1;
	while (num1<0 || num1>10) {
		cout << "输入错误,重新输入:\n";
		cin >> num1;
	}
	cout << "车牌号" << "\t" << " 车型 " << "\t" << "入场时间" << endl;
	for (int i = 0; i < num1; i++) {
		cin >> number1[i] >> model[i] >> enterTime[i];	//输入车辆入场信息
		while (enterTime[i] > 24 || enterTime[i] < 0) {
			cout << "输入错误,重新输入:\n";
			cin >> number1[i] >> model[i] >> enterTime[i];
		}
		cout << "车辆入场登记成功!" << endl;
	}
	cout << endl;
}

void Car::carout() {				//车辆离场
	cout << "离场车辆数:";
	cin >> num2;
	while (num2 < 0 || num2>10) {
		cout << "输入错误,重新输入:\n";
		cin >> num2;
	}
	cout << "车牌号" << "\t" << "离场时间" << endl;
	for (int i = 0; i < num2; i++) {
		cin >> number2[i] >> quitTime[i];	//输入车辆离场信息
		while (quitTime[i] > 24 || quitTime[i] < 0) {
			cout << "输入错误,重新输入:\n";
			cin >> number2[i] >> quitTime[i];
		}
		cout << "车辆离场登记成功!" << endl;
	}
	num1 -= num2;
	cout << endl;
};

void Car::parkingtime() {				//停车时长统计
	for (int j = 0; j < num2; j++) {
		for (int i = 0; i < num1; i++) {
			if (number1[i] == number2[j]) {
				totalTime[i] = quitTime[j] - enterTime[i];
			}
		}
	}
	for (int k = 0; k < sumps; k++) {
		if (totalTime[k] > 0) {
			cout << number1[k] << "\t" << "停车时长: " << totalTime[k] << endl;
		}
	}
	cout << endl;
}

void Car::carcast() {					//按车型时长收费
	for (int i = 0; i < num1; i++) {
		if (model[i] == "大型车") {			//不同车型的停车费用不同
			price[i] = 20;
			cost[i] = totalTime[i] * price[i];
		}
		else if (model[i] == "中型车") {
			price[i] = 15;
			cost[i] = totalTime[i] * price[i];
		}

		else if (model[i] == "小型车") {
			price[i] = 10;
			cost[i] = totalTime[i] * price[i];
		}
	}
		for (int i = 0; i < sumps; i++) {
			if (totalTime[i] > 0) {
				cout << number1[i] << "\t" << model[i] << "\t" << "停车费用: " << cost[i] << endl;
			}
		}
		cout << endl;
}

void Car::parkingsapce() {				//可用车位统计与查询
	cout << "可用车位: " << sumps-num1 << endl;
	cout << endl;
}

void Car::noparkingsapce() {			//零车位提示
	if (num1 == sumps)
		cout << "车位已满!" << endl;
	else
		cout << "车位未满!" << endl;
	cout << endl;
}

void Car::totalcost() {					//管理员收费累计
	double addcost = 0;
	for (int i = 0; i < sumps; i++) {
		addcost += cost[i];
	}
	cout << "管理员收费累计: " << addcost << endl;
	cout << endl;
}

int main() {
	CarManager cm;			
	cm.ID();
	cm.KEY();
	Car ci;
	cout << "==========================================" << endl;
	cout << endl;
	cout << " ***************功能菜单***************** " << endl;
	cout << endl;
	cout << "=          1.车辆入场登记                =" << endl;
	cout << "=          2.车辆离场登记                =" << endl;
	cout << "=          3.停车时长统计                =" << endl;
	cout << "=          4.按车型时长收费              =" << endl;
	cout << "=          5.可用车位统计与查询          =" << endl;
	cout << "=          6.零车位提示                  =" << endl;
	cout << "=          7.管理员收费累计              =" << endl;
	cout << "=          8.退出菜单                    =" << endl;
	cout << endl;
	cout << "==========================================" << endl;
	int n;
	while (cout << "选择功能:") {
		cin >> n;
		if (0 < n && n < 8)		//限定n的范围
			switch (n) {				//调用函数,实现功能		
			case 1:ci.carin(); break;
			case 2:ci.carout(); break;
			case 3:ci.parkingtime(); break;
			case 4:ci.carcast(); break;
			case 5:ci.parkingsapce(); break;
			case 6:ci.noparkingsapce(); break;
			case 7:ci.totalcost(); break;
			}
		else break;				//退出
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Driver.SHAO

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

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

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

打赏作者

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

抵扣说明:

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

余额充值