0

簡単に言えば、このプログラムは、文字列から文字のリンクされたリストを作成することです。("HELLO" から head->h->e->l->l->o->NULL と言う) 消去機能を使用してヘッドを削除しようとすると、プログラムが動作を停止し、"application.exe" が表示されます。動作を停止しました... Windows が解決策を確認しています..". メモリの割り当てに問題があると思いますが、実際にはわかりません。提案は大歓迎です。

これは機能します

void StringADT::append(string s)
{ 
for (int i = 0; i < s.length(); i++)
{
    Node* NodePtr;
    Node* newNode;
    newNode = new Node;
    newNode->data = s.at(i);
    newNode->next = NULL;
    if (!head)
    {
        head = newNode;
    } else
    {
        NodePtr = head;
        while (NodePtr->next)
        {
            NodePtr = NodePtr->next;
        }
        NodePtr->next = newNode;
    }
}
}

void StringADT::erase(int pos) //pos = position to erase

{
if (!head || pos < 0 || pos > length() - 1)
    return;
else {
    Node* NodePtr;  
    NodePtr = head;
    if (pos == 0)
    {   
        NodePtr = head->next;

        delete head; //PROBLEM COMES AFTER EXECUTION OF THIS LINE!!

    }
}

}

ここに私のクラスがあります

class StringADT{

private:
    struct Node {
        char data;
        Node* next;
    };
    Node* head;

ここに、メモリ割り当てのために問題の原因となる可能性のある追加機能があります。

void StringADT::append(string s) (appending string s to the linked list)
{ 
Node* NodePtr;

int slength = s.length();

Node *NodeArray;
NodeArray = new Node[slength];
if(!NodeArray)
    return;
for (unsigned i = 0; i < s.length(); i++)
{
    NodeArray[i].data = s.at(i);
    NodeArray[i].next = NULL;
}

if (!head)
{
    head = NodeArray;
    NodePtr = head;
    for(unsigned count = 1; count < slength; count ++)
    {
        NodePtr->next = (NodeArray + count);
        NodePtr = NodePtr->next;
        //cout << "number of count " << count << endl;
    }
} else {
    NodePtr = head;
    while (NodePtr->next)
    {
        NodePtr = NodePtr->next;
    }
    for(unsigned count = 0; count < slength; count ++)
    {
        NodePtr->next = (NodeArray + count);
        NodePtr = NodePtr->next;
        //cout << "number of count " << count << endl;
    }
}

}

4

3 に答える 3

0

Node オブジェクトを次のように割り当てました。

NodeArray = new Node[slength];

あなたが持っているのは、1 つの割り当て内の Node オブジェクトの配列です。後で、その配列内の特定の要素を使い終わったら、呼び出しています

    delete head; //PROBLEM COMES AFTER EXECUTION OF THIS LINE!!

配列の特定の要素を削除します。

これは、C++ メモリ割り当てでは許可されていません。

配列を割り当てた場合、特定の要素ではなく、配列全体のみを削除できます。さらに、次のように配列の delete[] 演算子を使用する必要があります。

delete[] someArray;

しかし、これは設計の根本的な問題になります。リンク リストを実装していますが、配列を割り当てています。さて、理論上は、先に行ったようにリンクされたリスト要素の配列を割り当てることができますが、それを行う意味はありません。配列は特定の数の要素に割り当てられます。リンクされたリストは、任意の数の要素が必要で、その数がわからない場合によく使用されます。

リンクされたリストは通常​​、事前定義された配列に置かれるのではなく、一度に 1 つずつ要素が割り当てられ、削除されます。新しいデータを取得したら、新しいノードを割り当ててから、リストに追加します。

(そして、上記のコードのにおいは、配列があるのに、なぜ要素をリンクする必要があるのか​​ということです。ポインターをたどる代わりに、次の要素に反復することができます。配列とリンクされたリストは組み合わせて使用​​されません。リンクされたリストの場合、配列を取り除き、個々のノードを割り当てる必要があります。その後、それらを個別に削除することもできます。その配列をまったく持つべきではありません。)

于 2013-02-20T12:33:30.430 に答える
0
  1. 問題は明らかに、オブジェクトの配列を割り当てて、そのうちの 1 つを削除したいことです。Nodes を個別に割り当てる必要があります。つまり、append修正する必要がある機能です。

  2. append は として記述しappend(char)、1 つの文字を追加するだけで、append(string const &)(文字列はコピーするのにコストがかかる可能性があるため、常に参照によって、通常は一定です!) ループ内でそれを呼び出す必要があります。またappend(char const *)、文字列リテラルも追加できます。

  3. ランダム アクセスがないものにはインデックスを使用しないでください。そして、直接アクセスできるものを考える必要がないように、インデックスを使用した反復よりも反復子/ポインターによる反復を優先することを学ぶだけです!

繰り返し説明を求めなければならない場合でも、割り当てについては自分で実際のコードを思いついた方がよいため、例は挙げません。

于 2013-02-20T12:37:26.080 に答える
0

消去関数は次のようになります。

if (pos == 0)
{   
    NodePtr = head;
    head = head->next;

    delete NodePtr;
}
于 2013-02-20T11:56:40.913 に答える