C++のifstreamクラスとistreamクラスについての質問

このQ&Aのポイント
  • C++のifstreamクラスとistreamクラスについて質問があります。
  • ifstreamクラスとfstreamクラスはistreamクラスから派生していると考えています。
  • ifstreamやfstreamのオブジェクトを引数とする入力マニピュレータや関数が問題なく動作する一方、istreamへの参照を引数に取る関数ではコンパイルエラーが発生します。なぜでしょうか?
回答を見る
  • ベストアンサー

ifstreamクラスとistreamクラス

こんにちは。 C++について質問させて下さい。 コンパイラは、Borland C++ Compiler 5.5 を使用しています。 僕は、ifstreamとfstreamクラスは、istreamクラスから派生していると認識しています。 つまり、istream型のポインタや参照は、ifstream型オブジェクトもfstream型オブジェクトも指す事ができるはずです。 その事を確認するために、まず、以下のような内容の入力マニピュレータを作成しました。 ------------------------------------------------------------ istream &alphabet(istream &stream) { char ch; do{ ch=stream.peek(); if(!isalpha(ch)) stream.get(ch); }while(!isalpha(ch) && !stream.eof() ); return stream; } ------------------------------------------------------------ この入力マニピュレータは、 ifstream fin("test.txt"); のようにして作成されたifstream型オブジェクトのfinと、 char str[80]; のようにして作成された文字列変数strに対して、 fin >> alphabet >> str; のように使うと、finに結び付けられたファイルtest.txtの現在位置(getポインタの位置)から、 次にアルファベットが現れるまで、アルファベット以外の文字を捨て去ることで、 アルファベットではじまる単語をstrに格納する事ができます。 また、この入力マニピュレータは、istream型オブジェクトへの参照を受け取るので、 fstream finout("test.txt"); のようにして作成されたfstream型オブジェクトのfinoutに対して、 fin >> alphabet >> str; のように使っても、問題なく動作しました。 つまり、上のマニピュレータの場合は、istream型オブジェクトへの参照を、 引数として受け取るようにしてあるので、istreamクラスから派生している、 ifstreamクラスのオブジェクトや、fstreamクラスのオブジェクトを渡す事ができています。 次に、以下のような内容の、ifstream型オブジェクトへの参照を受け取る関数を作成しました。 void file_to_str(ifstream &file, char *str) { const int size=1000; char temp[size]=""; do{ file.getline(temp, size); strcat(str, temp); if(!file.eof()) strcat(str, "\n"); }while(!file.eof()); } この関数は、 ifstream fin("test.txt"); のようにして作成されたifstream型オブジェクトのfinと、 char str[1000]; のようにして作成された文字列変数strに対して、 file_to_str(fin, str); のように使うと、finに結び付けられたファイルtest.txtの内容を、 文字列変数strに格納する事ができます。 ここで、上の関数のプロトタイプを void file_to_str(ifstream &file, char *str); から void file_to_str(istream &file, char *str); に変更してみると、プログラムをコンパイルした時に、以下のようなエラーが発生します。 ------------------------------------------------------------ C:\Users\kei\work\C++ >bcc32 file_to_str.cpp Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland file_to_str.cpp: Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland Error: 外部シンボル 'file_to_str(std::basic_fstream<char, std::char_traits<char> >&, char *)' が未解決(C:\USERS\KEI\WORK\C++\FILE_TO_STR.OBJ が参照) ------------------------------------------------------------ file_to_str.cppには、上の関数が定義されていて、 そのmain関数の内容は、以下の通りです。 ------------------------------------------------------------ void main(void){ ifstream fin("test.txt"); char str[1000]; file_to_str(fin, str); } ------------------------------------------------------------ コンパイルエラーは、 file_to_str(fin, str); の行で発生しています。 なぜ、入力マニピュレータの時は、仮引数をistream型オブジェクトへの参照にしてもOKだったのに、 関数の場合はコンパイルエラーが発生するのかが分からず、困っています。 理屈的には、何度も言っているように、istreamクラスからfstreamクラスとifstreamクラスが派生しているので、全然問題が無いように思えます。 何か御存じの方がいらっしゃれば、是非、情報を提供して頂きたく思います。 では、よろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.4

