#pragma twice

KAB-studio > プログラミング > #pragma twice > 082 Version 5.17 iostream で文字列操作!

#pragma twice 082 Version 5.17 iostream で文字列操作!

前のページへ 表紙・目次へ 次のページへ

 Version 5.17
iostream で文字列操作!

まずはごめんなさい
うおっ、いきなり謝るか
まず、インクルードファイルについて。インクルードファイルって憶えて
る?
憶えてるよん、 Ver 5.09 ( No.074 ) でやったよね
そう、今の FileTestDlg.cpp の最初で

#include "stdafx.h"
#include <fstream>
#include "FileTest.h"
#include "FileTestDlg.h"

ってしたよね
こうすれば、 fstream の機能が使えるんだよね。それが std::ifstream
なんだよね
で、実はここで新しくインクルードしなきゃいけないファイルがあったん
だけど、それを書き忘れてました
情けなー
ホントはこうです

#include "stdafx.h"
#include <fstream>
#include <strstream>
#include "FileTest.h"
#include "FileTestDlg.h"

 strstream っていうのをインクルードすればいいのね
今回紹介する std::istrstream を使うのにこれが必要だから。で、今回
紹介するプログラムにもちょっとミスがあったから

    DWORD dwReadedSize;
    BOOL bRes
        = ReadFile
            ( hFile, chAllLine, 1023
            , &dwReadedSize, NULL );
    if( bRes == 0 && dwReadedSize == 0 )
    {
        TRACE( "ファイルから読みとれませんでした。\n" );
        CloseHandle( hFile );
        return;
    }
// ここまでは前回に解説しました。間違いもない……はず。

    CloseHandle( hFile );

    std::istrstream cStrStrm( chAllLine, dwReadedSize );
    while( !cStrStrm.eof() )
    {
        int i;
        cStrStrm
            >> i;
        if( cStrStrm.fail() )
        {
            TRACE( "整数値じゃないです\n" );
            return;
        }
        char chDest[256]; 
        sprintf( chDest, "%d", i );
        m_cDataLstBox.AddString( chDest );
    }

    return;
// 以下、 iostream のプログラムを取っておきましょう。

 Ver 5.15 ( No.080 ) と見比べると、 CloseHandle( hFile ) 呼ぶ位置
が違うだけ?
そう。 CloseHandle( hFile ) の機能は?
 CreateFile() で開いたファイルを閉じるの
今回紹介するところはもうファイルの操作しなくていいから、その前に
ファイルを閉じちゃって良かったんだよね
つまりそれに気付かなかったと
 API は使い慣れてないからな〜。では今回の解説に入りましょう
ってゆーか、 Ver 5.10 ( No.075 ) の std::ifstream 使ったのとほとん
ど同じだよね
あ、そういえば i を宣言してる場所がばらばらだな〜。まぁこれは今度
解説しよう。そう、 std::ifstream とほとんど同じ
違いは?
 std::ifstream はファイルから読み取るためのクラスだったけど、
std::istrstream は文字配列から読み取るためのクラス
 API 使う例だからって、なんかこういう使い方って変くない?
ま、統一されてないのは変だけどね。でもこういう柔軟な使い方できるの
は重要だよ。関数やクラスは〈道具〉として使いこなせなきゃいけないから

まーそれはそうだけど
さて、まず std::istrstream 型の変数を作ります
あれ、でもなんか書き方ちょっと違うね。変数作ってるのに、なんか関数
呼んでる見たい
これはコンストラクタっていう、クラスが使える機能のひとつ。クラスは
こんなふうに〈変数を作るときに関数を呼び出す〉ことができるんです
変数を作るときに関数を呼びだすぅ!? はー、器用なことができるの
ねー
でも感覚的には int i = 0; みたくするのと同じ
よーするに初期化ね
そういうこと。ま、今はこういう使い方ができるくらいでいいから。ちな
みに、これは〈変数を作るとき〉に呼び出される関数だけど、〈変数がなく
なるとき〉に呼ばれる関数もあります
あーっ、勝手にファイル閉じてくれるってヤツだ!
そう、ファイルを閉じたりする後処理をしてくれるのが、デストラクタっ
ていう、変数がなくなるときに呼ばれる関数
なんかクラスって便利。だからランタイムや API とかよりも iostream 
や MFC 使った方が楽なのね
そういうことになるかな。ま、今は使う段階だから楽だけど、作る段階に
なったら
大変なのね……
で、 cStrStrm を作るときにコンストラクタを呼び出して cStrStrm の中
身を初期化します
第1引数の chAllLine はファイル全体が入ってる文字配列よね。これが
ファイルの代わりになるんだ
 dwReadedSize は ReadFile() から受け取った〈実際に読み取った文字列
