创建和清除结构数组

时间:2015-01-17 06:45:39

标签: c++ arrays structure

我一直试图编写一个简短的程序,允许用户将条目添加到"数据库",列出他们放入的条目,以及清除所有条目而不结束的能力该程序。这就是我所拥有的

#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;
}

现在这里有交易:以下代码成功编译,但当我输入&#34;添加&#34;命令,程序崩溃(成就解锁,没有认为可以用这么短的代码获得)。最重要的是阵列是由多种结构组成的,而且#34; clear&#34;命令会清除数组中的所有条目。

注意:我知道有很多方法可以编写这段代码,但我正在编写它来实践我迄今为止关于C ++的内容。因此,除非代码运行绝对必要,否则请不要引入任何新的噱头=)

4 个答案:

答案 0 :(得分:2)

将所有ptrarr[counter][1]替换为ptrarr[counter][0]以解决问题。

进一步建议:

我。此代码有冗余:

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

将其替换为:

ID *ptrarr;
ptrarr = new ID [10];

然后在每个ptrarr [counter]

的末尾不需要额外的[0]

II。函数使您的代码更具可读性:

if(command=="add")
    add();
else if(command=="list")
    list();
else if(command=="clear")
    clear();
else if(command=="exit")
    return 0;
else 
    cout << "try again" << endl;

然后在较小的范围内做出决定(大型项目的良好实践。)

III。您的代码中还有另一个错误:

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

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

在这里你应该重置计数器。另外,如果你看待我的观点(),这部分就可以了。否则,如果您将newfor循环一起使用,我恐怕您需要delete并使用for循环。仅仅删除数组树的根会导致内存泄漏!

此外,如果您通过删除清除列表,您是否还需要将数据存储在列表中?在链接列表中使用删除是一个好主意,但它不适用于此处。只需重置计数器即可完成工作,并且不再显示列表中的ID。列表中的for仅计入计数器。

如果你退出程序,你不释放内存吗?

我说

delete [] ptrarr;

很适合退出。

答案 1 :(得分:0)

数组索引从0开始。

ptrarr[counter][1]指的是ptrarr[counter]的第二个元素。 ptrarr[counter]指向一个元素的数组。

答案 2 :(得分:0)

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

  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;
  }

这有几个问题:

  1. 你有内存泄漏。您永远不会在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;
    }
    

    请记住,每个分配都必须具有相应的释放。否则,你正在泄漏记忆。

  2. 致电delete [] ptrarr;后,它指向悬空记忆。在您继续使用时,我没有看到任何为ptrarr重新分配内存的代码。

  3. 当用户选择“清除”时,您需要重新分配内存并将counter重置为0

    我的建议

    你没有两个级别的指针。你只需要:

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

    而不是ptrarr[counter][1],请使用IDarr[counter]

    MAX_ITEMS语句的表达式中使用while而不是幻数100

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

    处理“清除”时,您不需要释放或分配内存。只需重置counter

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

    确保在从main返回之前释放内存。

    以下是包含更改的完整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;
    }
    

答案 3 :(得分:0)

试试这个:

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

结论

  • 正如您使用0初始化counter一样,您应该使用0索引来访问第一个元素;
  • 上市时也一样。
  • 数组基于0索引。