C++ ⇒ VBA 書いて覚えるための初心者自己中記事

C++ ⇒ VBA 勉強の履歴を付けるというかノート代わりに使ってます

C++ ファイル操作 書いて覚えるための初心者自己中記事①

ファイルを扱うのに便利な標準ライブラリ

#include <cstdio>  便利な関数が入っている

#include <fstream> fstreamクラスが入っている

 

 

Xcode 8.3.3 で file.open で作ったはずのファイルがどこにもない・・・

 

 

・・できた。

xcodeでビルドした時にxcode内でいつも結果を見てるから勘違い。

ビルドされたファイルを実行しないとダメなのね。

 

---------------------------------------------------

int main(){

    fstream file; //fstreamクラスのオブジェクト作成

    

    file.open("test.txt",ios::out); //メンバ関数openに渡す引数は ファイル名 フラグ(ios::out はファイルへ書き出すの意味)

    if(! file.is_open()){ //メンバ関数is_open は返り値がbool型でファイルを開けなかったりエラーになったらflase

        cout << "NG" << endl;

        return EXIT_FAILURE;

    }

    

    file << "ファイルに書き込み" << endl; //fstreamオブジェクトのfileに書き込む内容を渡す

    file.close();

}

---------------------------------------------------

ファイルはユーザーの自分のフォルダ内に出来上がりました。

fstreamクラスのオブジェクトを作り、そのオブジェクトでメンバ関数 open(ファイル名,フラグ) を呼び出して test.txt を書き出し目的で開く、とする。

 

同じくメンバ関数の is_open( ) で open関数が成功したかどうかを確認。

失敗ならmain関数を抜けるための EXIT_FAILURE をreturnさせる。

EXIT_FAILUREのFAILUREってどう読むんだ?

 

フェイエルって聞こえる。

 

準備ができたら fstreamクラスのオブジェクト fileに << を使って書き込みたい内容を記述する。

最後にメンバ関数 close で当該ファイルを閉じて終了。

 

実際にはfstreamクラスのデストラクタでファイルは閉じられるそうですが、それ以前に必要なくなったら閉じるのが良いそうです。

 

ちなみにflushはfstreamクラスのメンバ関数にあるらしいので

 ---------------------------------------------------

    file << "ファイルに書き込み";

    file.flush();

 ---------------------------------------------------

こんな感じにも出来るとのこと。

色々書き込んで最後だけ file.flush(); でOK

 

 

 fstreamクラスのメンバ関数open( ) を使った際のフラグについて

ios:out  ファイルへの書き

ios::in   ファイルから読み込み(メモリへの力)

ios::binary  バイナリモードで開く

ios::trunc  ファイルが存在している場合にそれを破棄してから開く

ios::app  常にファイルの末尾に書き出し

ios::ate  ファイルを開いて末尾に移動

 

フラグは複数同時に指定できる。その場合は ,  ではなく | で区切る。

 

 ファイルから入力(読み込み)

---------------------------------------------------

int main(){

    fstream file; //fstreamクラスのオブジェクト作成

    

    file.open("test.txt",ios::in);

    if(! file.is_open()){

        cout << "NG" << endl;

        return EXIT_FAILURE;

    }

    

    string str;

    getline(file,str);

    cout << str << endl;

    file.close();

}

---------------------------------------------------

 

 getline関数でstringクラスのオブジェクトに渡してますね。

以前にgetline関数を習った時に気になってたことがあって

その内容をそのまま下にコピペ

 

=====================================

getline 関数

---------------------------------------------

int main(){

    string str;

    getline(cin,str);

    cout << str << endl;

}

---------------------

(結果)

aaa

aaa

---------------------------------------------

入力から1行を拾ってstringクラスのオブジェクトに入れることができる。

入力から1行を拾って。

入力から1行を拾って・・・?

=====================================

 

ファイルからの読み込みを入力と言ってるじゃないですか。

ってことはファイルからの入力に対して1行だけってことじゃないのかな?

試してみよう。

 

test.txt 

ファイルに書き込み1行目
ファイルに書き込み2行目
ファイルに書き込み3行目

 

を読み込んだら

ファイルに書き込み1行目

 

だけだった。

やっぱりそうなんですね。

疑問解決。

 

戻ります。

このようにファイルから入力されたデータを一時的に保存しているのもメモリですが、特にこの場合はバッファと言います。

今回の場合はstrがバッファらしいです。

今までcin >> 変数 とかやっていた時の 変数 もバッファなんですね。

入力データなので。

 

 

fstreamクラスのメンバ関数open の引数、フラグについて

なんでも ios::in|ios::out で読み書きができると書いていあるので試しても、うまくできない。

具体的には読めてない。書き込みはできる。

出力はできる。

入力ができない。

 

---------------------------------------------------

