C++相談室 part166 (569レス)
前次1-
抽出解除 必死チェッカー(本家) (べ) 自ID レス栞 あぼーん

リロード規制です。10分ほどで解除するので、他のブラウザへ避難してください。
524: デフォルトの名無しさん (ワッチョイ ffa1-BzvG) [sage] 2025/07/06(日) 06:14:16.80 ID:B20RUTJT0(1/9) AAS
質問なのですが
ケースA) std::stringstream ist("A B"); char c1, c2, c3; に対し、ist >> c1; ist >> c2; ist >> c3; とすると
ist >> c2 は正常に読めて、ist >> c3 を実施した時点で!ist.good()かつist.eof() となってgetc()と類似のEOF検知挙動なのですが
(ちなみに読み取った文字は c1='A'、c2='B'。c3の読み取りは行われない

ケースB) std::stringstream ist("A B"); std::string s1, s2, s3; に対し、ist >> s1; ist >> s2; ist >> s3; とすると
ist >> s2 を実施した時点で早々に!ist.good()かつist.eof() となって挙動が相違し
(ちなみに読み取った文字列は s1="A"、s2="B"。s3の読み取りは行われない

ケースC) しかしBの後に空白を追加してstd::stringstream ist("A B "); とすると、
ist >> s2 は正常に読めて、ist >> s3 を実施した時点で!ist.good()かつist.eof() となってgetc()と類似のEOF検知挙動になる
(ちなみに読み取った文字列は s1="A"、s2="B"。s3の読み取りは行われない

となってケースB)とケースC)で共通に使えるような最終要素まで読み取り完了判定ロジックが無く
std::istream神話が崩壊したんだけどこれっておま環?
一体どうすれば……orz
525: デフォルトの名無しさん (ワッチョイ ffa1-BzvG) [sage] 2025/07/06(日) 06:16:00.70 ID:B20RUTJT0(2/9) AAS
確認用サンプルコード:
外部リンク:ideone.com
526: デフォルトの名無しさん (ワッチョイ ffa1-BzvG) [sage] 2025/07/06(日) 06:47:52.68 ID:B20RUTJT0(3/9) AAS
とりま上のコードからフォークしたソースコード
外部リンク:ideone.com

 parse_as_string_with_common_logic(std::istream& is, std::string& s, bool& bErr)
みたいな判定処理にしたらケースB、Cを共通に扱えるような印象
なのですが正しくはどうすればよいかわからん……
530: デフォルトの名無しさん (ワッチョイ ffa1-BzvG) [sage] 2025/07/06(日) 10:56:09.61 ID:B20RUTJT0(4/9) AAS
>>527
527(1): デフォルトの名無しさん (ワッチョイ 17a6-aNVA) [sage] 2025/07/06(日) 07:26:05.90 ID:oIAQiRlj0(1) AAS
一般的な話ならchar以外の>>で一貫した挙動を期待するのに無理がある
期待した文字が来なかったらungetするかどうか?ファイル最後の改行をどうするか?シグナルが来たら?とか色々あるし
ケースBで言えば"B"の後に文字が続いていればs2に含まないといけないのだから内部的にはケースAで言えばc3まで試し済みの状態
EOFフラグを見るのではなく例外で受け取ったほうが確実
だいたいわかりた
 is >> s
