1

さまざまな検索エンジン (および素晴らしいスタックオーバーフロー データベース) を使用して、似たような状況をいくつか見つけましたが、それらははるかに複雑であるか、私が達成しようとしているほど複雑ではありません。

テンプレートを使用した C++ リスト ループリンク エラーC++: リンク リストの順序付け ポインタ アドレスがリンク リストで変更されない

非標準のクラス オブジェクト (この場合は、分類された連絡先のコレクション) を保存および印刷するために、リンク リストおよびノー​​ド テンプレートを使用しようとしています。特に、さまざまなカテゴリのオブジェクトの束から、同じカテゴリを持つ複数のオブジェクトを印刷したいと考えています。カテゴリ別に印刷する場合、サブオブジェクト tmpCategory (= "business") を分類された連絡先のカテゴリ部分と比較します。

しかし、int main() で比較するためにこのデータを抽出する方法は?

これが私が考えていることです。LinkList.tem で GetItem メンバー関数を作成します。これにより、ポインター カーソルが初期化され、関数の入力が反復回数と一致するまで For ループが実行されます。その時点で、GetItem は (カーソル -> データ) を使用してオブジェクト タイプを返します。

template <class Type>
Type LinkList<Type>::GetItem(int itemNumber) const
{
    Node<Type>* cursor = NULL;

    for(cursor = first;
        cursor != NULL;
        cursor = (cursor -> next))
    {
        for(int i = 0; i < used; i++)
        {
            if(itemNumber == i)
            {
                return(cursor -> data);
            }
        }
    }
}

ここで int main() の出番です。比較オブジェクト tmpCategory を特定の値 (この場合は「Business」) に設定します。次に、(関数 GetUsed() によって決定される) ノードの数に等しいサイクルを反復する For ループを実行します。そのループ内で、現在の反復回数を使用して GetItem を呼び出します。理論的には、これにより int メイン ループが LinkList.tem から対応するノードを返すようになります。そこから、そのノードのデータ内のオブジェクトからカテゴリを呼び出します (現在は機能しています)。これは tmpCategory と比較されます。一致する場合、ループはノードのデータ オブジェクト全体を出力します。

tmpCategory = "Business";

for(int i = 0; i < myCategorizedContact.GetUsed(); i++)
{
    if(myCategorizedContact.GetItem(i).getCategory() == tmpCategory)
       cout << myCategorizedContact.GetItem(i);
}

問題は、現在のセットアップ (実行中) が何も返さないことです。さらにテスト ( cout << myCategorizedContact.GetItem(i).getCategory() ) すると、最初のノードのカテゴリを何度も何度も出力しているだけであることがわかりました。同じノードを吐き出すだけでなく、すべてのノードを評価して一致するデータを出力する全体的なスキームが必要です。

どんなアイデア/提案も大歓迎です。

4

1 に答える 1

0

これを注意深く見ください:

template <class Type>
Type LinkList<Type>::GetItem(int itemNumber) const
{
    Node<Type>* cursor = NULL;

    // loop over all items in the linked list    
    for(cursor = first;
        cursor != NULL;
        cursor = (cursor -> next))
    {
        // for each item in the linked list, run a for-loop 
        // counter from 0 to (used-1). 
        for(int i = 0; i < used; i++)
        {
            // if the passed in itemNumber matches 'i' anytime
            //  before we reach the end of the for-loop, return
            //  whatever the current cursor is.
            if(itemNumber == i)
            {
                return(cursor -> data);
            }
        }
    }
}

リストの時間だけカーソルを下に移動しているわけではありませんitemNumber。最初のアイテムcursor参照は、inner-for-loopを開始します。ループインデックスがitemNumberに達した瞬間に戻ります。リンクリストに少なくともitemNumberアイテムがリストに含まれている場合は、カーソルを進めることはありません。。実際、この2つ(cursorとitemNumber)は、この関数の実装ではまったく関係ありません。そして、本当に皮肉なことに、usedcursorは完全に無関係であるため、が未満の場合usedは常にそうなります。これは、外側のループを進んでも変化しないためです。したがってitemNumberusedcursorcursor最終的にNULLになり、この関数の結果は未定義です(戻り値なし)。要約すると、記述されているように、常に最初の項目(if itemNumber < used)を返すか、戻り値がないため未定義の動作を返します。

代わりに、次のようなものが必要だと思います。

template< class Type >
Type LinkList<Type>::GetItem(int itemNumber) const
{
    const Node<Type>* cursor = first;
    while (cursor && itemNumber-- > 0)
        cursor = cursor->next;

    if (cursor)
        return cursor->data;

    // note: this is here because you're definition is to return
    //  an item COPY. This case would be better off returning a 
    //  `const Type*` instead, which would at least allow you to
    //  communicate to the caller that there was no item at the 
    //  proposed index (because the list is undersized) and return
    //  NULL, which the caller could check.
    return Type();
}
于 2012-11-10T09:18:49.583 に答える