C ++将指针数组中的元素添加到结构问题中

时间:2015-06-23 16:27:48

标签: c++ arrays pointers struct

所以我有一个名为Person的结构:

def select_paragraph(text, word, delimiter='\n'):
    return [p for p in text.split(delimiter) if word in p]

我已经做了所以我的main()读取了一个名为gift1.in的文件,其中包含:

struct Person {
    char *name;
    int initialMoney;
    int currentMoney;
};

还有一点点。重要的是这些线。 第一行代表有多少人,其余的是人们的名字 您可能已经猜到,这些名称将成为Person的结构中的5 dave laura owen vick amr

现在出现问题:

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]; } 中的每个元素都有一个指向结构人的指针。但是,由于我在另一个范围内创建了Struct,我必须分配它(因此使用malloc())。

所以我的理解是我应该得到:

peopleArray[]

但是,从运行实际的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: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

这使我看起来像使用malloc()而不是分配新内存完全重复。

所以我的问题是: 为什么会这样?内存中发生了什么导致这个

我该怎么做才能解决这个问题?我肯定知道另一种方法是只创建一个结构数组,但我很想知道一个解决方案可以继续使用指向结构的指针数组。

免责声明:很抱歉,如果我的C ++看起来不像C ++!我一直在使用更多的C而且我正在慢慢进行转换,所以我的C ++看起来很像C,(使用char * name而不是string)。

添加个人硬件信息(如果这是问题):我在Mac OS X Mavericks上使用来自macports的clang ++(最新版本)

3 个答案:

答案 0 :(得分:0)

你一遍又一遍地为Person.name分配相同的指针,这就是为什么他们只是“接受”你在原始地址上做的改变。

要改变此行为,您必须为每个条目创建一个新实例(例如,使用strcpy) 之后你会得到预期的行为。

此外,您还可以通过使用std :: string和std :: vector来实现这一目的: http://pastebin.com/Ftt5FKeX

答案 1 :(得分:0)

正如@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垃圾。

答案 2 :(得分:0)

// Create a person for every name...
for (index = 0; maxIndex != index; index++) {
        char newName[MAXNAMECHAR+1];

在此处,您可以在堆栈上分配内存以存储名称。您还没有告诉编译器每个循环需要其中一个,所以要么每次迭代都要分配/释放堆栈空间,否则编译器会将其视为:

char newName[MAXNAMECHAR+1];
for (index ... ) {
    ...

您读取的每个名称都会进入此变量,这很可能位于内存/堆栈中的相同位置。您将此内存的地址传递给您的create函数:

       makePerson(peopleArray, index, newName);

然后将该地址存储在Person对象中。所以他们都指向同一个地址 - 堆栈上的临时位置。

您应该考虑在Personstd::string进行输入,或者使name复制正在传递的字符串。

struct Person {
    std::string name;
    int initialMoney;
    int currentMoney;

    Person(const char* name_) : initialMoney(0), currentMoney(0) {}
};

makePerson变为

void makePerson(Person *peopleArray[], int insertIndex, char *name) 
{
    peopleArray[insertIndex] = new Person(name);
}

但请记住,当你完成这些对象时,你需要delete这些对象(就像你之前应该free一样),考虑std::unique_ptr {{ 3}}

这是一个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://en.cppreference.com/w/cpp/memory/unique_ptr