Up, en

簡単なテキストファイル入出力例

 

テキストファイル入出力サンプルプログラムをC++で作成してみた。

 

#include <iostream>

#include <fstream>

 

using namespace std;

 

int main(){

        cout << "Input File Name = ";

        char nm[100];

        cin >> nm;

        ifstream fin;

        fin.open(nm);

        cout << "Output File Name = ";

        cin >> nm;

        ofstream fout;

        fout.open(nm);

       

        char str[1000];

        while(!fin.fail()){

                char str[1000];

                fin.getline(str, 1000);

                fout << str << endl;

        }

        fin.close();

        fout.close();

 

        return 0;

}

 

上のプログラムを、データファイルData.txtを入力ファイル、Check.txtを出力ファイルとして実行してみる。

Data.txtは、図1のように用意されている。

図1(各行先頭の青字で表示されている1〜10の数字は、エディタ画面における行番号である)

 

プログラムを図2のように実行する。

Screenshot1

図2

 

上の実行例は、openSUSE 13.2 におけるものであるが、openSUSE 13.2 における g++ のインストールの方法を説明したウェブサイトも用意した。

図2の実行例では、ファイルData.txtは、プログラムと同じフォルダに用意されていて、出力ファイルもプログラムと同じフォルダに出力される。プログラムの実行時カレントディレクトリがプログラムソースファイルと同じディレクトリになっている。

図1の入力ファイルに対して、プログラムの実行終了後の出力ファイルは図3のようになっている。

図3

 

上のプログラムにおいて

fin.getline(str, 1000);

fin.getline(str, 5);

に変更した次のプログラムを、図2と同じように実行してみる。

 

#include <iostream>

#include <fstream>

 

using namespace std;

 

int main(){

        cout << "Input File Name = ";

        char nm[100];

        cin >> nm;

        ifstream fin;

        fin.open(nm);

        cout << "Output File Name = ";

        cin >> nm;

        ofstream fout;

        fout.open(nm);

       

        char str[1000];

        fin.getline(str, 5);

        while(!fin.fail()){

                fout << str << endl;

                fin.getline(str, 5);

        }

        fin.close();

        fout.close();

 

        return 0;

}

 

このとき、出力ファイルは図4のようになる。

図4

 

ファイルからの読み込み

fin.getline(str, 5);

において、2番目の引数の値5より1少ない4番目の文字まで読み込まれると、4番目の文字までがstrに設定されて、関数

fin.fail()

の値がtrueに設定されることがわかる。

最初のプログラム例では、

fin.fail()

の値は、ファイルからの読み込み

fin.getline(str, 1000);

の実行において、ファイルの最後の文字列が読み込まれた後、trueに設定されている。このtrueに設定されるタイミングはVisual C++では少し異なるが、別のウェブサイトで説明した。

 

 

テキストファイルから1つずつの値を読み込むサンプルプログラムを、以下のように作成した。

 

#include <iostream>

#include <fstream>

 

using namespace std;

 

int main(){

        cout << "Input File Name = ";

        char nm[100];

        cin >> nm;

        ifstream fin(nm);

        cout << "Output File Name = ";

        cin >> nm;

        ofstream fout(nm);

        int v;

        fin >> v;

        while (!fin.fail()){

                fout << v << endl;

                fin >> v;

        }

        fin.close();

        fout.close();

 

        return 0;

}

 

標準入出力cincoutと同じ使い方である。

図5のデータファイルに対して、

ScreenshotA2

図5

 

図6のように実行すると、

ScreenshotA4

図6

 

図7の出力ファイルを得る。

ScreenshotA3

図7

 

 

空白などで区切られた文字列から、空白で区切られた部分文字列を取り出す

 

図8のファイル

ScreenshotB2

図8

 

を入力ファイルとするとき、空白で区切られた部分文字列を取り出すことを考える。例えば、3行目の文字列「aa   f   gg 」から、「aa」、「f」、「gg」を取り出す。

部分文字列を取り出すプログラム例として次のものを作成した。

 

#include <iostream>

#include <fstream>

#include <sstream>

 

using namespace std;

 

string SeekStr(char * cstr, int pos){

        stringstream strfile(cstr);

        string vs;

        for (int i = 0; i <= pos; i++){

                if (strfile.eof()){

                        vs = "";

                        break;

                }

                else{

                        strfile >> vs;

                        if (i < pos) vs = "";

                }

        }

        return vs;

}

 

int main(){

        cout << "Input File = ";

        char nm[100];

        cin >> nm;

        ifstream fin(nm);

        cout << "Output File = ";

        cin >> nm;

        ofstream fout(nm);

        while (!fin.fail()){

                char vcs[1000];

                fin.getline(vcs, 1000);

                for (int i = 0; i < 10; i++)

                        fout << i << ":<" << SeekStr(vcs, i) << ">  ";

                fout << endl;

        }

 

        return 0;

}

 

