2016-07-02 21 views
2

私はArduinoでプログラミングしていて、私のプログラムにはwhileループがたくさんあります。 Arduinoが文字を受け取ったとき、それは文字を受け取ったときにあったループからいくつかの計算を行い、中断しなければなりません。私はあなたに単純な例を与える(i、jは0に設定されていると推定):あなたは、私がもし文章内のコードの同じ部分を使用し、両方のケースでそれを見ることができます外部メソッドでループを中断する

while (i < 256) 
{ 
    // some calculations #1 
    i++; 

    if (Serial.available() > 0) 
    { 
     setStringOne = "string one" 
     setStringTwo = "string two" 
     setStringThree = "string three" 
     setStringFour = "string four" 

     break; 
    } 
} 

while (j < 256) 
{ 
    // some calculations #2 
    j++; 

    if (Serial.available() > 0) 
    { 
     setStringOne = "string one" 
     setStringTwo = "string two" 
     setStringThree = "string three" 
     setStringFour = "string four" 

     break; 
    } 
} 

。このようなことを書くことができるようにしたい。

while (i < 256) 
{ 
    // some calculations #1 
    i++; 

    if (Serial.available() > 0) 
     checkAndBreak(); 
} 

while (j < 256) 
{ 
    // some calculations #2 
    j++; 

    if (Serial.available() > 0) 
     checkAndBreak(); 
} 

void checkAndBreak() 
{ 
    if (Serial.available() > 0) 
    { 
     setStringOne = "string one" 
     setStringTwo = "string two" 
     setStringThree = "string three" 
     setStringFour = "string four" 

     break; 
    } 
} 

外部メソッドを使用してループを中断する。

"ループやスイッチ内ではないbreak文"というエラーが表示されます。これは、どのループが壊れているかわからないためですが、これらの行に何かを加えることが可能かどうか疑問に思っていました。

ありがとうございます!

+1

あなたは 'checkAndBreak'マクロまたは例外や' longjmp'を使用することができます。 – melpomene

+3

ループ条件を 'while(j <256 && Serial.available()<= 0)'に変更すると、ブレークを取り除くことができます – user3147395

+0

ああ、私はそれについても考えていません。ありがとう。 – orglce

答えて

6

あなたはそんなに壊れることはありません。ただ、各メソッドが何をするかのバランスを取る:あなた」

while (i < 256) 
{ 
     if (Serial.available() > 0) 
     { 
      setThoseStrings(); 
      break; 
     } 
     i++; 
} 

はまた

while (i < 256) 
{ 
     if (checkSerialAndSetStrings()) 
     { 
       break; 
     } 
     i++; 
} 

これは短くなりますが、あなたは今まで(タイマーが切れるとき、例えば、それらを設定する)他の状況で文字列を設定する必要がある場合シリアルチェックを削除してcheckSerialAndSetStringsから時間を無駄にしてコードを更新してください。私は#1で行くだろう。

+0

さて、私はこれをこのようにしなければならないと思う。とにかく答えてくれてありがとう。 :) – orglce

1

returnで同様のトリックを行うことはできますが、古い学校のプログラマにとってはあまり明らかではないようです。それ前に、あなたの計算をチェックする必要はありませ Serial.avaiable()戻り符号なし整数と仮定すると、あなたが、あなたが実際にあなたがあなたの文字列を更新すると、ポストエフェクトとして更新i,jカウンタを必要とする、私はそれにこれを行うだろうを行う方法:最後にi,jはあなたの例のように同じ値が得られることを

// Obviously this function somehow has 
// access to the strings being modified 
// And possibly to some other state affected by calculations #1 and #2 
// I'm leaving it similar to how you've written it 
// for the sake of clarity 
bool checkAndBreak() 
{ 
    if (!Serial.available()) 
     return false; 

    setStringOne = "string one"; 
    setStringTwo = "string two"; 
    setStringThree = "string three"; 
    setStringFour = "string four"; 

    return true; 
} 

size_t i = 0, j = 0; 

do { 
    // calculations #1 
} while (++i, !checkAndBreak() && i < 256); 

do { 
    // calculations #2 
} while (++j, !checkAndBreak() && j < 256); 

注意。 もう一つの面白い方法がある:

// define `i,j` outside of the loops if you need their final values 
// !i and !j checks are to make sure checkAndBreak() 
// won't execute before the loop body 
for (size_t i = 0; (!i || !checkAndBreak()) && i < 256; ++i) 
    // calculations #1 
for (size_t j = 0; (!j || !checkAndBreak()) && j < 256; ++j) 
    // calculations #2 

また、機能にあなたの計算を抽出することができます。

void calc1(size_t i) { ... } 
void calc2(size_t j) { ... } 

for (size_t i = 0; i < 256 && (calc1(i++), !checkAndBreak());); 
for (size_t j = 0; j < 256 && (calc2(j++), !checkAndBreak());); 

あなたが最初にあなたの< 256チェックを得る。この方法は、その後、calc1/calc2は、その後、古いi/j値で実行されていますi/jの値がインクリメントされ、チェックが実行されます。チェックがtrueを返す場合、forループ全体が終了します。

これらのプラクティスはKISSの原則と一致していないことに注意してください、あなたは単にあなたが使用してはならない理由は、完璧な例です

for (size_t i = 0; i < 256; ++i) 
{ 
    // do the calculations #1 
    // now check the side effects of those calculations 
    if (serialCheckedAndStateChanged()) 
     break; 
} 
// The same for #2 
+0

本当に役に立つ例。ありがとう! – orglce

1

を書くためにあなたのコード、事前条件と事後効果を調整することができますメソッド/プロシージャ内の "break"、 "continue"または複数のreturn文。冗長性を減らす方法を抽出することはできません。私のアドバイスは、あなたのコードを改行ステートメントなしで動作させるように修正することです。

私はアプローチを以下しようとするだろう:

do { 
    // some calculations #1 
    i++; 
} while (i < 256 && Serial.available() == 0) 

if (Serial.available() > 0) 
{ 
    setStringOne = "string one" 
    setStringTwo = "string two" 
    setStringThree = "string three" 
    setStringFour = "string four" 
} 

do { 
    // some calculations #2 
    j++; 

} while (j < 256 && Serial.available() == 0) 

if (Serial.available() > 0) 
{ 
    setStringOne = "string one" 
    setStringTwo = "string two" 
    setStringThree = "string three" 
    setStringFour = "string four" 
} 

今、あなたはコード改善することができます:

抽出方法をと(Arduinoの中で可能な限り)計算コードにテンプレートパターンを適用冗長性を減らす。抽出方法の

例:

void determineString() 
{ 
    if (Serial.available() > 0) 
    { 
     setStringOne = "string one" 
     setStringTwo = "string two" 
     setStringThree = "string three" 
     setStringFour = "string four" 
    } 
} 
+0

ありがとうございます。はい、私も休憩を使用しないように私のコードを書き換え、私はいくつかの冗長性を取り除いた。 – orglce

+1

'Serial.available()'に副作用がなく、無償で提供されると仮定して、各ループの後にもう一度呼び出します。あなたが休憩を取り除きたいのであれば、適切な方法は、各ループを計算を行う関数に抽出し、反復が終了すると 'Serial.available()> 0'または' false'を返すときに 'true'を返すことです。 – kikobyte

+0

あなたは正しい:その "Serial.available()" "[...]は副作用がなく、無償で提供されている" ... "は推測でした。私はそれがどのように命名されるのかを期待していました。それを見てから、私の前提は現実から遠く離れていないようです。 (https://www.arduino.cc/en/Serial/Available)。 – oopexpert

関連する問題