今日のひらしょー本(20150415):Cp3

うーーん. ようやく進んだ.

今日のひらしょー本の目次

http://snoopopo.hatenablog.com/entry/2015/04/27/114854

はまったエラー

こんなんなってた…↓ f:id:snoopopo:20150416012508p:plain

dds(バイナリ)データ読み込み ifstream in( filename, ios::binary );

ifstream in( filename, ios::binary );

第二引数のbinaryがないとうまくddsファイルを読み込まなかった.上半分とか半端に表示された.

ひらしょー本では以下の通りにbinaryはifstreamという名前空間で指定しているけどどちらも xiosbase というファイルのbinaryを指してた.

ifstream in( filename, ifstream::binary );

文字コードの分が…

ステージのxがひらしょーさんのより1つ多い原因は、以下ソースの通り.

・ひらしょーさん

void State::setSize( const char* stageData, int size ){
    mWidth = mHeight = 0; //初期化
    //現在位置
    int x = 0;
    int y = 0;
    for ( int i = 0; i < size; ++i ){
        switch ( stageData[ i ] ){
            case '#': case ' ': case 'o': case 'O':
            case '.': case 'p': case 'P':
                ++x;
                break;
            case '\n': 
                ++y;
                //最大値更新
                mWidth = ( mWidth > x ) ? mWidth : x;
                mHeight = ( mHeight > y ) ? mHeight : y;
                x = 0; 
                break;
        }
    }
}

・僕のソース(修正前)

void Status::setSize( const char* fileStage ){
    const char* i = fileStage;
    int x = 0;
    int y = 0;

    //改行コードから縦横サイズを計測
    while( *i != '\0'){   //char[]は最後に \0 が入っている
        switch( *i ){
            case '\n' : 
                ++y;
                mStageX = ( x > mStageX ) ? x : mStageX;
                mStageY = ( y > mStageY ) ? y : mStageY;
                x = 0;
                break;
            default: ++x;
        }
        ++i;
    }
}

改行コード \n かそれ以外で見ていたが、ステージファイルの文字コードがCRLFだったので、CR 相当のものが余分に1列多く出力されてた.

ステージファイルの改行コードが何でくるかなんてわからないので、それも許容してあげるべきだ.

条件を絞れるところで、絞らない(それ以外)としてしまうのは危険. 肝に銘じよう.

黒だけが黒く表示されない件

・僕のソース(修正前)

Image::Image( const char* fileImage ){
    
    mImageY = getUnsigned( &fileImage[12] );
    mImageX = getUnsigned( &fileImage[16] );
    mImageData = new unsigned[ mImageX * mImageY ];
    for( unsigned i = 0; i < mImageX * mImageY; ++i ){
        if( !fileImage[ 128 + i * 4 ] ){// データがあるか確認
            cout << "ArrayIndexOutOfBounds Error!!" << endl;
        }else{
            mImageData[ i ] = getUnsigned( &fileImage[ 128 + i * 4 ] );   //*4はunsignedが4バイトなので、char4つ分の意味
        }
    }
}

ddsファイル読み込む部分でのバグ.

     if( !fileImage[ 128 + i * 4 ] ){// データがあるか確認

やりたいことは、上記の部分ではnullポインターを検知したかったが、 データを判定してしまっている.

ここで書いた通り.→ http://snoopopo.hatenablog.com/entry/2015/04/08/003404

今回のバグは、黒色が白っぽく表示されており、 fileImage[]の値が黒色を表す 0x000000 = 0 だったため、このif文は if(!0)となり、trueになってた….

if文について

大きな勘違いをしていた.javaではこういう意識でやれてなかったけど、

cppのifは0以外→true 0→false という意味.

となると、boolのtrueは0以外を表していて,falseは0ということ.

int a = 1;
int b = 1;

if( a == b ) //←この a == b の判定もtrueっていうよりは1が返ってきている.

null判定について

nullなのか判断したいときはどうすればいいか.

int *p;
if( !p ){ //落ちる!
    cout << "nullpointer" << endl;
}

↑の通りにするとif判定の時点で落ちる.

int *p = 0;
if( !p ){
    cout << "nullpointer" << endl;
}

ポインタの代入をすぐしない場合は、初期値を0にしておくと判定出来る.

つまりif( !p ) は0なので!マークついててtrueになる.

まあポインタに代入しない前に使われるとまずいから落ちた方が正解かもしれないけど,

ひらしょーさんがdeleteした後にポインタに0を詰めるのはこれだな.後で説明ありそうだけど.

明確に使ってないことを示すために 0 を詰めるお約束みたいにしてるってことか.

この記事の成果物

https://github.com/snoopopo/puzzleGame/tree/master/NimotsuKunImage