ライブラリの「>>」の仕様的にsが任意のクラスで有り得るから、
例えばsが複素数クラスで2つの要素を読み取るブツなのに対し要素を1つだけ読み取れなかった場合、
みたいなのが生じ得るがis.eof()ではそこまで表現できない故にライブラリ側では
char以外の一般のケースについて責任を持たないというと理解すた、
従って、test_parse_as_string_with_common_logic(const char* szInput, bool& bErr)を
charの読み取りによってeof()判定するように直したわ
これならiostreamの正当な使い方だけで構成されておりかつ目的を果たせているはず……
外部リンク:ideone.com
531: デフォルトの名無しさん (ワッチョイ ffa1-BzvG) [sage] 2025/07/06(日) 11:00:55.07 ID:B20RUTJT0(5/9) AAS
>>528
528(1): デフォルトの名無しさん (アウアウウー Sa9b-zcFv) [sage] 2025/07/06(日) 10:18:34.40 ID:RFZXbMVga(1/2) AAS
ケースB、Cを共通に扱える
ist.eof()でいいやん
Bが一回余分にループするのは気持ち悪いけど
気にしたら負け
>Bが一回余分にループするのは気持ち悪いけど
いきなりis >> s してその直後のeof()を当てにするロジックである限り、
リンク先のケースBの挙動となり、最後の要素に引き続く空白文字がないとき
最後の要素が入力ストリームにあるのに受け取れないというもっと深刻な事態となる以下略

>>529
529(2): デフォルトの名無しさん (ワッチョイ 1f7f-Wka8) [sage] 2025/07/06(日) 10:53:22.37 ID:14zTNASB0(1) AAS
普通はoperator bool(または fail())を使う
operator boolはis.good()と同じはず……
なおかつそれ単独では(is >> sのsがchar以外のとき)ケースBの解決になんね
532: デフォルトの名無しさん (ワッチョイ ffa1-BzvG) [sage] 2025/07/06(日) 11:06:26.76 ID:B20RUTJT0(6/9) AAS
ごめoperator boolは!is.fail()やった……orz
533
(1): デフォルトの名無しさん (ワッチョイ ffa1-BzvG) [sage] 2025/07/06(日) 11:24:16.88 ID:B20RUTJT0(7/9) AAS
二転三転してすまんこ考えを改めたはサーセン……orz
入力ストリームはシリアルポートみたいな途中で入力がブチ切れる危険性があるブツである
こともあるから、
 ケースB) (空白) (非空白文字列の期待する全体)
 ケースB') (空白) (非空白文字列が受信タイムアウトにより途中で切れたもの)
の区別が!isになったというだけでは区別がつかない。一方、
(空白) (非空白文字列) (空白)
まで受け取ったら、(非空白文字列) がタイムアウトにより途中で切れたものでないことが確実となりワカル
故に、ケースBやB'みたいな条件を扱うこと自体がライブラリの仕様想定外なのかもしれん……
通常のテキスト読み込みでは行末に改行文字(空白文字のうち)が1文字以上あるから、この枠内で話が収まる。

Unixみたいに改行文字が '\n' 1文字だけな環境で、改行文字を読み飛ばして
呼び出し元に返さないgetline()みたいなやつで読んだ結果を
istringstreamしようとするとケースBが顕在化するが、
この場合は強制的に末尾に空白文字を付けることができうる
そうすればケースBは発生しない(ただし空白文字を付け忘れるとバグ
536: デフォルトの名無しさん (ワッチョイ ffa1-BzvG) [sage] 2025/07/06(日) 12:43:07.86 ID:B20RUTJT0(8/9) AAS
>>529
ゴメ operator std::istream::bool() か std::istream::fail() だけでとりま解決したわスマンカッタorz
外部リンク:ideone.com

オンメモリのストリームである std::istringstream であっても>>533のケースB'に当たるケース
(オンメモリなので非空白文字列でデータが終わっている場合)においてbadbitがセットされるっぽい
この挙動がおま環でないかどうかはわからん……
537: デフォルトの名無しさん (ワッチョイ ffa1-BzvG) [sage] 2025/07/06(日) 12:47:26.46 ID:B20RUTJT0(9/9) AAS
>>534
534(1): デフォルトの名無しさん (ワッチョイ 377c-ZLf6) [sage] 2025/07/06(日) 11:56:43.72 ID:wbQZP2jZ0(1) AAS
iostreamなんかをテキストの厳格なパースなんかに使わなければならない理由から考え直した方がいい
いまさらlex的な処理をgetc()で手で書いたりstrtok()に戻ったりしたくないし……
前次1-
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 0.030s