0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

変なfor文にビビらないために

Last updated at Posted at 2024-02-08

はじめに

for文?ああ

sample.c
for(int i = 0; i <= 10; i++){
    sum = sum + i;
}

みたいなやつね知ってる知ってる~ぐらいの人に、

・初期化式
・条件式
・変化式

について一度知っておこう、という記事。

初期化式

int i = 0;
に代表される部分。

for文を実行するとき、最初に一度だけ実行される。
for(int i = 0;のように、for文の中で初めて宣言された変数は、
for文の外では使えない。(変数のスコープ)

なので、for文の外で使いまわしたい場合、宣言も、for文の外でする必要がある。

sample.c
int i;
for(i = 0; i <= 10; i++){
    //繰り返し処理
}

int x = i + 1;

for文の外で宣言と初期化 int i = 0 するとどうなるか?
初期化式が必要なくなる。

しかし、初期化式がどこからどこまでかコンピュータが把握するには、
セミコロン;が必要。

という事情から、ごく稀に下のような、セミコロン;だけ急に出てくるfor文がある。

sample.c
//for文の外で宣言 & 初期化
int i = 0;

//既に宣言 & 初期化されているので初期化式を省略可能
for(; i <= 10; i++){
    //繰り返し処理
}

//iを初期化せず続き(i = 11)から実行する
for(; i <= 20; i++){
    //繰り返し処理
}

初期化式が省略されたfor文を見て
「なんだこのセミコロン?いらないだろうし消しておくか」
をすると当然のようにコンパイルエラーが出る。(体験談)

後者のようにiの値を使いまわす目的がないのであれば、
宣言時に初期化していてもちゃんと初期化式を書く方が見た目のやさしいコードになる。

sample.c
int i = 0;
for(i = 0; i <= 10; i++){
    //繰り返し処理
}

条件式

この部分がTRUEの間、for文が実行される。
つまり、i自体を評価する式でなくても問題ない。
実例を示すと

sample.c
int sum = 0;
//合計値が55未満の間、繰り返す
for(int i = 0; sum < 55; i++){
    sum = sum + i;
}

のようにsumを基準とした条件式でも構わない。
一般的なfor文は「どんな条件のとき終了か」というより「最大で何回繰り返すか」
を考えるので、普通は上のような書き方にはならない。breakを使う。

sample.c
int i = 0;
int sum = 0;

for(i = 0; i <= 10; i++){
    sum = sum + i;

    if(sum >= 55){
        break;
    }
}

個人的には、for文の主役は初期化式で初期化したものと同じ変数
( この場合i ) にしておくのが無難だと思う。

ちなみに、初期化式のように条件式も省略可能なので
i <= 10sum >= 55のようにループを抜けるタイミングが一致している場合、

sample.c
for(i = 0; ; i++){
    sum = sum + i;

    if(sum >= 55){
        break;
    }
}

としても "実行は" できる。(コンパイラによってはエラーを出すかも)

無限ループの可能性を生むので条件式の省略はやめましょう

変化式

ループ1周分の終了と開始の間に実行される式。
いわゆるi++の部分。
ここまででなんとなく予想はつくかもしれないが、変化式も省略できる。

for文の末尾か開始にi++;を書いてあげるだけで同じ処理になる。

sample.c
for(int i = 0; i <= 10;){
    //繰り返し処理
    i++;
}

変化"式"とあるように、1行に収まる式であればよいので、
三項演算子なんかもその気になれば使うことができる

sample.c
for(int i = 0; i <= 10; i = i + ((i % 2 == 0) ? 1 : 3)){
    //繰り返し処理
}

偶数の場合、i = i + 1
奇数の場合、i = i + 3
されるfor文。

もっと複雑な処理が挟まれる場合、関数を作ってiのポインタ&iを渡す、という手もある

sample.c
void main(){
    for(int i = 0; i <= 10; function(&i)){
        //繰り返し処理
    }
}

void function(int* i){
    i = i + 1;
}

これは結局のところi++しているだけ。

おわりに

上の3つを合体させるとこんなfor文も作れるらしい。
泣かないで ( ; ; )

sample.c
int i = 0;
int sum = 0;

for( ; ; ){
    sum = sum + i;
    if(sum >= 55){
        break;
    }
    i++;
}

特別な理由がない場合は3つとも式を書きましょう。

0
0
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?