関数 string SeekStr(char * cstr, int pos) によって、cstr 内の pos 番目の部分文字列が取り出される。pos の値が大きすぎて該当する部分文字列がないときは、空白文字列が返される。

図8のファイルに対して上のプログラムを図9のように実行する。

ScreenshotB1

図9

 

出力ファイルは図10のようになっている。

ScreenshotB3

図10

 

空白などで区切られた部分文字列が取り出されていることがわかる。

 

 

数値を表す文字列を数値に変換する

 

数値を表す文字列を数値に変換する場合において、Cの関数を用いる方法とC++stringstreamオブジェクトを用いる方法の処理時間の比較を行うプログラムを作成した。

 

#include <iostream>

#include <sstream>

#include <time.h>

#include <stdlib.h>

 

using namespace std;

 

//              Conversion of string to int

int str2i(string str){

        stringstream sstrm(str);

        int iv;

        sstrm >> iv;

        return iv;

}

 

//              Conversion of string to double

double str2d(string str){

        stringstream sstrm(str);

        double dv;

        sstrm >> dv;

        return dv;

}

 

int main(){

        cout << "Start..." << endl;

 

        const int n = 1000000;

 

        string * vstr = new string[n], * vstrd = new string[n];

 

        time_t * t0 = new time_t;

        time(t0);

 

        //

        //                      Set string data

        //

        for (int i = 0; i < n; i++){

                ostringstream sstrm, sstrmd;

                sstrm << i;

                vstr[i] = sstrm.str();

                sstrmd << 0.1 * i;

                vstrd[i] = sstrmd.str();

        }

 

        time_t * t1 = new time_t;

        time(t1);

        double diff_time = difftime(*t1, *t0);

 

        cout << "string values..." << endl;

        for (int i = n - 3; i < n; i++)

                cout << i << ": " << vstr[i] << "   " << vstrd[i] << endl;

        cout << "diff time = " << diff_time << "s  for " << n * 2 << "values" << endl;

 

        //

        //                      Convert string to char*

        //

        char ** cstr = new char*[n], ** cstrd = new char*[n];

        for (int i = 0; i < n; i++){

                cstr[i] = new char[100];

                for (int j = 0; j < vstr[i].length(); j++)

                        cstr[i][j] = vstr[i][j];

                cstr[i][vstr[i].length()] = 0;

 

                cstrd[i] = new char[100];

                for (int j = 0; j < vstrd[i].length(); j++)

                        cstrd[i][j] = vstrd[i][j];

                cstrd[i][vstrd[i].length()] = 0;

        }

        cout << endl << "(char *) values..." << endl;

        for (int i = n - 3; i < n; i++)

                cout << cstr[i] << "   " << cstrd[i] << endl;

       

        //

        //              Convert char* to int or double

        //

        int  * ivalues = new int[n];

        double * dvalues = new double[n];

        char * ept;

        int gn_rep = 20;

        cout << endl << "Conversion by C functions..." << endl;

        time(t0);

        for (int k = 0; k < gn_rep; k++)

                for (int i = 0; i < n; i++){

                        ivalues[i] = atoi(cstr[i]);             //              C function

                        dvalues[i] = strtod(cstrd[i], &ept);    //              C function

                }

        time(t1);

        diff_time = difftime(*t1, *t0);

        cout << "diff time/C = " << diff_time << "s  for atoi and strtod functins." << endl;

        cout << "Converted values..." << endl;

        for (int i = n - 3; i < n; i++)

                cout << ivalues[i] << "   " << dvalues[i] << endl;

 

        //

        //              Convert string to int or double

        //

        cout << endl << "Conversion by stringstream objects..." << endl;

        time(t0);

        for (int k = 0; k < gn_rep; k++)

                for (int i = 0; i < n; i++){

                        ivalues[i] = str2i(vstr[i]);            //              Defined above

                        dvalues[i] = str2d(vstrd[i]);           //              Defined above

                }

        time(t1);

        diff_time = difftime(*t1, *t0);

        cout << "diff time/S = " << diff_time << "s  for stringstream objects." << endl;

        cout << "Converted values..." << endl;

        for (int i = n - 3; i < n; i++)

                cout << ivalues[i] << "   " << dvalues[i] << endl;

 

        cout << endl << "Deleting objects..." << endl;

        delete [] vstr;

        delete [] vstrd;

        delete t0;

        delete t1;

        for (int i = 0; i < n; i++){

                delete [] cstr[i];

                delete [] cstrd[i];

        }

        delete [] cstr;

        delete [] cstrd;

        delete [] ivalues;

        delete [] dvalues;

               

        return 0;

}

 

 

上のプログラムをVM VirtualBox上にインストールしたopenSUSE 13.2において実行すると、図11のようになった。

図11

 

 

Up