のサイズ〉。ってことは?
ってことは、 chAllLine の中に入ってる文字列のサイズってことね
この第2引数で cStrStrm のサイズを指定します。こうすればこれ以上は
み出ないから
こーゆーことしなきゃいけないんだ
はみ出てるかどうかは次の std::istrstream::eof() で分かります
ってゆーか、こっから先は std::ifstream とまったくって言っていいほ
ど同じよね
 iostream のメリットはそこだね。同じ系統のクラスなら同じ使い方でい
いっていうのが分かりやすいでしょ
まーこれだけ見れば分かりやすいかなー
またそーゆーこと言う。さて、ここまでで iostream 、ランタイム、 MFC
そして API でファイル処理をしてきたわけだけど、どう?
ってゆーかさ、ファイル操作そのものってどれも同じじゃん、開いて読み
込んでそして閉じるってゆー
うんうん
それよりも文字列操作の方がめんどかった
うん、僕も面倒だった
はぁ?
 iostream には〈書式化機能〉、つまり整数値や文字列への変換機能も付
いてるわけでしょ
そうそう、でもランタイムと MFC は1行ずつ読み込んで整数値に変えてっ
てめんどくさくて、 API なんてファイル全体を読み込むハメに……
どうしてもローレベルのライブラリほど、便利な機能が省かれてる傾向に
あるからね
ローレベルって低レベルってこと?
いや、そういう意味じゃなくて、低層レベルって言った方がいいのかな、
前に〈 API は OS やハードウェア寄りのライブラリ〉って言ったでしょ
言ってた言ってた。そういう意味での低層?
そう、細かい部分を操作できる意味でね。 iostream はいろんな機能が付
いているぶん、そういう細かいことはできないんだよね
やっぱ便利よねー
しかーし!!
しかぁし?
 iostream も MFC も、 ランタイムだって〈低層に高層が重なっている〉
のには変わらないんだよね
どゆこと?
では、 CFileTestDlg::OnBtnShow() を元に戻しましょう

void CFileTestDlg::OnBtnShow() 
{
    int i;
    std::ifstream cIFStrm;
    cIFStrm.open( "Data.txt" );   // ここにブレークポイント
    if( cIFStrm.fail() )
    {
        TRACE( "ファイルがない!\n" );
        return;
    }

    while( !cIFStrm.eof() )
    {
        cIFStrm
            >> i;
        if( cIFStrm.fail() )
        {
            TRACE( "整数値じゃないです\n" );
            return;
        }
        char chDest[256]; 
        sprintf( chDest, "%d", i );
        m_cDataLstBox.AddString( chDest );
    }
}

あ、元の std::ifstream 使ったのだ
〈ここにブレークポイント〉ってとこにブレークポイント設置して
クリックして手のひらマーク押して実行して【参照】ボタン! 止まった
よ、メモリ見るの?
ううん、今回は std::ifstream::open() の中に入ってみます
へ?
ステップイン……っと、【中カッコに入る】ボタン押して
それステップインっつーのね。ほい入った。あ、 Fstream ってファイル
の中みたい
そのファイルインクルードしたでしょ
あ、そういえば
このファイルに std::ifstream::open() の中身があるってことだね。さ
らに入って
ほいっと。ん? 同じファイルの違う場所かな
ステップイン2回して
ほいほい、 Fiopen ってファイルに来たね
ステップイン4回でストップ
ほいほいほいほい、ってなんも変わんないけど
その行って

    if (valid[n] == 0 || (fp = fopen(name, mods[n])) == 0)

ってなってない?
うんなってる……あれ、もしかしてこの fopen() って……
というわけで続く!

/*
    Preview Next Story!
*/
 iostream の中にランタイム!?
こういうふうに、ライブラリの中には驚きがいっぱい
って、なんか水希ちゃんアヤシイ感じ
あ、怪しい!?
アヤシイアヤシイ!!
というわけで次回
< Version 5.18 すべての道は API に通ず! >
につづく!
でもなんかドキドキしてるでしょ
うん、なんか冒険してる感じ
ふっふっふー
……ヤな目ぇ
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。