2017-10-21 8 views
-1

メンバ関数を含む通常の関数を使用すると、私のプログラムで不正なallocエラーが発生し続けます。std :: bad_allocのインスタンスをスローした後にTerminateを呼び出します。 2つのクラスを使用して、もう一方へのポインタを使用する

プログラムは、コマンドラインからいくつかの特定の入力を受け取り、ポインタの配列の要素を出力することについてです。これはポインタの配列で行わなければなりません。

まず、2つの文字列が必要なクラスを作成しました。名前のためのものと部屋のためのもの。次に、配列を作成するために、最初のクラスへのポインタとサイズを持つ別のクラスを作成しました。

私のメインは最後にあり、上記メインは2つの通常の機能です。このコードで何が問題になっていますか?ループの最初のコマンドを入力すると、通常の関数に接続するコマンドを入力するまで機能します。おそらく何かそこに間違いがありますが、私はそれを見つけることができません。あなたの問題につながる

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

class Address 
{ 
    private: 
     string name; 
     string room; 
    public: 
     Address(){}; 
     Address(string, string); 
     string get_name(); 
     string get_room(); 
     void change_room(string); 
}; 

Address::Address (string n, string r) 
{ 
    name = n; 
    room = r; 
} 


string Address::get_name() 
{ 
    return name; 
} 

string Address::get_room() 
{ 
    return room; 
} 

void Address::change_room(string change) 
{ 
    room = change; 
} 


//end of Address class 


class Address_Book 
{ 
    private: 
     int size; 
     Address* addresses; 
    public: 
     Address_Book(); 
     ~Address_Book(){ delete[] addresses;} 
     void add(Address); 
     void move(string, string); 
     int get_size(); 
     Address location(int); 
     int find(string); 
     void clear(); 
     void remove_address(string); 
     int exists(string); 
     void sort(); 
}; 


Address_Book::Address_Book() 
{ 
    int s = 0; 
    size = s; 
    addresses = new Address[s]; 
} 

void Address_Book::add(Address add) 
{ 
    Address* temp = new Address [size + 1]; 
    for (int i = 0; i < size; i++) 
    { 
     temp[i] = addresses[i]; 
    } 
    temp[size] = add; 
    delete[] addresses; 
    addresses = temp; 
    size ++; 

} 

void Address_Book::move(string name, string newroom) 
{ 
    for (int i = 0; i < size ; i++) 
    { 
     if (addresses[i].get_name() == name) 
     { 
      addresses[i].change_room(newroom); 
     } 
    } 
} 

void Address_Book::remove_address(string name) 
{ 
    Address* temp = new Address [size - 1]; 

    for (int i = 0; i < size; i++) 
    { 
     if (addresses[i].get_name() != name) 
     { 
      temp[i] = addresses[i]; 
     } 
     else if (addresses[i].get_name() == name) 
     { 
      for (int j = i + 1; j < size; j++) 
      { 
       temp[i] = addresses[j]; 
       i++; 
      } 
      break; 
     } 
    } 
    delete[] addresses; 
    addresses = temp; 
    size--; 
} 


int Address_Book::get_size() 
{ 
    return size; 
} 


Address Address_Book::location(int index) 
{ 
    return addresses[index]; 
} 


void Address_Book::sort() 
{ 
    Address temp; 
    for (int i = 0; i < size; i++) 
    { 
     for(int j = 0; j < size - 1; j++) 
     { 
      if (addresses[j].get_room() > addresses[j + 1].get_room()) 
      { 
       temp = addresses[j]; 
       addresses[j] = addresses[j + 1]; 
       addresses[j + 1] = temp; 
      } 
     } 
    } 
    for (int i = 0; i < size; i++) 
    { 
     if (addresses[i].get_room() == addresses[i + 1].get_room()) 
     { 
      if (addresses[i].get_name() > addresses[i + 1].get_name()) 
      { 
       temp = addresses[i]; 
       addresses[i] = addresses[i + 1]; 
       addresses[i + 1] = temp; 
      } 
     } 
    } 
} 

void Address_Book::clear() 
{ 
    Address * temp = new Address[0]; 
    delete[] addresses; 
    addresses = temp; 
    size = 0; 
} 


int Address_Book::find(string name) 
{ 
    for (int i = 0; i < size; i++) 
    { 
     if (addresses[i].get_name() == name) 
     { 
      return i; 
     } 
    } 
    return -1; 
} 



//end of Address_Book class 



void find(string name, Address_Book addbook) 
{ 
    int index = addbook.find(name); 
    cout << index << endl; 

    if (index > -1) 
    { 
     cout << addbook.location(index).get_name() << " is in room " << 
     addbook.location(index).get_room() << endl; 
    } 
    else 
    { 
     throw runtime_error("entry does not exist."); 
    } 
} 


void remove_add(string name, Address_Book book) 
{ 
    int exist = book.find(name); 

    if (exist > -1) 
    { 
     book.remove_address(name); 
    } 
    else 
    { 
     throw runtime_error("entry does not existt."); 
    } 

} 






