for( unsigned int i=10; i>=0; i-- )
と書くと、i=0 の次は正の最大値になってループが終わりません。
皆さんはこういう場合(たとえばvectorを逆順にアクセスし、インデクスの値もループ内で使いたい場合)どうしますか?
非常に主観的かつ興味本位ですが、int を使う以上に「気持ちいい」解決策があれば見てみたいと思い質問しました。
unsigned int i = UINT_MAX;
do {
ほにゃらら;
i--;
} while (i != UINT_MAX);
とすれば、UINT_MAX 回、ほにゃららが実行されることにはなるかな。
でも、コメントなしで、この終了条件が理解されることは無いと思う。
ありがとうございます。
ループの外側に変数を作れば
unsigned int i=N;
do{
xxx;
i--;
}while( i != 0 )
とできますね。
iの値を1増やして
for(unsigned int i = 11;i>0;i--) printf("%d",i-1);
という感じに、iが使われるところで-1する。
または、
for(unsigned int i = 10,int j = 10;j >= 0;i--,j--)
という具合に、ループのカウンタだけに使用するintの変数を追加する。
ありがとうございます。
前者はバグの原因になりそうですね。
後者のような書き方ができるのですね。
でもやっぱり可読性が悪くなるのは避けられないみたいですね。
ループカウンターとインデックスを分けるとか。
#include <vector> #include <iostream> typedef std::vector<int> vector_int; int main() { vector_int ary; ary.push_back(1); ary.push_back(2); ary.push_back(3); for ( vector_int::size_type n = ary.size(); n > 0; --n ) { vector_int::size_type i = n - 1; std::cout << ary[i] << "\n"; } }
ありがとうございます。
色々なやり方を紹介していただきましたが、ところで
皆様は実際にこういう場面でこの書き方をされるのでしょうか?
それともやはり int で書きますか?
質問とはあまり関係ないですが,
これはいわゆる「番兵」の問題に似ていますね.
方法としては2番の回答と同じことです.
unsignedの場合は,最大値(UINT_MAX)がNULL(無効なデータ)なのだと考えれば
わりと綺麗に理解できるかもしれません.
#define UINT_NULL UINT_MAX for ( unsigned int i = 10; i != UINT_NULL ; i-- ) { ... }
実際,STLなどではイテレータでこういう書き方(!=を使いNULLと比較する)
をよくします.
これは気持ちがいい(主観ですが)ですね!
#define するだけで全く可読性が変わりますね。
ありがとうございます。
for( unsigned int i=0; i<=10; i++ ) { unsigned int index = 10 - i; // do somthing }
として実際のインデックスには index を使うとか?
ありがとうございます。
これはやったことがありますが、何となく負けかなと思っています。
制約がないなら別変数を用意します。
この条件で無理矢理するなら
for ( unsigned int i = 10; i+1 >= 1; i-- ) { ... }
でしょうか。一応 unsigned じゃなくなってもそのまま動きます。
書いた人以外が見たらなんだこりゃと思われそうですが。
なるほど、 i>=0 はダメだけど i+1>=1 は ok なんですね。
勉強になります。ありがとうございます。
ところで皆様は実際にこういう場面でこの書き方をされるのでしょうか?
それともやはり int で書きますか?
使い捨てのプログラムの場合は符号あり整数を使う場合もありますが、基本的には回答 4 で書いたように符号なし整数を使います。(その場合、別の変数に代入せず、使う場所で -1 する場合もあります。)
というか、std::size_t や foo::size_type など実際の型を隠蔽した型(名前)を使うので、符号あり/なしどちらでも良いように書きます。
なお、C/C++ で整数演算時のオーバーフロー/アンダーフローの動作は未定義だという認識なので、回答 2 や回答 5 のように 0 - 1 が最大値になることを期待する書き方はしません。
なるほど、確かにアンダーフローを前提に書くのは危ない面がありますね。
回答 4 や回答 6 のきれいさが理解できました。ありがとうございます。
こんばんは。
そもそも、vector::size_typeの最大値が、
unsigned int の最大値をこえないという保障はあるのでしょうか?
保証がないのなら、この時点で負けてると思います。
ありがとうございます。その通りでした。
回答 8 にあるように、そもそも隠蔽した型で符号あり/なしによらないコードを書くべきで、
そうではなく直接 unsigned int を使う場合に限り上の色々な方法を使えばよい、というように
理解しました。
稚拙な質問ですみません。勉強になりました。
皆様、ありがとうございます。
ありがとうございます。
しかし可読性が微妙で、こう書くくらいなら int を使うだろうなと思います。