11: 2016-06-18 (土) 10:57:45 osinko |
現: 2016-08-01 (月) 01:45:01 osinko |
| 有用なデザインパターンをサンプルコードとして羅列したページ | | 有用なデザインパターンをサンプルコードとして羅列したページ |
| | | |
| + | **switch_case文とcontinue;との関係 [#sdc20f7e] |
| + | |
| + | switch_case文の内部でbreak;はよく使われるがcontinue;を利用する場合はちょっと特殊な考え方になる |
| + | switch文の外側にあるネスト内の反復処理、for、while、do 、foreachに対して次のループに移る |
| + | 特殊な検索をかける場合に憶えておくと便利なやり方になる |
| + | |
| + | visualStudioではカーソルをbreak;やcontinue;の上に持っていくと関連している構文をマーカー表示する |
| + | わからなくなったら、まずこれで位置を確認すると良い |
| + | |
| + | #code(csharp){{ |
| + | using UnityEngine; |
| + | using System.Collections; |
| + | |
| + | public class SwitchContinue : MonoBehaviour |
| + | { |
| + | //優先順位の低い文字を検索する |
| + | void Start() |
| + | { |
| + | //括弧で囲まれると優先順位は上がるとする |
| + | string str ="B(AC(1A))CB(57A6)"; |
| + | int pos = 0; |
| + | int nest = 0; |
| + | int priority = 0; |
| + | int lowPriority = 3; |
| + | |
| + | //for文に対してcontinue;はここに来る |
| + | for (int i = 0; i < str.Length; i++) |
| + | { |
| + | switch (str[i]) |
| + | { |
| + | case 'A': priority = 1; break; //switch_case文に対してのbreak; |
| + | case 'B': priority = 2; break; |
| + | case 'C': priority = 3; break; |
| + | case '(': nest++; continue; |
| + | case ')': nest--; continue; |
| + | default: continue; //for文に対してのcontinue; |
| + | } |
| + | |
| + | //switch_case文に対してのbreak;はここに来る |
| + | if (nest==0 && priority <= lowPriority) |
| + | { |
| + | lowPriority = priority; |
| + | pos = i; |
| + | } |
| + | } |
| + | |
| + | print(string.Format("配列位置:{0} の文字:{1}", pos,str[pos])); |
| + | } |
| + | } |
| + | }} |
| | | |
| **帰納関数のサンプル(順列の出力) [#m9ded6a9] | | **帰納関数のサンプル(順列の出力) [#m9ded6a9] |
| -基底部、帰納部の二段階で関数を作成する(ドミノの一つ目、それに続く無限のドミノ、とふたつに分ける) | | -基底部、帰納部の二段階で関数を作成する(ドミノの一つ目、それに続く無限のドミノ、とふたつに分ける) |
| -基底の呼び出しの際は出来るだけ余計なデーターを渡さないように設計する | | -基底の呼び出しの際は出来るだけ余計なデーターを渡さないように設計する |
- | -派生する関数(帰納部)には「差が生じるデータ」を参照渡ししないようにする | + | -派生した関数(帰納部)で扱う「差が生じるデータ」部が参照渡しの値の場合、希望する動作により呼び出し元が書き換えられると困る場合もあるので値の動きに注意する。必要であれば複製する |
| -帰納関数の入口に終了条件を設定する | | -帰納関数の入口に終了条件を設定する |
| | | |
| void Start() | | void Start() |
| { | | { |
- | int length = 4; | + | int length = 3; |
| char[] set = { 'A', 'B', 'C' }; | | char[] set = { 'A', 'B', 'C' }; |
| | | |
| for (int i = 0; i < set.Length; i++) | | for (int i = 0; i < set.Length; i++) |
| { | | { |
- | char[] cloneDat = (char[])dat.Clone(); //オブジェクトを複製する(帰納関数に参照渡ししないために大事な事!) | + | char[] cloneDat = (char[])dat.Clone(); //オブジェクトを複製する |
| cloneDat[level] = set[i]; | | cloneDat[level] = set[i]; |
- | Loop(cloneDat, level, set, strList); //複製したものを派生する帰納関数に渡すことが大事(それが差になる) | + | Loop(cloneDat, level, set, strList); //帰納関数には複製された参照値が渡される為、呼び出し元側の値が書き換えられることは無い |
| } | | } |
| } | | } |
| } | | } |
| } | | } |
| + | } |
| + | } |
| + | |
| + | }} |
| + | |
| + | ***補足:値渡し、参照渡しとは? [#v46aed99] |
| + | |
| + | 以下のコードの出力は |
| + | |
| + | 123 |
| + | 0 |
| + | 789 |
| + | |
| + | となる |
| + | |
| + | 変数valListの内容が関数内で書き換えられている点に注目。int型は値型だが、int[]型は参照型になるので関数は参照渡しを受け取り、呼び出し元を書き換える |
| + | つまり帰納関数で同様の事をした場合、派生先の関数内の書き換えで呼び出し元を書き変える事になり希望していた効果が得られない事がある |
| + | |
| + | #code(csharp){{ |
| + | using UnityEngine; |
| + | using System.Collections; |
| + | |
| + | public class TestMetho : MonoBehaviour { |
| + | |
| + | void Start () { |
| + | |
| + | int val = 123; |
| + | int[] valList = { 456, 789 }; |
| + | |
| + | Method(val, valList); |
| + | |
| + | print(val); |
| + | print(valList[0]); |
| + | print(valList[1]); |
| + | } |
| + | |
| + | void Method(int val, int[] valList) { |
| + | val = 000; |
| + | valList[0] = 000; |
| } | | } |
| } | | } |