int main(){

    fstream file; //fstreamクラスのオブジェクト作成

    string str;

    file.open("test.txt",ios::in|ios::out|ios::ate);

    if(! file.is_open()){

        cout << "NG" << endl;

        return EXIT_FAILURE;

    }

    

    getline(file,str);

    cout << str << endl;

    

    file << "もじれつ文字列" << endl;

 

    getline(file,str);

    cout << str << endl;

    file.close();

}

---------------------------------------------------

 結果空白

 

何かを勘違いしているはず・・・

test.txt にはどんどんと文字列が追加されて言ってるんだけどなぁ・・

 

---------------------------------------------------

int main(){

    fstream file; //fstreamクラスのオブジェクト作成

    string str;

    file.open("test.txt",ios::in|ios::out/*|ios::ate*/);

    if(! file.is_open()){

        cout << "NG" << endl;

        return EXIT_FAILURE;

    }

    

    getline(file,str);

    cout << "" << str << endl;

    

    file << "もじれつ文字列" << endl;

    

    getline(file,str);

    cout << "" << str << endl;

    file.close();

}

----------------------------

(結果)

①もじれつ文字列

---------------------------------------------------

test.txt の一行目が空白になってた。

でも②はなんで・・・?

 

ちょっと今は理由がわからない。まだファイル操作始まったばかりだから。うん。

 

 

 

 

ios::binary  バイナリモードで開く について

 ファイル操作の際に行われる入出力は二つのモードのどちらかだ。

テキストモード

バイナリモード

 

デフォルトはテキストモード

ios::binary をフラグにした時だけはバイナリモード

 

違いを説明するために必要な項目は改行コード

改行コードは環境によっていくつかあり

windowsでは \r (13) \n (10)

Macでは   \r (13)

Unix / Linaxでは \n (10)

とバラバラ。

 

テキストモードはこの改行コードを自動で読み替えてくれる。

バイナリモードの場合は一切しない。純粋にメモリの値が入出力される。

 

 

 C++ では10進数・16進数・8進数をそれぞれ表現できる

 

---------------------------------------------------

int main(){

    int n;

    n =  214; //10進数

    n = 0xD6; //16進数

    n = 0326; // 8進数

}

---------------------------------------------------

 どれも数値に違いないので普通に使える。

 

 

 ios::binary 

バイナリデータの

出力 .write ( (const char*)buf  ,  size );   送り側のアドレスとバイト数

入力 read

 

 

---------------------------------------------------

int main(){

    fstream file;

    file.open("binary.txt",ios::out|ios::binary);

    

    if(!file.is_open()){

        return EXIT_FAILURE;

    }

    

    int n = 0x41424344; 

    file.w rite( (const char*)&n,sizeof n);

    file.close();

}

(結果)

DCBA

---------------------------------------------------

fstreamクラスのメンバ変数 writeの引数がなんかすごい。

const char* にキャストするために16進数入れた変数に & つけて、

( const char*)&n なんか琴線に触れた。

 

結果を見ると逆になっている。

これは下の桁から記録されたから?

つまり 0x44 0x43 0x42 0x41 と記憶されているということらしい。

この順番は環境依存なのだそうです。

 

このバイトの順番の違いにも名前があってバイトの順番のことを

バイトオーダー と言います。

そして私の環境だった順番が逆のものをリトルエンディアン

そして順番通りのものをビッグエンディアンと言います。

バイトオーダーはCPUによって変わる。

 

セーブデータ改造ツールとかに書いてあったのはこの事かぁ〜〜

 

 

いままでのfile << "文字列" << endl; 的なのをやると

---------------------------------------------------

int main(){

    fstream file;

    file.open("binary.txt",ios::out|ios::binary);

    

    if(!file.is_open()){

        return EXIT_FAILURE;

    }

    

    int n =  0x41424344 ;

    //file.wri te( (const char*)&n,sizeof n);

    

    file << n;

    file.close();

}

-------------------

(結果)

 1094861636

--------------------------------------------------- 

こうなります。

さっきはメモリのデータをそのままファイルに出力したので .txt ファイルを開くと文字コードとして扱われて DCBA と表示されました。

今回は file << n;

とした為10進数の10バイトの文字列として出力されたそうです。

0x41424344 を10進数で表すと  1094861636 です。

 

 

 入力(読み込み)

 .read( (char*)buf ,size);   引数は受け取り先のアドレスとサイズ

受け取り先のサイズって必要なの?

 ---------------------------------------------------

int main(){

    fstream file;

    file.open("binary.txt",ios::in|ios::binary);

    

    if(!file.is_open()){ 

        return EXIT_FAILURE;

    }

    int n;

    file.read( (char*)&n ,sizeof n); //read関数はコチラ

    

    cout << n << endl;

    file.close();

}

(結果)

1094861636

---------------------------------------------------

とにかくできた。

出力時は16進数でだったけど、10進数で来た。

 

 

 

 

眠い。

 とりあえずここまで。