C++向结构问题的指针数组添加元素
C++ Adding elements to an Array of Pointers to a Struct Issue
所以我有一个名为Person:的结构
struct Person {
char *name;
int initialMoney;
int currentMoney;
};
我已经做到了,所以我的main()读取了一个名为gift1.in的文件,其中包含:
5
dave
laura
owen
vick
amr
还有一点点。重要的是这些线条。第一行代表有多少人,然后是其他人的名字
正如您可能已经猜到的,这些名称将成为Person结构中的char *name
。
现在解决问题:
int main ()
{
struct Person *peopleArray[MAXFRIENDSNUM];
int index = 0;
int maxIndex = 0;
std::ofstream fout ("gift1.out");
std::ifstream fin ("gift1.in");
// Obtain max number of names!
fin >> maxIndex;
// Create a person for every name...
for (index = 0; maxIndex != index; index++) {
char newName[MAXNAMECHAR+1];
fin >> newName;
std::cout << "Inserting " << index << ": " <<newName << std::endl;
makePerson(peopleArray, index, newName);
}
std::cout << "Checking if the proper person's name is there: n";
// Check to see if the person's name is being read correctly
for (index = 0; maxIndex != index; index++) {
std::cout << "Reading " << index << ":" << peopleArray[index]->name << std::endl;
}
std::cout << "Changing a single element of an array: n";
peopleArray[1]->name = (char *)"John";
for (index = 0; maxIndex != index; index++) {
std::cout << "Reading " << index << ":" << peopleArray[index]->name << std::endl;
}
return 0;
}
void makePerson(Person *peopleArray[], int insertIndex, char *name)
{
peopleArray[insertIndex] = (Person *)malloc(sizeof(peopleArray[insertIndex]));
peopleArray[insertIndex]->name = name;
peopleArray[insertIndex]->initialMoney = 0;
peopleArray[insertIndex]->currentMoney = 0;
peopleArray[insertIndex] = peopleArray[insertIndex];
}
根据我的理解,peopleArray[]
中的每个元素都有一个指向Struct Person的指针。然而,由于我在另一个作用域中创建了Struct,所以我必须分配它(因此使用了malloc())。
所以我的理解是我应该得到:
Inserting 0: dave
Inserting 1: laura
Inserting 2: owen
Inserting 3: vick
Inserting 4: amr
Checking if the proper person's name is there:
Reading 0:dave
Reading 1:laura
Reading 2:owen
Reading 3:vick
Reading 4:amr
Changing a single element of an array:
Reading 0:dave
Reading 1:John
Reading 2:owen
Reading 3:vick
Reading 4:amr
然而,从运行实际的C++脚本中,我得到了:
Inserting 0: dave
Inserting 1: laura
Inserting 2: owen
Inserting 3: vick
Inserting 4: amr
Checking if the proper person's name is there:
Reading 0:amr
Reading 1:amr
Reading 2:amr
Reading 3:amr
Reading 4:amr
Changing a single element of an array:
Reading 0:amr
Reading 1:John
Reading 2:amr
Reading 3:amr
Reading 4:amr
这让我看起来像是从使用malloc()而不是分配新内存中获得了完全的重复。
所以我的问题是:为什么会发生这种情况?内存内部发生了什么导致
我能做些什么来解决这个问题?我当然知道一个替代方案是只制作一个structs数组,但我很想看看有什么解决方案可以继续使用指向structs的指针数组。
免责声明:很抱歉,如果我的C++看起来不像C++!我一直在使用更多的C,而且我正在慢慢地进行转换,所以我的C++看起来很像C(使用char*名称而不是字符串)。
其他硬件信息(如果是问题的话):我在Mac OS X Mavericks(最新版本)上使用来自macports的clang++
// Create a person for every name...
for (index = 0; maxIndex != index; index++) {
char newName[MAXNAMECHAR+1];
在这里,您可以在堆栈上分配内存来存储名称。你还没有告诉编译器每个循环需要一个这样的循环,所以要么你会在每次迭代中分配/释放堆栈空间,要么你的编译器会这样处理:
char newName[MAXNAMECHAR+1];
for (index ... ) {
...
您读取的每个名称都会进入该变量,该变量很可能位于内存/堆栈中的同一位置。您将此内存的地址传递给您的创建函数:
makePerson(peopleArray, index, newName);
然后将该地址存储在您的Person对象中。所以它们都指向同一个地址——堆栈上的一个临时位置。
您应该考虑使Person
中的条目成为std::string
,或者使name
复制它正在传递的字符串。
struct Person {
std::string name;
int initialMoney;
int currentMoney;
Person(const char* name_) : initialMoney(0), currentMoney(0) {}
};
CCD_ 6变为
void makePerson(Person *peopleArray[], int insertIndex, char *name)
{
peopleArray[insertIndex] = new Person(name);
}
不过,请记住,当您处理完这些对象时,您将需要delete
这些对象(就像您以前应该free
处理它们一样),请考虑std::unique_ptr
http://en.cppreference.com/w/cpp/memory/unique_ptr
这里有一个C++实现:
#include <string>
#include <vector>
#include <iostream>
using std::cout;
using std::cin;
using std::vector;
using std::string;
struct Person {
string m_name;
int m_initialMoney;
int m_currentMoney;
Person(const std::string& name_, int money_=0)
: m_name(name_)
, m_initialMoney(0), m_currentMoney(0)
{}
};
int main ()
{
vector<Person> people;
// Obtain max number of names!
size_t maxIndex = 0;
cin >> maxIndex;
if (maxIndex <= 0) {
cout << "Nothing to do.n";
return 1;
}
// Create a person for every name...
for (size_t index = 0; maxIndex != index; index++) {
std::string newName;
cin >> newName;
cout << "Inserting " << people.size() << ": " << newName << std::endl;
people.emplace_back(newName);
}
// Check to see if the person's name is being read correctly
cout << "Checking if the proper person's name is there: n";
for (auto& person : people) {
cout << "Reading " << person.m_name << std::endl;
}
cout << "Changing a single element of an array: n";
people[1].m_name = "John";
for (auto& person : people) {
cout << "Reading " << person.m_name << std::endl;
}
return 0;
}
参见http://ideone.com/jjfPda
正如@Ben所说,咬紧牙关,只使用C++约定。您对newName的描述存在问题。您在堆栈上声明它,在for循环的本地范围内,并且它很可能每次都有相同的地址。因此,您读取的文件中的最后一个条目"amr"将被分配给该地址。然后在makePerson中复制该指针,并将其分配给该结构中的char*name元素。
for (index = 0; maxIndex != index; index++) {
char newName[MAXNAMECHAR+1];
makePerson(peopleArray, index, newName);
}
你可以(糟糕地)通过为名称分配内存来解决这个问题:
char * newName = new char[MAXNAMECHAR+1];
但之后你也必须清理自己并删除记忆。开始使用"真正的"C++,并避免所有这些malloc垃圾。
您一次又一次地为Person.name分配相同的指针,这就是为什么它们都只是"接受"您对原始地址所做的更改。
要改变这种行为,您必须为每个条目创建一个新实例(例如使用strcpy)在那之后,你会得到预期的行为。
此外,您还可以使用std::string和std::vector来实现这一点http://pastebin.com/Ftt5FKeX
- C++向数组添加元素并调整数组大小
- 向对象数组 c++ 添加值
- 在 c++ 中将 Char 数组添加到 Char * 变量
- 向动态数组添加内容
- 动态数组添加元素而不创建结构变量/对象
- 将 2D 数组添加到 1D 数组
- 如何使用sprintf将UINT_64的数组添加到一个字符数组中
- 当循环崩溃时,不向数组添加单词
- 如何将对象数组添加到另一个类
- 将字符数组添加到 const string&in C++
- 如何将数组添加到列表中
- 向量数组C++ - 添加元素时的奇怪行为
- 将char数组添加到C 中的字符串
- strncpy向我的char数组添加了额外的字符
- 在C++中向数组添加项的最有效方法
- 将类对象的数组添加到一个主类对象中
- 将BSON数组添加到MongoDB 3.2文档并提取值(MongoCXX 3.2)(C++11)
- 我是否正确地为 2D 数组添加了行与列
- 读取文件内容,存储在数组中,向数组添加更多内容,然后将新数组存储在文件C++中
- C++类对象数组 - 添加新记录