変更してはならない特定のクラスヘッダーを持つリンクリストを反復処理するように求められる宿題が与えられました。
template<typename ItemType>
class LinkedList{
public:
...
LinkedList();
LinkedList(const LinkedList<ItemType>&);
int getCurrentSize340RecursiveNoHelper() const;
private:
Node<ItemType>* headPtr{ nullptr }; // Pointer to first node
}
ノードクラスヘッダーは次のとおりです。
template<typename ItemType>
class Node {
public:
...
Node();
Node(const ItemType&);
Node(const ItemType&, Node<ItemType>*);
Node<ItemType>* getNext() const;
private:
ItemType item; // A data item
Node<ItemType>* next{ nullptr }; // Pointer to next node
}
関数getCurrentSize340RecursiveNoHelper()
では、サイズを取得するためにリンクリストを反復することになっています。
静的またはグローバルの助けを借りてリンクリストを繰り返すことができることは知っていますが、私の教授はそれらの使用を避けるべきだと言っています。それを行うための可能な方法はありますか?
関数getCurrentSize340RecursiveNoHelper()では、リンクリストを反復してサイズを取得することになっています。
静的またはグローバルの助けを借りてリンクリストを繰り返すことができることは知っていますが、私の教授はそれらの使用を避けるべきだと言っています。
それを行うための可能な方法はありますか?
最初の最後の質問:はい、これは可能で、簡単ですらあります。ソフトウェアは非常に柔軟です。
関数パラメーターなしの再帰(静的変数、グローバル変数)。
パラメータを使用しない反復と再帰は、方法を理解すれば、どちらも簡単に実行できます。
そして練習すれば、静的変数とグローバル変数の両方を簡単に回避できます。
https://stackoverflow.com/a/45550373/2785528も参照してください。これは、「グローバル変数を使用せずにシステムを介してユーザー入力を渡す」ための簡単なメカニズムを示しています。これを2つのステップにまとめることができます。a)メインの早い段階でカスタムクラスインスタンスをインスタンス化して、さまざまなユーザーがフェッチするためにグローバル変数に配置するユーザー入力/値を(「トランスポート」用に)含めます。b)これらのトランスポートオブジェクトを必要とするオブジェクトのctorを参照して、これらのトランスポートオブジェクトを渡します(トラベルケースと同様の方法で)。簡単。
ユーザー定義型(UDT)を主張する教授への工藤。これはあなたが練習する必要があるものです。
ただし、この投稿では、問題がないと述べたUDTを単に無視することで、ハウツー(パラメーターなしの反復と再帰など)を学習する方が簡単です。このようにして、関数形式に集中することができます。
さらに単純化するために、私の例はファンクターです...短くて単純な形式のクラスです。シンプルで効率的なFunctorクラスをお勧めします。
そしてもう1つ簡単に、std :: listを使用します。このコンテナを作成、充填、および使用する方法の例はたくさんあります。
(パラメータなしの関数をサポートするための)重要なアイデアの1つは、データとメソッドをクラスに「バンドル」することです。カプセル化はあなたの友達です。
アイデア1-main()を最小化します。短くしてください。出て、ビジネスに直接。
int main(int, char**)
{
int retVal = 0;
retVal += F820_Iterative_t()();
retVal += F820_Recursive_t()();
return retVal;
}
ここでは、2つのファンクターが呼び出されます。反復的な例と再帰的な例を分けました。
これらのファンクターは、メインの早い段階で呼び出されることに注意してください。mainの前に初期化されるものはたくさんあります(ただし、よく知られている初期化の大失敗を参照してください)。これにより、これらの初期化がいつ発生するかが簡素化および制御されます。
最初のファンクターは、インスタンス化、処理、および破棄し、次のファンクターが開始される前に、つまりシリアル化される前に、その存続期間全体を完了します。
データ型:
// examples use std::list
// user typedefs ---------------vvvvvvvvvvv
typedef list<string> StrList_t;
typedef list<string>::iterator StrListIt_t;
データ属性:
// Functor
class F820_Iterative_t
{
// NOTE: class instance data attributes are not global vars
StrList_t m_strList; // std::list<std::string>
StrListIt_t m_it; // std::list<std::string>::iterator
...
// Functor
class F820_Recursive_t
{
StrList_t m_strList; // std::list<std::string>
StrListIt_t m_it; // std::list<std::string>::iterator
...
例1-反復要素数
// iterate with no parameters, static vars, or global vars
uint F820_Iterative_t::iterateCount( )
{ // --^-- no params
uint lcount = 0;
do // -------------iterative loop
{
if (m_it == m_strList.end()) // detect end of list
break; // kick out
lcount += 1;
m_it++; // step to next element
} while(true);
return(lcount);
}
例2-再帰的な要素数
// recurse with no parameters, static vars, or global vars
uint F820_Recursion_t::recurseCount( )
{ // --^-- no params
if (m_it == m_strList.end()) // RTC (recursion termination clause)
return 0;
m_it++; // step to next element
return (1 + recurseCount()); // tail recursion
} // --^^^^^^^^^^^^-- recursive invocation
上記の両方の要素カウント関数では、F820_xxx :: xxxCount()が呼び出される前にFunctorデータ属性が初期化されます。
このコードは、関数パラメーターとグローバル変数を使用していません。これらの関数で使用される変数(m_itおよびm_strList)は、クラスインスタンスのデータ属性です。関数は、暗黙の「this」ポインターを介してそれらに直接アクセスします。
人生は中断します。
両方のxxxxCount()は、比較のために上記にあります。必要に応じて、このコードをコンパイルして実行します。残りを挿入する時間を見つける予定です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加