前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3

13.8. サンプルコード

13.8.1. CSV ファイルの処理

以下のコードは、 ファイル(SFXFile)からカンマで区切られた CSV データを読み込み、 配列(SFXArray)に格納します。

例 13.8. CSV データの例 ("/data.csv")

6,8,15,21,4,5

例 13.9. ファイルから CSV データを読み込み、配列に格納する

SFCError error;                    // エラー値
SFXFile file;                      // SFXFile インスタンス
SFXAnsiStringStreamReader reader;  // ファイル読み込み用ストリーム
SFXAnsiString stringFromFile;      // データが読み込まれる変数
SFXAnsiString csvElement;
SInt32 startOfComma, endOfComma;   // カンマの位置
SInt32 sum;                        // 要素の和
SFXArray<SInt32> array;            // SInt32 型データ要素からなる配列
SFXArray<SInt32>::Enumerator etor; // SInt32 型データ要素からなる配列の列挙子

// 読み込みモードでファイルを開く
if ((error = file.OpenReadOnly(SFXPath("/data.csv"))) == SFERR_NO_ERROR) {

    // ファイル読み込み用ストリームの取得 ( バッファサイズ: 1024 )
    if ((error = file.GetStreamReader(1024, &reader)) == SFERR_NO_ERROR) {

        // フェッチを行う
        if ((error = reader.Fetch()) == SFERR_NO_ERROR) {

            // ファイル読み込み用ストリームバッファから stringFromFile にデータを読み込む
            if ((error = reader.ReadSFXAnsiString(&stringFromFile))
                == SFERR_NO_ERROR) {

                startOfComma = 0;

                // カンマの位置を探す
                endOfComma = stringFromFile.FirstIndexOf(',');

                while (endOfComma >= 0) {   // カンマが見つかる限り繰り返す
                    
                    // 部分文字列を取得する
                    csvElement = stringFromFile.Substring(startOfComma, endOfComma);

                    // 文字列を数字に変換して array に格納する
                    if ((error = array.InsertLast(csvElement.AsSInt32()))
                        != SFERR_NO_ERROR) { // エラーが発生したとき
                        break;
                    }

                    // 次のカンマを探すために startOfComma を設定する
                    startOfComma = endOfComma + 1;
                    // 次のカンマの位置を startOfComma 文字目から探す
                    endOfComma = stringFromFile.FirstIndexOf(',', startOfComma);
                }

                if (error == SFERR_NO_ERROR) {

                    // 最後の文字列を取得する
                    csvElement = stringFromFile.Substring(startOfComma,
                        stringFromFile.GetLength());

                    // 文字列を数字に変換して array に格納する
                    if ((error = array.InsertLast(csvElement.AsSInt32())) == SFERR_NO_ERROR) {

                        // ここで読み込みを完了する

                        // 列挙子を取得する
                        etor = array.GetFirstEnumerator();
                        sum = 0;

                        while (etor.HasNext()) { 

                            // 各要素についての処理
                            SInt32 c;
                            c = etor.GetNext(); // 次の要素を取得する
                            sum += c;           // その要素を加算する
                        }

                        TRACE("%d", sum);
                    }
                }
            }
        }
        reader.Release();
    }
    file.Close();
}

例 13.10. 実行結果

*dbgprintf*:0 - 59

13.8.2. リストのソート

以下のコードは、 挿入ソートアルゴリズムを利用してリスト(SFXList)の要素をソートします。

[Tip] Tip
SFXList は、SFXArray よりも要素の挿入や削除が高速に行えます。

例 13.11. リストのソート

SFCError error;                     // エラー値
SFXList<SInt32> list;               // SInt32 型データ要素からなるリスト
SFXList<SInt32>::Enumerator etor;   // SInt32 型データ要素からなるリストの列挙子
SInt32 number[] = {14, 3, 22, -5, 8, 16, 1, 0, -7, -2}; // ソート対象のデータ
SInt32 i, j, ithValue, jthValue;


for (i = 0; i < lengthof(number); ++i) {

    error = list.InsertLast(number[i]);// 配列 number の要素を list に追加する
    if (error != SFERR_NO_ERROR) { 

        // エラーが発生したとき
        ...
        return;
    }
}

// リストの要素を値でソートする
// ※ 挿入ソートアルゴリズムを利用する
for (i = 1; i < list.GetSize(); ++i) {

    ithValue = list.Get(i);           // i 番目の要素の値を ithValue に格納する

    etor = list.GetFirstEnumerator(); // リストの列挙子を取得する

    for (j = 0; j < i; ++j) {  // ※ 0 ≦ j < i

        jthValue = etor.GetNext();    // j 番目の要素の値を jthValue に格納する(列挙子は次の要素に進む)

        if (jthValue > ithValue) { 
            // j 番目の要素の値が i 番目の要素の値よりも大きい場合

            // j 番目の要素の前に i 番目の要素を移動する
            list.Remove(i);                   // i 番目の要素を削除する(i 番目の要素の値は ithValue に格納されている)
            error = list.Insert(j, ithValue); // j 番目の要素の前に旧 i 番目の要素の値を挿入する

            if (error != SFERR_NO_ERROR) {

                // エラーが発生したとき
                ...
                return;
            }
            break;
        }
    }
}

// すべての要素をデバッグウィンドウに表示する

etor = list.GetFirstEnumerator();  // リストの列挙子を取得する

while (etor.HasNext()) {

    TRACE("%d", etor.GetNext());
}

例 13.12. 実行結果