#2のお礼に記載のコードを BCC55でコンパイルorリンクを行いましたが質問のような現象には遭遇しませんでしたよ 一部変更/修正が必要でしたが … // ヘッダーファイルの指定を追加 #include <iostream.h> #include <fstream.h> void file_to_str(istream &file, char *str) {   const int size=1000;   char temp[size]="";   do{     file.getline(temp, size);     strcat(str, temp);     if(!file.eof())       strcat(str, "\n");   }while(!file.eof()); } void main(void) {   // fstreamをifstreamに修正   ifstream file("test.txt");   char str[10000]="";   // 変数pをstrに修正   file_to_str(file, str); } といった具合です … >bcc32 BCSTL001-test.cpp Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland BCSTL002-test.cpp: Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

MetalLover
質問者

お礼

御回答ありがとうございます。 何が悪かったのか分かりました。 main関数を含むプログラムでインクルードしている、 ヘッダファイルに記述してあるfile_to_str関数のプロトタイプが、 file_to_str(istream &file, char *str); ではなく、 file_to_str(ifstream &file, char *str); file_to_str(fstream &file, char *str); となって事が原因だったようです。 Tacosanさん、redfox63さん ご協力頂き、ありがとうございました。

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

それら全体を 1つのファイルにして g++ に食わせたら (いくつか修正しなきゃならんけど) コンパイルできました. とはいえ, 「main の内容」が違っていたりするのが謎. もとの質問では ifstream なのに, #2 に対して出てきたプログラムだと fstream になってる. 「プロトタイプを変更したプログラム」の全体は本当にそれであってますか? そして, 本当にエラーメッセージはもとの質問に挙がっている通りですか?

MetalLover
質問者

お礼

Tacosanさん 御返信ありがとうございます。 >「main の内容」が違っていたりするのが謎. もとの質問では ifstream なのに, #2 に対して出てきたプログラムだと fstream になってる. 分かりにくくて申し訳ありません。 #2では、書き換えた方のプログラムを、記載しましたので、 最初の質問フォームに記載したコードは無視してもらっても構いません。 書き換えた方のプログラムで file_to_str(file, p); の部分が間違っているので file_to_str(file, str); に修正しておいてください。 あと、 書き換えた方のプログラムで表示されるエラーは、 Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland file_to_str-test.cpp: Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland Error: 外部シンボル 'file_to_str(std::basic_fstream<char, std::char_traits<char> >&, char *)' が未解決(C:\USERS\KEI\DESKTOP\FILE_TO_STR-TEST.OBJ が参照) です。 >それら全体を 1つのファイルにして g++ に食わせたら (いくつか修正しなきゃならんけど) コンパイルできました. 御手間をお掛けしますが、どのように修正すればよいのか、教えて頂けますでしょうか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

とりあえず「プロトタイプを変更した」あとのプログラムを全部だしてください.

MetalLover
質問者

お礼

御回答ありがとうございます。 プロトタイプを変更した後のプログラムですね。 file_to_str関数とmain関数の両方を、一応記載しておきます。 ----------------------------------------------------------- void file_to_str(istream &file, char *str) { const int size=1000; char temp[size]=""; do{ file.getline(temp, size); strcat(str, temp); if(!file.eof()) strcat(str, "\n"); }while(!file.eof()); } void main(void) { fstream file("test.txt"); char str[10000]=""; file_to_str(file, p); } ----------------------------------------------------------- 何か分かりましたら、よろしくお願い致します。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

コンパイルエラーじゃなくて リンクエラーですよね ということは 引数書き換えたときに 関数名を変更してしまったなんてことありませんか 今あるブロック(file_to_str)をコメントアウトしておいて 関数をもう一度書いてみてはいかがでしょう どこかにケアレスミスがあると思うんですけどね …