int main() 
{ 
    Address_Book addbook; 
    string action, in_name, in_room; 
    do 
    { 
     try 
     { 
      cout << "> "; 
      cin >> action; 

      if (action == "add") 
      { 
       cin >> in_name >> in_room; 
       Address newadd(in_name, in_room); 
       addbook.add(newadd); 
      } 
      else if (action == "move") 
      { 
       cin >> in_name >> in_room; 
       addbook.move(in_name, in_room); 
      } 
      else if (action == "remove") 
      { 
       cin >> in_name; 
       remove_add(in_name, addbook); 
      } 
      else if (action == "find") 
      { 
       cin >> in_name; 
       find(in_name, addbook); 
      } 
      else if (action == "list") 
      { 
       addbook.sort(); 

       for (int i = 0; i < addbook.get_size(); i++) 
       { 
       cout << addbook.location(i).get_name() << " is in room 
       " << addbook.location(i).get_room() << endl; 
       } 
      } 
      else if (action == "clear") 
      { 
       addbook.clear(); 
      } 
      else 
      { 
       throw runtime_error("input mismatch."); 
      } 
     } 
     catch (runtime_error& e) 
     { 
      cerr << "error: " << e.what() << endl; 
     } 
    }while (action != "exit"); 

    return 0; 
} 
+0

あなたが使用しているオペレーティングシステムなど、コンパイラ、知っていると便利だろう。 問題の原因となっている入力の例が参考になります。 また、画面に表示される内容をお知らせください。 – CplusPuzzle

+0

私はこのためにベクトルを再発明する必要があります。その使用する必要があります。私は記憶の仕組みを理解する必要があります。 –

+0

オペレーティングシステムはmacです。私が「追加」と名前と部屋を続けて入力すると、彼らは私が作成したアドレス配列にまっすぐに行きます。私が 'list'と入力すると配列全体が出力されます。しかし、私が削除したい場合、またはそれを見つけるのは初めてです。それは私に悪いalloc()を取得します。どうしたの? –

答えて

0

機能remove_addは、参照またはポインタによってアドレス帳オブジェクトを取得する必要があります。 今のところ、アドレス帳のコピーから削除されます。

それは次のようになります。

void remove_add(string name, Address_Book& book) 
{ 
    int exist = book.find(name); 

    if (exist > -1) 
    { 
     book.remove_address(name); 
    } 
    else 
    { 
     throw runtime_error("entry does not existt."); 
    } 

} 

また、あなたはおそらく次の関数の場合とsize == 1で別の何かを行う必要があります。例えばコンパイラがサポートする場合は、addressesNULLを0またはnullptrに設定します。

void Address_Book::remove_address(string name) 
{ 
    Address* temp = new Address[size - 1]; 

    for (int i = 0; i < size; i++) 
    { 
     if (addresses[i].get_name() != name) 
     { 
      temp[i] = addresses[i]; 
     } 
     else if (addresses[i].get_name() == name) 
     { 
      for (int j = i + 1; j < size; j++) 
      { 
       temp[i] = addresses[j]; 
       i++; 
      } 
      break; 
     } 
    } 
    delete[] addresses; 
    addresses = temp; 
    size--; 
} 

言語と幸運を学ぶ楽しみを持って:)

+0

ああ男。今、私はそれを得る...私はそんなにおかげでありがとう...あなたはなぜこれが起こっているかをさらに教えてもらえますか? –

+0

値渡しと参照渡しについての読解を試してみると、私が提供するよりも優れた説明がたくさんあります。 – CplusPuzzle

0

正確なコマンドは、あなたの質問に指定され、そのコードは、セグメンテーションフォールトでクラッシュしたまで、私は少しの周りつついていません。

Valgrindおよびは、このような問題の根本原因を突き止めるための素晴らしいツールです。あなたのケースでは:

$ g++ -g 46865300.cpp 
$ valgrind ./a.out 
> add foo bar 
> list 
==102== Invalid read of size 8 
==102== at 0x4EF4EF8: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib64/libstdc++.so.6.0.19) 
==102== by 0x401354: Address::get_room() (46865300.cpp:33) 
==102== by 0x401C05: Address_Book::sort() (46865300.cpp:152) 
==102== by 0x4026A3: main (46865300.cpp:262) 
==102== Address 0x5a17410 is 8 bytes after a block of size 24 alloc'd 
==102== at 0x4C2A8A8: operator new[](unsigned long) (vg_replace_malloc.c:423) 
==102== by 0x4014BF: Address_Book::add(Address) (46865300.cpp:74) 
==102== by 0x40245C: main (46865300.cpp:243) 

これは、次のコードは、範囲外のアクセスを行うことを言う:

150  for (int i = 0; i < size; i++) 
151  { 
152   if (addresses[i].get_room() == addresses[i + 1].get_room()) 
153   { 
154    if (addresses[i].get_name() > addresses[i + 1].get_name()) 

私はループ条件が「サイズ - 1」を使用する必要がありますねではなく「サイズ」のを。

+0

これは問題ではありません。次のように入力してみてください: 'add' John F450、次に他の人を追加してください。 '追加'フランクT430。次に、 'list'と入力します。それから、 'find' John(正しい出力を表示するはずです)をもう一度タイプするか、または 'find'をもう一度試そうとすると、不正なallocまたはdoubleの空きまたは破損が発生します。 –

関連する問題