LoginSignup
1
3

More than 5 years have passed since last update.

C++ の小さな技術を紹介するシリーズ【小技C++ 全9回】#1<インデックスループ>

Last updated at Posted at 2018-04-15

インデックスループ

テーマ

ここに0から3までの数字を振った4つの箱と、箱を指定するためのカーソルが1つある。
カーソルは値を持ち、その値と同じ番号の箱を指定する。

[0]  [1]  [2]  [3]
 ^
 |
 0

カーソルが右へ移動するとき、0から3までの箱を順番に指定したのち、再び0へ戻りループするためには、カーソルの値をどのように計算すればよいだろうか。また、カーソルが左へ移動するときはどのように計算すればよいだろうか。

メソッド

(このシリーズで記述するコードは、あくまで筆者のオススメする案です。よりよい方法や、場面にあった手法を見つけるヒントとして使ってください。そして、楽しんでください!)

// 移動方向の定義

enum class OPERATION
{
    LEFT,
    RIGHT,
};
// op            : 移動方向
// index         : カーソルの値
// LOOP_WIDTH    : ループ幅

void UpdateIndex( const OPERATION op, size_t& index, const size_t LOOP_WIDTH );

if 文で境界をチェックする


void UpdateIndex( const OPERATION op, size_t& index, const size_t LOOP_WIDTH )
{
    if( op == OPERATION::LEFT ) {

        if( index > 0 ) {

            index--;            
        }
        else {

            index = LOOP_WIDTH - 1;
        }
    }
    else if ( op == OPERATION::RIGHT ) {

        if( index < LOOP_WIDTH - 1 ) {

            index++;
        }
        else {

            index = 0;
        }
    }
    else {
    }
}

C++ 初経験者が最初に思いつきやすい(プロの書くコードでもたまに見かける)コードだろう。条件式が多用され、自然言語をそのまま書き起こしたような構造になっているため、説明しやすい。しかし、実現したい計算のわりに、そのコード長が無視できないほどの長さであることは、無駄な保守コストやバグの原因となりやすい傾向にある。

剰余を使って計算する


void UpdateIndex( const OPERATION op, size_t& index, const size_t LOOP_WIDTH )
{
    switch( op )
    {
    case OPERATION::LEFT:
        index = ( index + LOOP_WIDTH - 1 ) % LOOP_WIDTH;
        break;
    case OPERATION::RIGHT:
        index = ( index + LOOP_WIDTH + 1 ) % LOOP_WIDTH;
        break;
    default:
        break;
    }
}

こちらのコードは、条件式による境界チェックを一切行わない。インクリメントされる値の剰余を求めることで、ループする数列を表現する。注意したいのは、剰余を求める前にループ幅と同じだけの「ゲタ」を履かせるところだ。左へ移動する場合に index が0のとき、1減算しても問題のないようにしてくれている。右へ移動する場合に 「ゲタ」は本来必要ないのだが、字面を近くすることで、2つの計算式が同じ性質であることを強調している。ただし、一見何をやっているのか理解されない可能性もあるため、慣れない相手にはフォローが必要になるかもしれない。

1
3
0

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
1
3