1

私はかなり経験豊富な C# プログラマーであり、Stack オブジェクトを作成する C++ アプリケーションで友人を助けようとしています。私が C++ を見始めてから 13 年以上が経ちましたが、これを行う適切な方法を思い出すのにとても良い時間を費やしています。ヘッダーと CPP の違いを理解するのに少し時間がかかったので、そこにも問題があるかもしれません。これが私の問題です:

//Stack.h

#ifndef __STACK_INCLUDED__
#define __STACK_INCLUDED__
#include "Node.h"

class Stack
{
    private:
    /// Going to be the pointer to our top node
    Node* m_topNode;

    /// Running count of elements
    int m_count;
    public:
    ///Constructor
    Stack();

    ///Allows us to retrieve the top value from the stack
    /// and remove it from the stack
    int Pop();
    .
    .
    .
};
#endif

以下は、ヘッダーに一致する CPP です。現時点では、デバッグのためだけにここでやっています。また、ポインターと参照の損失に問題が発生しているかどうかわからなかったため、すべてを完全に修飾しています。

//Stack.cpp
#include "stdafx.h"
#include "Stack.h"
#include <iostream>
Stack::Stack(){
    m_count = 0;
    m_topNode = NULL;
} 

void Stack::Push(int Value){

    std::cout << "\nPushing Value: ";
    std::cout << Value;
    std::cout << "\n";
    if ( Stack::m_topNode )
    {
        std::cout << "TopNode Value: ";
        std::cout << Stack::m_topNode->data;
        std::cout << "\n";
    }
    std::cout << "\n";

    Node newNode(Value, NULL, Stack::m_topNode);
    Stack::m_topNode = &newNode;
    Stack::m_count++;
}

ノード クラスは非常に単純なエンティティです。値とポインタを両側に格納するだけです。スタックの両方向で追跡する必要がないことはわかっていますが、これをキューまたは同様の構造に簡単に変更できるものにしたかったのです。

//Node.h

#ifndef __NODE_INCLUDED__
#define __NODE_INCLUDED__
class Node
{
    private:

    public:
    ///Constructor allows us to specify all values. 
    /// In a stack I expect NextNode to be NULL
    Node(int Value,Node* NextNode, Node* PreviousNode);

    ///Pointer to the next node
    Node* Next;

    ///Pointer to the previous node
    Node* Prev;

    ///Value to be stored
    int data;
}; 
#endif

非常に単純な実装: //Node.cpp #include "stdafx.h" #include "Node.h"

Node::Node(int Value, Node* NextNode, Node* PreviousNode){
    data = Value;
    Next = NextNode;
    Prev = PreviousNode;
}

私のメインは、プッシュを介して現在スタックに2つの値を送信し、値が出力されていることを確認することです:

#include "stdafx.h"
#include "Node.h"
#include "Stack.h"
using namespace std;

int main(){
    Stack s = Stack();

    for ( int i = 0; i < 2; i++ ){
        s.Push(i * 10);
    }

    int blah;
    cin >> blah; //Stall screen
    return 0;
}

出力は次のとおりです。

 Pushing Value: 0

 <blank line>
 Pushing Value: 10
 TopNode Value: -858993460

デバッガーで Node newNode(Value, NULL, Stack::m_topNode) をヒットすると、現在のノードで適切な値を追跡していることがわかりますが、m_topNode は非常に奇妙な値を参照しています。何年も前にやったときにこれがこれほどトリッキーだったことを覚えていないので、私が愚かなことをしていることは非常に明白であることを願っています. 私の間違ったマナーへの助け/洞察に感謝します。

4

3 に答える 3

5
Node newNode(Value, NULL, Stack::m_topNode);
Stack::m_topNode = &newNode;
Stack::m_count++;

これはあなたの問題です。現在のスタックに新しいノードを割り当ててから、ポインターをノードのリンク リストに配置します。このポインターは、スタック フレームが戻るとすぐに無効になり、すべての地獄の休憩が失われます。;)

ノードを new で割り当てる必要があります。

于 2013-09-25T18:30:28.217 に答える
2

Norwæ が述べているように、newNode を「new」で割り当てる必要があります。そうしないと、newNode が静的になり、Push 関数の最後で範囲外になるためです。

また、"Stack::" なしでプライベート メンバーを呼び出す必要もあります。これは、C++ で静的なクラス メンバーと関数にアクセスするためだけに使用されるためです。「Stack::m_topNode」を「m_topNode」のみに置き換え、Stack::m_count を m_count に置き換えます。

これは動作中のプッシュ機能です:

void Stack::Push(int Value){

std::cout << "\nPushing Value: ";
std::cout << Value;
std::cout << "\n";
if ( m_topNode )
{
    std::cout << "TopNode Value: ";
    std::cout << m_topNode->data;
    std::cout << "\n";
}
std::cout << "\n";

Node * newNode = new Node(Value, NULL, m_topNode);
m_topNode = newNode;
m_count++;

}
于 2013-09-25T19:05:31.223 に答える
0

この行:

std::cout << Stack::m_topNode->data;

前に起こる

Node newNode(Value, NULL, Stack::m_topNode);
Stack::m_topNode = &newNode;
Stack::m_count++;

したがって、初期化されていない値を出力しようとしています。これらを逆にして、何が起こるかを見てください。

于 2013-09-25T18:33:13.290 に答える