MetalLover
質問者

お礼

御回答ありがとうございます。 仰っている内容から考えると、 「僕は、ifstreamとfstreamクラスは、istreamクラスから派生していると認識しています。 つまり、istream型のポインタや参照は、ifstream型オブジェクトもfstream型オブジェクトも指す事ができるはずです。」 という部分は、間違っていないと考えてもいいのでしょうか? あと、file_to_str関数ですが、プロトタイプの第一引数の型を、ifstream&から istream& に変更しただけであり、関数名や、その内容は全く変更していません。

関連するQ&A

  • ifstreamについて

    ifstream でファイルを読み込もうとしているのですが、上手くいきません。 ソース A.cpp #include"A.h" void Broker::read_file(ifstream in) { in >> shikin; } int main(void) { ifstream in; in.open("hoge.txt"); Broker b; b.read_file(in); b.show(); } A.h #include<fstream.h> #include<iostream.h> class Broker{ int shikin; int nensu; double nenri; int tesuryo; public: Broker() { shikin = 0; nensu = 0; nenri = 0.0; tesuryo = 0; } void read_file(ifstream in); void show() {cout << shikin << endl;} }; 以上のようなプログラムなのですが、 コンパイルすると エラー E2247 'ios::basic_ios(const ios &)' はアクセスできない(関数 ifstream::basic_ifstream(ifstream &) ) エラー E2125  コンパイラは 'copy constructor' クラスの istream を作成できない(関数 ifstream::basic_ifstream(ifstream &) ) とのエラーが出てきて実行できません。 コンパイラ C++Builder OS XP なにが原因なのかが分かりません。 本当に初心者な質問ですが、よろしくお願いします。 (何か足りない情報などがありましたら、お手数ですがその掲示板にお願いします)

  • fstream型オブジェクトを関数の仮引数にする

    こんにちは。 現在、C++を使ってプログラミングをしているのですが、fstream型・ifstream型・ofstream型のオブジェクトを、関数の仮引数にするにはどうすればよいのか分からず困っています。 具体的に言いますと、まず、main関数の中で fstream file("test.txt"); のように、fstream型オブジェクトfileを定義しておき、これを以下のような関数に渡して、関数の内部で使いたいのです。 (以下の関数は、ファイルの内容を、1つの文字列変数に格納するためのものです。) ________________________________________________________________________________________________________________________ void file_to_str(fstream file, char *str){ const int size=10000; str=""; //初期化しとかないとダメ。 char temp[size]=""; //初期化しとかないとダメ。 while(!file.eof()){ file.getline(temp, size); //改行に出会うかsize個の文字を読み込むまで、 //文字をバtemp)に読み込む。 strcat(str, temp); if(!file.eof()){ strcat(str, "\n"); //getline()関数は改行をバッファに読み込まない。 } } } ________________________________________________________________________________________________________________________ この関数を、main関数でfstream file("test.txt"); と記述した直後で呼び出した所、以下のようなエラーが出ました。 ________________________________________________________________________________________________________________________ エラー E2247 file_to_str.cpp 48: 'ios::basic_ios(const ios &)' はアクセスできな い(関数 fstream::basic_fstream(fstream &) ) エラー E2247 file_to_str.cpp 48: 'ios::basic_ios(const ios &)' はアクセスできな い(関数 iostream::basic_iostream(iostream &) ) エラー E2125 file_to_str.cpp 48: コンパイラは 'copy constructor' クラスの istrea m を作成できない(関数 iostream::basic_iostream(iostream &) ) エラー E2125 file_to_str.cpp 48: コンパイラは 'copy constructor' クラスの ostrea m を作成できない(関数 iostream::basic_iostream(iostream &) ) ________________________________________________________________________________________________________________________ 何かいい方法を知っておられる方がいらっしゃれば、是非アドバイスを頂きたいと思います。 (「このプログラムの場合は、FILE型ポインタで代用できる。」といった答え以外でお願い致します。) では、よろしくお願い致します。

  • C++のifstreamの使い方

    C++のifstreamの使い方で分からない所があるので、分かる方御教示ください。 下記は、C++で読み込んだファイルの中身が空だった場合を無理やり例外処理を使って書いてみたのですが、中身が存在する場合、たとえば、 line1 line2 line3 ではline1を無限に繰り返してしまいます。(1)を ifstream instream = inStream(argv[1]); while (instream >> input) にするとうまくいくようなのですが、この違いがよくわかりません。 違いを教えてください。 #include <iostream> #include <string> #include <fstream> using namespace std; ifstream inStream(char *str); int main(int argc, char *argv[]) { if (argc < 2) cout << "ファイル名を指定してください" << endl; else { try { string input; while (inStream(argv[1]) >> input) // (1) cout << input << endl; } catch (int i) { cerr << argv[1] << "を開けません" << endl; } } return 0; } ifstream inStream(char *str) { ifstream inStream(str); if (!inStream) throw 1; return inStream; }

  • C++の問題で質問です。

    C++のストリームを用いたファイルの入出力の問題です。 #include<iostream> #include<fstream> using namespace std; int main() { ifstream fin; fin.open("test.txt"); if(!fin){ cout<<"Cannot open the file."<<"\n"; exit(1); } char str1[16]; char str2[16]; fin>>str1>>str2; cout<<"Tow words have been written!"<<"\n"; cout<<str1<<"\n"; cout<<str2<<"\n"; fin.close(); return 0; } このプログラムを実行しようとすると In function 'int main()'; 'exit' was not declared in this scope と表示されてしまいます。 どこが間違っているのでしょうか? わかる方がいらっしゃいましたらお願いします。

  • プログラムの動作

    10文字をスキップするプログラムなのですが、どのようにスキップしているのかわからないので教えてください。 下にソースコードを書きます。 #include <iostream> using namespace std; //10文字をスキップする istream &skipchar(istream &stream) { int i; char c; for(i=0; i<10; i++)stream >> c; return stream; } int main() { char str[80]; cout << "いくつかの文字を入力する:"; cin >> skipchar >> str; cout << str << endl; return 0; } よろしくおねがいします。

  • 修正箇所の指摘のお願い(文字列の書き出し)

    C++についての質問です。 あるテキストファイルを読み込み、行頭の空白文字(スペース)を 削除して、別のテキストファイルへ書き出すプログラムを 作成しています。 下記のようにコーディングを行いましたが、 読み込みファイルの1行目が書き出されず、最終行が2回 書き出される状態となってしまいました。 お手数ですが、修正箇所を教えて頂けないでしょうか。 ************************************************************ #include <iostream> #include <string> #include <fstream> using namespace std; #define INPUT_FILE "C:\\input.txt" #define OUTPUT_FILE "C:\\output.txt" int main() { ifstream fin(INPUT_FILE); ofstream fout(OUTPUT_FILE); char str[255]; if(!fin) { cout << "入力ファイルを開けません\n"; return 1; } if(!fout) { cout << "出力ファイルを作成できません\n"; return 1; } fin.getline(str,254); while(!fin.eof()) { std::cin.setf( std::ios::skipws ); // スペースの読み飛ばし fin >> str; fout << str << std::endl; } fin.close(); fout.close(); return 0; } ************************************************************ よろしくお願いします。

  • C++のstringクラスとファイルの入出力について

    C言語では入出力はfopen,fcloseなど, 文字列の扱いも,char型の配列にfgets…なんとなく使いづらかったので, C++のstringクラスが便利だと聞き,勉強しています。 主にネットで"string 配列 入出力"などで検索しながら探しています。 自分で作成したデータファイル"ex.txt"を読み込み, 用意した配列"data[i]"に代入して,その後色々処理をしたいと思います。 //ex.txt A 2 0 1.0 B 1 2 10.0 C 1 0 100.0 という,"名前 番号1 番号2 数値データ"という4つの情報を"data[i]"に入れ,for文でA~Cまで配列を作りたいです。 後に,名前と番号,数値を切り離して処理したいです。 とりあえず某サイトを見よう見まねで以下のプログラムを書きました。 #include <fstream> #include <string> #include <iostream> using namespace std; int main(){ ifstream ifs( "ex.txt" ); string str; ifs >> str; cout << str << endl; return 0; } Visual C++のコンソールアプリケーションでデバッグなしで実行させると 単に,"A"と一文字しか出力されませんでした。 正直,動作もなにもわからず書いただけです。 C++のstringクラスを用いて,先の"ex.txt"の内容を, ファイルから読み込んで,画面に表示させるプログラムを教えてください。 よろしくお願いします。

  • io error flag を消去したいのですが

    下記プログラムで一度入力がフェイルすると正常に入力動作ができなくなります フラグをリセットする方法を教えてください #include <string> #include <iostream> #include <fstream> using namespace std; void main(void) { char buffer[256]; string str; char c; ifstream ifs; //gomi.txt="123" ifs.open("gomi.txt"); ifs.read(buffer,8); //errorフラグをリセットするためにここに何がいるか教えてください ifs.iostate=0; ifs.seekg(0); for(str="";true;str+=c){ifs.get(c);if(ifs.eof()!=0)break;} cout<<"gomi.txt:"<<str<<endl; }

  • CSVを用いた検索プログラム動かし方

    #pragma warning( disable: 4996 ) #include <stdio.h> #include <string.h> #include <fstream> using namespace std; typedef struct tagKOTOWAZA{ char japanese[50]; char english[50]; }KOTOWAZA; int main() { char buf[256]; KOTOWAZA c[200]; int i, count; /*ifstream strtok strcpy を使ってファイルを読み込む*/ //=====ここから===== ifstream fin("Book1.csv"); if(fin.is_open()){ //ファイル内容の表示とクローズ for(count=0;fin.getline(buf, sizeof(buf)), !fin.eof();count++){//読み込める間 //printf("%s",buf);デバッグ用 char *p; p = strtok(buf,","); if(p)strcpy(c[count].japanese,p); p = strtok(NULL,","); if(p)strcpy(c[count].english,p); } fin.close(); }else{ printf("ファイルのオープンに失敗しました。\n"); return 1; } //=====ここまで==== return 0; } ここからどうすればCSVファイルに書いた 漢字,English を検索できるのかがわかりません・・・ 言語はC++を使っていますvisualstudio2012を使っています。 どうすればいいのか全く分かりません。 よろしくお願いします。

  • ifstream/ofstream について

    こんにちは。 よろしくお願いいたします。 ifstream で定義したファイルを open し、一端 close した後再度 open しようとすると、エラーとなります。 何が原因かわかりますでしょうか? ちなみに、インファイル.txt は何も記載していないので、下記ソースのwhileループ内には入りません。 が、whileループが有ればエラー(メッセージ:3103)が発生し、 無ければ、エラーは発生しません。 環境:XP home & ボーランドC++Builder6.0 テストしたソース: void __fastcall TForm1::Button6Click(TObject *Sender) { ifstream InFile; ofstream OutFile; char cBuf[255]; InFile.open("インファイル.txt"); if (!InFile) ShowMessage("3101"); OutFile.open("アウトファイル.txt"); if (!OutFile) ShowMessage("3002"); while (!InFile.getline(cBuf, sizeof(cBuf)).eof()) { OutFile << cBuf << endl; } // このwhileループが無ければ、エラーは発生しません。 OutFile.close(); InFile.close(); InFile.open("インファイル.txt"); if (!InFile) ShowMessage("3103"); // ここでメッセージが出力されます。 }