class 数组中的 C++ 深度复制 const char *?
C++ deep copy const char * inside of class array?
所以我在制作 class 时遇到了问题。在这个 class 我应该有一些数据的数组。我对分配和创建新数据没有问题,例如 x2.NewAccount("123456" , 1000);这工作正常问题是当我试图用寻址到某个变量的字符串创建数据时。我知道一些关于深度复制的知识,但我不知道如何编程 = operator 在我的情况下 + 我认为 strcpy 但那也不起作用。
PS:这是一个学校程序,所以请不要因为我没有使用 headers 和使用一堆我没有在代码中使用的包含而评判我。它是由我的学校制作的,我不允许更改它们 + 添加它们(我知道使用来自 c++ 的字符串会容易得多。)。
谢谢你的帮助。
#ifndef __PROGTEST__
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <cctype>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
#endif /* __PROGTEST__ */
struct data_history{
int money = 0;
bool Income;
const char * UnStr;
const char * to_from;
};
struct client{
const char * accID;
int Balance;
int def_bal;
data_history * history;
int in_index = 0;
int in_cap = 10;
friend ostream &operator << (ostream &output , client p){
output << p.accID << ":" << endl << " " << p.def_bal << endl;
for (int i = 0 ; i < p.in_index ; i++){
if (p.history[i].Income == false)
output << " - " << abs(p.history[i].money) << ", to: " << p.history[i].to_from << ", sign: " << p.history[i].UnStr << endl;
else
output << " + " <<abs(p.history[i].money) << ", from: " << p.history[i].to_from << ", sign: " << p.history[i].UnStr << endl;
}
output << " = " << p.Balance << endl;
return output;
}
};
class CBank
{
public:
int cap = 10;
int index = 0;
client * database;
~CBank(){
for (int i = 0 ; i < index ; i++)
delete[] database[i].history;
delete[]database;
}
CBank(){
database = new client[cap];
}
bool NewAccount ( const char * accID, int initialBalance ){
for(int i = 0 ; i < index ; i ++)
if (accID == database[i].accID) {
return false;
}
//strcpy (database[index].accID , accID ); // Im getting errors while compileing (cuz I was using const char * for database.accID when i chenged it i got program crash.
database[index].accID = accID;
database[index].Balance = initialBalance;
database[index].def_bal = initialBalance;
database[index].in_cap = 10;
database[index].history = new data_history[database[index].in_cap];
index ++;
return true;
}
client Account (const char * accID ){
const char * input =accID;
for (int i = 0 ; i < index ; i++){
if (database[i].accID == input )
return database[i];
}
throw "error";
}
void print (){
for (int i = 0 ; i < index ; i ++) {
cout << endl;
cout << i << " = "<< " ID = " << database[i].accID << " | Balance = " << database[i].Balance << endl;
cout << "===Account history ===\n\n";
for (int y = 0 ; y < database[i].in_index; y++) {
cout << "Was it for him? : " << boolalpha << database[i].history[y].Income
<< "\nHow much : " << database[i].history[y].money << "\nUnique string : "
<< database[i].history[y].UnStr << "\nfrom/to: " << database[i].history[y].to_from << endl << endl;
}
}
}
private:
};
#ifndef __PROGTEST__
int main ( void )
{
char accCpy[100], debCpy[100], credCpy[100], signCpy[100];
CBank x2;
strncpy ( accCpy, "123456", sizeof ( accCpy ) );
assert ( x2 . NewAccount ( accCpy, 1000 ) );
x2 . print();
cout << "\n\n\n\n";
strncpy ( accCpy, "987654", sizeof ( accCpy ) );
assert ( x2 . NewAccount ( "987654", -500 ) );
x2 . print();
}
#endif /* __PROGTEST__ */
当使用 database[index].accID = accID;
时,你只是在做一个浅拷贝(并且依赖于调用者来保持这个内存有效,因为指针可能被访问)。
您已经正确地确定您需要执行深拷贝,但是 client::accID
只是一个指针,但是在您将其初始化为指向某个内存之前,您不能将其复制到其中。
实现此目的的一种方法是动态分配和管理 client::accID
,类似于动态分配和管理 client::history
。
而不是 strcpy (database[index].accID , accID );
或 database[index].accID = accID;
,试试:
size_t bufsize = strlen(accID) + 1;
char *buf = new char[bufsize];
memcpy(buf, accID, bufsize);
database[index].accID = buf;
并在析构函数中添加:
delete[] database[i].accID
正如其他人所指出的那样,这种 C++ 编程风格非常容易出错,并且不受社区的欢迎。使用标准库 类 可以轻松避免这种手动内存管理。即使进行了上述更改,如果您开始复制 CBank
对象,您的程序仍将 运行 进入未定义行为。
即使您的作业不需要这样做,您也应该考虑尝试将其重写为练习:
std::string
而不是 accID;
的 C 字符串
std::vector
而不是 data_history
数组
另供参考:
if (database[i].accID == input )
不会用 C 字符串做预期的事情...
所以我在制作 class 时遇到了问题。在这个 class 我应该有一些数据的数组。我对分配和创建新数据没有问题,例如 x2.NewAccount("123456" , 1000);这工作正常问题是当我试图用寻址到某个变量的字符串创建数据时。我知道一些关于深度复制的知识,但我不知道如何编程 = operator 在我的情况下 + 我认为 strcpy 但那也不起作用。
PS:这是一个学校程序,所以请不要因为我没有使用 headers 和使用一堆我没有在代码中使用的包含而评判我。它是由我的学校制作的,我不允许更改它们 + 添加它们(我知道使用来自 c++ 的字符串会容易得多。)。 谢谢你的帮助。
#ifndef __PROGTEST__
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <cctype>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
#endif /* __PROGTEST__ */
struct data_history{
int money = 0;
bool Income;
const char * UnStr;
const char * to_from;
};
struct client{
const char * accID;
int Balance;
int def_bal;
data_history * history;
int in_index = 0;
int in_cap = 10;
friend ostream &operator << (ostream &output , client p){
output << p.accID << ":" << endl << " " << p.def_bal << endl;
for (int i = 0 ; i < p.in_index ; i++){
if (p.history[i].Income == false)
output << " - " << abs(p.history[i].money) << ", to: " << p.history[i].to_from << ", sign: " << p.history[i].UnStr << endl;
else
output << " + " <<abs(p.history[i].money) << ", from: " << p.history[i].to_from << ", sign: " << p.history[i].UnStr << endl;
}
output << " = " << p.Balance << endl;
return output;
}
};
class CBank
{
public:
int cap = 10;
int index = 0;
client * database;
~CBank(){
for (int i = 0 ; i < index ; i++)
delete[] database[i].history;
delete[]database;
}
CBank(){
database = new client[cap];
}
bool NewAccount ( const char * accID, int initialBalance ){
for(int i = 0 ; i < index ; i ++)
if (accID == database[i].accID) {
return false;
}
//strcpy (database[index].accID , accID ); // Im getting errors while compileing (cuz I was using const char * for database.accID when i chenged it i got program crash.
database[index].accID = accID;
database[index].Balance = initialBalance;
database[index].def_bal = initialBalance;
database[index].in_cap = 10;
database[index].history = new data_history[database[index].in_cap];
index ++;
return true;
}
client Account (const char * accID ){
const char * input =accID;
for (int i = 0 ; i < index ; i++){
if (database[i].accID == input )
return database[i];
}
throw "error";
}
void print (){
for (int i = 0 ; i < index ; i ++) {
cout << endl;
cout << i << " = "<< " ID = " << database[i].accID << " | Balance = " << database[i].Balance << endl;
cout << "===Account history ===\n\n";
for (int y = 0 ; y < database[i].in_index; y++) {
cout << "Was it for him? : " << boolalpha << database[i].history[y].Income
<< "\nHow much : " << database[i].history[y].money << "\nUnique string : "
<< database[i].history[y].UnStr << "\nfrom/to: " << database[i].history[y].to_from << endl << endl;
}
}
}
private:
};
#ifndef __PROGTEST__
int main ( void )
{
char accCpy[100], debCpy[100], credCpy[100], signCpy[100];
CBank x2;
strncpy ( accCpy, "123456", sizeof ( accCpy ) );
assert ( x2 . NewAccount ( accCpy, 1000 ) );
x2 . print();
cout << "\n\n\n\n";
strncpy ( accCpy, "987654", sizeof ( accCpy ) );
assert ( x2 . NewAccount ( "987654", -500 ) );
x2 . print();
}
#endif /* __PROGTEST__ */
当使用 database[index].accID = accID;
时,你只是在做一个浅拷贝(并且依赖于调用者来保持这个内存有效,因为指针可能被访问)。
您已经正确地确定您需要执行深拷贝,但是 client::accID
只是一个指针,但是在您将其初始化为指向某个内存之前,您不能将其复制到其中。
实现此目的的一种方法是动态分配和管理 client::accID
,类似于动态分配和管理 client::history
。
而不是 strcpy (database[index].accID , accID );
或 database[index].accID = accID;
,试试:
size_t bufsize = strlen(accID) + 1;
char *buf = new char[bufsize];
memcpy(buf, accID, bufsize);
database[index].accID = buf;
并在析构函数中添加:
delete[] database[i].accID
正如其他人所指出的那样,这种 C++ 编程风格非常容易出错,并且不受社区的欢迎。使用标准库 类 可以轻松避免这种手动内存管理。即使进行了上述更改,如果您开始复制 CBank
对象,您的程序仍将 运行 进入未定义行为。
即使您的作业不需要这样做,您也应该考虑尝试将其重写为练习:
std::string
而不是accID;
的 C 字符串
std::vector
而不是data_history
数组
另供参考:
if (database[i].accID == input )
不会用 C 字符串做预期的事情...