我一直在尝试编写一个简短的程序,允许用户将条目添加到“数据库”中,列出他们已放入的条目,并能够清除所有条目而无需结束程序。这就是我所拥有的

#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;

struct BIRTH
    {int month; int year;};
struct ID
    {string name; bool vip; float score;
        struct BIRTH date;} ;

int main(int argc, char** argv) {

    ID **ptrarr;
    ptrarr = new ID * [10];
    for (int r=0; r<10; r++)
        {ptrarr[r] = new ID[1] ;}


    int counter = 0;

    while(counter<100){
    cout << "Type add to create a new entry" << endl;
    cout << "Type list to see all entries" << endl;
    cout << "Type clear to delete all entries" << endl;
    cout << "Type exit to terminate" << endl;

    string command = "0";

    getline (cin,command);

    if(command=="add")
        {
        cout << "Enter name" << endl;
        getline (cin,ptrarr[counter][1].name);
        cout << "VIP? 1 for yes, 0 for no" << endl;
        cin >> ptrarr[counter][1].vip;
        cout << "Enter score" << endl;
        cin >> ptrarr[counter][1].score;
        cout << "Month of birth" << endl;
        cin >> ptrarr[counter][1].date.month;
        cout << "Year of birth" << endl;
        cin >> ptrarr[counter][1].date.year;
        counter++;

        }
    else if(command=="list")
        {
            for (int i=0; i<counter; i++)
            {int n=i+1;
            cout << n << " "
                 << ptrarr[i][1].name << "  ";
                    if (ptrarr[i][1].vip)
                    {cout << "VIP   ";}
            cout << "Score: " << ptrarr[i][1].score << "      "
                 << "Born: " << ptrarr[i][1].date.month << "/" << ptrarr[i][1].date.year << endl;
                    }
    }
    else if(command=="clear")
    {delete[] ptrarr;

        cout << "Entries cleared" << endl;}
    else if(command=="exit")
        {return 0;}
    else
        cout << "try again" << endl;
    }
return 0;
}


现在要解决的是:以下代码成功编译,但是当我键入“ add”命令时,程序崩溃(成就已解锁,认为用这样短的代码无法获得)。最重要的是,该数组由多类型结构组成,并且“ clear”命令清除了数组中的所有条目。

注意:我知道有上千种更好的方法来编写这段代码,但是我正在编写它来练习到目前为止我所介绍的有关C ++的内容。因此,除非绝对有必要运行代码,否则请不要引入任何新的头=)

最佳答案

您正在创建一个指针数组,每个指针都指向一个元素:

  ptrarr[r] = new ID[1] ;


可以与ptrarr[r]一起使用的最大索引为0。由于您正在使用ptrarr[counter][1],因此您正在访问超出范围的内存。这导致未定义的行为。崩溃就是这样一种未定义的行为。

您的代码中还有其他问题可能需要修复。

更多超出范围的内存访问

您正在使用:

int counter = 0;
while(counter<100){

...

getline (cin,ptrarr[counter][1].name);


如果counter > 10,这将再次导致未定义的行为,因为您仅为10分配了ptrarr指针。

删除内容

您正在使用:

  else if(command=="clear")
  {
     delete[] ptrarr;

     cout << "Entries cleared" << endl;
  }


这有几个问题:


您有内存泄漏。您永远不会在delete []指向的地方调用ptrarr[0] - ptrarr[9]。您必须使用:

else if(command=="clear")
{
   for ( int i = 0; i < 10; ++i )
   {
      delete [] ptrarr[i];
   }

   delete[] ptrarr;

   cout << "Entries cleared" << endl;
}


请记住,每个分配必须有一个对应的解除分配。否则,您正在泄漏内存。
调用delete [] ptrarr;后,它指向悬空的内存。在继续使用ptrarr时,看不到任何为counter重新分配内存的代码。


用户选择“清除”时,您需要重新分配内存并将0重置为ptrarr[counter][1]

我的建议

您没有两个级别的指针。您只需要以下内容:

int const MAX_ITEMS = 100;
ID* IDarr  = new ID[MAX_ITEMS];


代替IDarr[counter],使用MAX_ITEMS

while语句的表达式中使用100代替魔术数字counter

int counter = 0;
while(counter<MAX_ITEMS){


在处理“清除”时,您不需要取消分配或分配内存。只需重置main

  else if(command=="clear")
  {
     counter = 0;
     cout << "Entries cleared" << endl;
  }


main返回之前,请确保先释放内存。

这是带有更改的完整函数:

int main(int argc, char** argv) {

   const int MAX_ITEMS = 100;
   ID* IDarr = new ID[MAX_ITEMS];

   int counter = 0;
   while(counter < MAX_ITEMS){
      cout << "Type add to create a new entry" << endl;
      cout << "Type list to see all entries" << endl;
      cout << "Type clear to delete all entries" << endl;
      cout << "Type exit to terminate" << endl;

      string command = "0";

      getline (cin,command);

      if(command=="add")
      {
         cout << "Enter name" << endl;
         getline (cin, IDarr[counter].name);
         cout << "VIP? 1 for yes, 0 for no" << endl;
         cin >>  IDarr[counter].vip;
         cout << "Enter score" << endl;
         cin >>  IDarr[counter].score;
         cout << "Month of birth" << endl;
         cin >>  IDarr[counter].date.month;
         cout << "Year of birth" << endl;
         cin >>  IDarr[counter].date.year;
         counter++;

      }
      else if(command=="list")
      {
         for (int i=0; i<counter; i++)
         {
            int n=i+1;
            cout << n << " " << IDarr[i].name << "  ";
            if (IDarr[i].vip)
            {
               cout << "VIP   ";
            }
            cout
               << "Score: " << IDarr[i].score << "      "
               << "Born: " << IDarr[i].date.month << "/" << IDarr[i].date.year << endl;
         }
      }
      else if(command=="clear")
      {
         counter = 0;

         cout << "Entries cleared" << endl;
      }
      else if(command=="exit")
      {
         // Don't use return 0;
         // Just break out of the while loop so that memory
         // can be deallocated at the end of this function.
         break;
      }
      else
         cout << "try again" << endl;
   }

   delete [] IDarr;

   return 0;
}

关于c++ - 创建和清除一系列结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27996972/

10-09 23:21