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;
}
No.1ベストアンサー
- 回答日時:
ifstream inStream(str);
の行が、何をやっているか、理解してますか?
「strで指定されたファイルをストリームとしてオープンして、ファイルの読み込みポインタを先頭にする」のですよ。
そして
return inStream;
の行で、オープンしたストリームを「ifstream型の変数」として返しています。
なので
while (inStream(argv[1]) >> input)
とやると「毎回、argv[1]で指定されたファイルをオープンして、読み込み位置を1行目にする」ってのを繰り返します。
なので「何回ループしようが、1行目しか返って来ない」のです。
しかも、ストリームをクローズしないまま、何度も再オープンを繰り返しているので、何十回か繰り返した段階で、リソースを使い尽くしてオープンエラーが出る筈です。
ともかく「クローズしないでオープンを何度も繰り返す」ってのは、絶対に駄目です。
オープンしたストリームハンドラは「プログラム終了時に自動的にクローズされる」ので、明示的にクローズしない人が殆どですが、本来であれば「ストリームハンドラを変数に受け取って、最後にクローズするべき」なのです。
#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;
//オープンしていいのは最初の1回だけ!
//ストリームハンドラは変数に受け取る
ifstream instream = inStream(argv[1]);
//受け取った変数でループを回す
while (instream >> input)
cout << input << endl;
}
//終わったらちゃんとクローズ!
instream.close();
//ここから例外処理
catch (int i) {
cerr << argv[1] << "を開けません" << endl;
}
}
return 0;
}
ifstream inStream(char *str) {
ifstream inStream(str);
if (!inStream) throw 1;
return inStream;
}
No.2
- 回答日時:
>ifstream instream = inStream(argv[1]);
>while (instream >> input)
>にするとうまくいくようなのですが、この違いがよくわかりません。
>違いを教えてください。
inStream()の中で「毎回、新規にオープンし直す」ので、結果として「毎回先頭から読み込んでいる」んです。
# 正確には…ローカル変数としてifstreamのインスタンス作成して…でしょうかね。
コードに書かれた通り、正常動作していますよ。
# ただし、オープンしたifstreamを閉じていないので、リソースリークしていると思いますが。
ってか…
>ifstream inStream(char *str) {
>ifstream inStream(str);
だと、再帰で永遠に自分呼び出ししません?(吹っ飛ぶまで)
# いや、ローカル変数名と関数名が同一だからコンパイルエラー?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
【C++】ヘッダ内でstringを格納...
-
空ENTERの判別
-
cygwinでのboost
-
C++でShowCursorを使いたい。
-
vectorのイテレータを大小比較...
-
gccでコンパイル時のエラー
-
VS2019でofstreamが未定義になる
-
string型のフォーマット書式指...
-
c++のvirtual関数および継承に...
-
STLのwstring型から BSTR型 へ...
-
wstringの主力
-
string型の固定長文字列を配列...
-
コンパイルエラー
-
構造体に決められた文字列を入...
-
C++ 平均値、最大値と最小値の...
-
#include "fstream.h"
-
C言語のポインターで詰まっている
-
構文エラーが出ているのですが...
-
2重の(?)の#include
-
C++ iteator const を使ったプ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
switch文のエラーについて
-
構文エラーが出ているのですが...
-
VC++で文字列から任意の文字を...
-
#defineの使い方について
-
空ENTERの判別
-
C++でShowCursorを使いたい。
-
enumの値から定義名を文字列化...
-
C++での <iostream.h>と<iostre...
-
VS2019でofstreamが未定義になる
-
std::wstringのメモリリークに...
-
wstringの主力
-
JPEGやPNGが読めるLoadImage関数
-
なぜ、C++の標準ヘッダをインク...
-
#include "fstream.h"
-
C言語のエラーを修正したい
-
C言語のポインターで詰まっている
-
#define中の#のエスケープ
-
リモートデスクトップの接続元I...
-
CStringとString
-
【C++】複素数で配列を使いたい
おすすめ情報