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;
}