dポイントプレゼントキャンペーン実施中!

こんにちは。

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クラスが派生しているので、全然問題が無いように思えます。

何か御存じの方がいらっしゃれば、是非、情報を提供して頂きたく思います。
では、よろしくお願い致します。

A 回答 (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
    • good
    • 0
この回答へのお礼

御回答ありがとうございます。

何が悪かったのか分かりました。
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さん
ご協力頂き、ありがとうございました。

お礼日時:2011/11/14 14:19

それら全体を 1つのファイルにして g++ に食わせたら (いくつか修正しなきゃならんけど) コンパイルできました.



とはいえ, 「main の内容」が違っていたりするのが謎. もとの質問では ifstream なのに, #2 に対して出てきたプログラムだと fstream になってる.

「プロトタイプを変更したプログラム」の全体は本当にそれであってますか? そして, 本当にエラーメッセージはもとの質問に挙がっている通りですか?
    • good
    • 0
この回答へのお礼

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++ に食わせたら (いくつか修正しなきゃならんけど) コンパイルできました.

御手間をお掛けしますが、どのように修正すればよいのか、教えて頂けますでしょうか?

お礼日時:2011/11/14 02:41

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

    • good
    • 0
この回答へのお礼

御回答ありがとうございます。

プロトタイプを変更した後のプログラムですね。
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);
}
-----------------------------------------------------------
何か分かりましたら、よろしくお願い致します。

お礼日時:2011/11/14 00:57

コンパイルエラーじゃなくて リンクエラーですよね



ということは 引数書き換えたときに 関数名を変更してしまったなんてことありませんか

今あるブロック(file_to_str)をコメントアウトしておいて
関数をもう一度書いてみてはいかがでしょう
どこかにケアレスミスがあると思うんですけどね …
    • good
    • 0
この回答へのお礼

御回答ありがとうございます。

仰っている内容から考えると、
「僕は、ifstreamとfstreamクラスは、istreamクラスから派生していると認識しています。
つまり、istream型のポインタや参照は、ifstream型オブジェクトもfstream型オブジェクトも指す事ができるはずです。」
という部分は、間違っていないと考えてもいいのでしょうか?

あと、file_to_str関数ですが、プロトタイプの第一引数の型を、ifstream&から
istream& に変更しただけであり、関数名や、その内容は全く変更していません。

お礼日時:2011/11/14 01:03

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!