*dbgprintf*:0 - -7
*dbgprintf*:0 - -5
*dbgprintf*:0 - -2
*dbgprintf*:0 - 0
*dbgprintf*:0 - 1
*dbgprintf*:0 - 3
*dbgprintf*:0 - 8
*dbgprintf*:0 - 14
*dbgprintf*:0 - 16
*dbgprintf*:0 - 22

13.8.3. クラスインスタンスのリスト処理

クラスインスタンスのように 4 バイトより大きなデータは、 要素としてコレクションクラスに格納できません。 このような場合は、4 バイトのポインタを要素としてコレクションクラスに格納します。

以下のコードは、 直線(SFXLine)をリスト(SFXList)の要素とし、 始点の X 座標でソートしています。

[Note] 注意
実際には SFXLine インスタンスへのポインタを SFXList の要素とし、 要素をクリアする前に SFXLine インスタンスを明示的に削除していることに注意してください。

例 13.13. SFXLine インスタンスのリスト処理

SFCError error;                       // エラー値
SFXList<SFXLinePtr> list;             // SFXLinePtr 型データの要素からなるリスト
SFXList<SFXLinePtr>::Enumerator etor; // リスト要素の列挙子
SFXMTRandom random;                   // 乱数
SFXLinePtr line, ithLine, jthLine;    // SFXLine インスタンスへのポインタ
SInt32 i, j;

// 10 個の直線を作成し、リストに格納する
for (i = 0; i < 10; ++i) {

    // 始点と終点の座標値をランダム関数を使用して生成し、直線を作成する
    if ((line = new SFXLine(random.GetSInt16(), random.GetSInt16(),
                            random.GetSInt16(), random.GetSInt16())) != null) {
        
        // 直線へのポインタを要素としてリストに追加する
        error = list.InsertLast(line);
    }
    else { 

        // 直線の生成に失敗したとき
        error = SFERR_NO_MEMORY;
    }
    if (error != SFERR_NO_ERROR) {

        //エラーが発生したときはループを抜ける
        break;
    }
}

// リストに格納された直線を始点の X 座標でソートする
// ※ 挿入ソートアルゴリズムを利用する
if (error == SFERR_NO_ERROR) {

    for (i = 1; i < list.GetSize(); ++i) {

        ithLine = list.Get(i);            // i 番目の直線へのポインタを ithLine に格納する

        etor = list.GetFirstEnumerator(); // リストの列挙子を取得する

        for (j = 0; j < i; ++j) {      // ※ 0 ≦ j < i

            jthLine = etor.GetNext();     // j 番目の直線へのポインタを jthLine に格納する(列挙子は次の要素に進む)

            if (jthLine->GetStartX() > ithLine->GetStartX()) {
                // 直線の始点の X 座標に関して、j 番目の直線が i 番目の直線よりも大きい場合

                // j 番目の直線の前に i 番目の直線を移動する
                list.Remove(i);                  // i 番目の要素を削除する(i 番目の直線そのものは削除されない)
                error = list.Insert(j, ithLine); // j 番目の要素の前に旧 i 番目の直線へのポインタを挿入する

                break;
            }
        }
        if (error != SFERR_NO_ERROR) {

            //エラーが発生したときはループを抜ける
            break;
        }
    }
}

// リストを使用後、要素をクリアする前に必ず直線を削除する
// ※ これを行わないと、メモリリークが発生する
etor = list.GetFirstEnumerator();

while (etor.HasNext()) {

    line = etor.GetNext();
    delete line;
}

// リストをクリアする
list.Clear();

13.8.4. 文字列のカウント

以下のコードは、 ハッシュマップ(SFXLinkedHashMap)を利用して文字列中の単語の出現回数をカウントします。 ハッシュマップのペア要素のキーを単語、値を出現回数として処理しています。

例 13.14. 文字列のカウント

SFXAnsiString string("abc def def def ghi ghi");         // カウント対象の文字列
SFXLinkedHashMap<SFXAnsiString, SInt32> hashmap;         // ハッシュマップ(キー: 単語、値: 出現回数)
SFXAnsiString word;                                      // 切り出した単語
Bool isAlphabet = false;                                 // 英数字を処理中のときは true になる
SInt32 startOfWord, endOfWord;
SInt32 i;

// 末尾にダミーの非アルファベット文字を追加する
string += '.';

for (i = 0; i < string.GetLength(); ++i) {

    // string[i] が英数字であるか判定する
    if (SFXAscii::IsAlphaDigit(string[i])) {

        // 英数字を処理中でないとき
        if (!isAlphabet) { 

            startOfWord = i; // 単語の先頭を設定する
            isAlphabet = true;
        }
    } else {

        // 英数字を処理中のとき
        if (isAlphabet) { 

            endOfWord = i;

            // word の切り出し
            word = string.Substring(startOfWord, endOfWord);

            if (hashmap.ContainsKey(word)) { 

                // word が含まれるとき
                // これまでの出現回数を取得する
                SInt32 count = hashmap.Get(word);
                // 回数を 1 加算する
                hashmap.Set(word, count + 1);
            } else {

                // 初めて出現したので、回数を 1 に設定する
                hashmap.Set(word, 1);
            }
            isAlphabet = false;
        }
    }
}

// 結果をデバッグウィンドウに表示する
TRACE("\"def\": %d, \"ghi\": %d, \"abc\": %d, \"xyz\": %d", hashmap.Get("def"), hashmap.Get("ghi"), hashmap.Get("abc"), hashmap.Get("xyz"));

例 13.15. 実行結果

*dbgprintf*:0 - "def": 3, "ghi": 2, "abc": 1, "xyz": 0