こんにちは。
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クラスが派生しているので、全然問題が無いように思えます。
何か御存じの方がいらっしゃれば、是非、情報を提供して頂きたく思います。
では、よろしくお願い致します。
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
御回答ありがとうございます。
何が悪かったのか分かりました。
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さん
ご協力頂き、ありがとうございました。
No.3
- 回答日時:
それら全体を 1つのファイルにして g++ に食わせたら (いくつか修正しなきゃならんけど) コンパイルできました.
とはいえ, 「main の内容」が違っていたりするのが謎. もとの質問では ifstream なのに, #2 に対して出てきたプログラムだと fstream になってる.
「プロトタイプを変更したプログラム」の全体は本当にそれであってますか? そして, 本当にエラーメッセージはもとの質問に挙がっている通りですか?
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++ に食わせたら (いくつか修正しなきゃならんけど) コンパイルできました.
御手間をお掛けしますが、どのように修正すればよいのか、教えて頂けますでしょうか?
No.2
- 回答日時:
とりあえず「プロトタイプを変更した」あとのプログラムを全部だしてください.
御回答ありがとうございます。
プロトタイプを変更した後のプログラムですね。
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);
}
-----------------------------------------------------------
何か分かりましたら、よろしくお願い致します。
No.1
- 回答日時:
コンパイルエラーじゃなくて リンクエラーですよね
ということは 引数書き換えたときに 関数名を変更してしまったなんてことありませんか
今あるブロック(file_to_str)をコメントアウトしておいて
関数をもう一度書いてみてはいかがでしょう
どこかにケアレスミスがあると思うんですけどね …
御回答ありがとうございます。
仰っている内容から考えると、
「僕は、ifstreamとfstreamクラスは、istreamクラスから派生していると認識しています。
つまり、istream型のポインタや参照は、ifstream型オブジェクトもfstream型オブジェクトも指す事ができるはずです。」
という部分は、間違っていないと考えてもいいのでしょうか?
あと、file_to_str関数ですが、プロトタイプの第一引数の型を、ifstream&から
istream& に変更しただけであり、関数名や、その内容は全く変更していません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- その他(プログラミング・Web制作) python OpenPyXLを使って出力結果をエクセルに書き込み 2 2022/06/04 19:46
- その他(プログラミング・Web制作) python flask から fastapiへの移行時のエラー対処 1 2023/02/05 12:26
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
EXCEL VBAにて動的にCheckBOXを...
-
パワーポイントのVBAでテキスト...
-
戻り値がクラスオブジェクト
-
JAVAからHTMLへ値を返す方法
-
Excelで =EMBED("Acrobat Docu...
-
VBA 同じ名前のオブジェクトを...
-
C#でフォームのオブジェクト名...
-
JSPのout.printについて
-
Accessの連結・非連結オブジェ...
-
ワイルドカード<?>と型パラメー...
-
VBAのWindowオブジェクトとWork...
-
時間帯判定をする。
-
オブジェクト名をforループ内で...
-
Rangeオブジェクトを一時的に作...
-
Webアプリケーションのエラーメ...
-
ビジュアルC++でボタンの有...
-
Object型からDouble型へのキャスト
-
オブジェクトと関数の違い
-
FPS,TPSの当たり判定
-
VBAでvlookup関数から、別シー...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
0 == False はいいけど
-
パワーポイントのVBAでテキスト...
-
C#でフォームのオブジェクト名...
-
Excelで =EMBED("Acrobat Docu...
-
VBAのWindowオブジェクトとWork...
-
JAVAからHTMLへ値を返す方法
-
EXCEL VBAにて動的にCheckBOXを...
-
ワイルドカード<?>と型パラメー...
-
COMコンポーネントって何?
-
VBA 同じ名前のオブジェクトを...
-
Object型からDouble型へのキャスト
-
ビジュアルC++でボタンの有...
-
error C2712: オブジェクト ア...
-
オブジェクト名をforループ内で...
-
bmp画像をjpegやpng画像に圧縮...
-
戻り値がクラスオブジェクト
-
Vbで通常使用するプリンターを...
-
時間帯判定をする。
-
Webアプリケーションのエラーメ...
-
LISTBOXの内容が更新されま...
おすすめ情報