3

我正在编写一个准数据库。

我有一个班级对:

class Pair{
    MyString m_key;
    Data* m_data;
}

然后 AddItem 方法组成该对并将其添加到数据库中。

Data Ivanov(1, 10, "Manager", 100000);
Data Petrov(2, 20, "Manager", 200000);
MyString* employee0 = new MyString("Ivanov");
MyString* employee1 = new MyString("Petrov");
bd.AddItem(employee0, &Ivanov);
bd.AddItem(employee1, &Petrov);

数据库本身监控元素的数量和容量。类 Bd { 私人: int m_size; int m_容量;对** ar; ... }

如果我们添加一个项目,如果容量溢出,数据库就会伸展。如果我们删除一个项目,则会出现一个空单元格,将来可能会使用它。这样做是为了不使堆碎片过多。

void Bd:: AddItem(MyString* key, Data* data){
    if (m_size < m_capacity){
        *ar[m_size+1] = Pair(key, data);
    }
    else{ 
        if (m_size == 0){
            ar = new Pair*[++m_size];
            m_capacity++;           
            ar[0] = new Pair(key, data);
            stop
        }
        else{
            Pair** tmp = new Pair*[++m_size];  
            m_capacity++;
            memcpy(tmp, ar, m_size * sizeof(Pair*));
            delete[] ar;
            ar = tmp;
            ar[m_size-1] = new Pair(key, data);
            stop
        }
    }
}


void Bd::RemoveItem(const char* a_key){
    Pair** tmp_ar = this->get_ar();
    for (int i = 0; i < m_size; i++){       
        Pair* tmp_key = tmp_ar[i];
        MyString* tmp_my_string= (*tmp_key).get_m_key();
        const char* tmp_str = (*tmp_my_string).GetString();
        if ( strcmp(tmp_str, a_key) == 0){
            delete ar[i];           
            for (int j = i; j < m_size-1; j++){
                *ar[j] = *ar[j+1];
            }
            delete ar[m_size-1];
            m_size--;
            break;
        }
        stop
        if (i == (m_size-1)){
            cout << "No such person." <<endl;           
        }
    }   
    stop
}

好吧,现在我想使用 bd。

cout << bd;
bd.Print("Ivanov");
bd.Print("Petrov");

它完美地工作。它打印整个数据库或任何元素。

然后我删除了伊万诺夫先生。bd.RemoveItem("伊万诺夫");

现在我有这两个问题:

bd.Print("Petrov");
cout << bd;

我在数据类中有一个打印方法。

void Data:: print_info(){   
    cout << "Sex: " << this->getSex() << ", age: " << age <<", position: " << position <<", salary: ";
    cout << salary << endl; 
}

我特地做了第二个cout,因为这是我遇到麻烦的地方。薪水虽然在范围内清晰可见,但却导致了整个问题。请看这张图:

在此处输入图像描述

如果我再迈出一步,我会收到有关堆损坏的错误。输出窗口显示: HEAP: Free Heap block 296b30 modified at 296b58 after it is freed

你能帮我理解为什么我不能打印这个薪水吗?

4

1 回答 1

0

我看到以下问题AddItem()

void Bd:: AddItem(MyString* key, Data* data){
    if (m_size < m_capacity){
        *ar[m_size+1] = Pair(key, data);
    }

如果m_size小于m_capacity,则添加新项目但不增加m_size

    else{ 
        if (m_size == 0){
            ar = new Pair*[++m_size];
            m_capacity++;           
            ar[0] = new Pair(key, data);
            stop
        }

我假设您打算检查是否m_capacity为 0。

        else{
            Pair** tmp = new Pair*[++m_size];  
            m_capacity++;
            memcpy(tmp, ar, m_size * sizeof(Pair*));
            delete[] ar;
            ar = tmp;
            ar[m_size-1] = new Pair(key, data);
            stop
        }

memcpy正在从 复制arm_size在您增加之前的大小为m_size,但现在的大小为m_size-1,因此您已复制到数组的末尾。

以及以下问题RemoveItem()

if ( strcmp(tmp_str, a_key) == 0){
    delete ar[i];           
    for (int j = i; j < m_size-1; j++){
        *ar[j] = *ar[j+1];
    }
    delete ar[m_size-1];
    m_size--;
    break;
}

delete ar[m_size-1]正在删除您刚刚移动到的项目ar[m_size-2]。你不想删除它。

我认为此删除可能是您问题的一部分。具体来说,我认为以下两项更改将有所帮助:

  1. *ar[j] = *ar[j+1]将行更改ar[j] = ar[j+1]为评论中提到的。
  2. 摆脱delete ar[m_size-1];线。与ar换行一样,您绝对不希望这样做。

这不会解决所有问题,但它会确保您Petrov在尝试调用他的print_info()方法之前没有删除。

于 2013-04-16T19:17:10.423 回答