質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2593閲覧

C++ 標準入力でcinの後にgetlineを行うと期待する出力が1行少なくなる

mjk

総合スコア303

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2022/11/29 14:21

編集2022/12/01 06:31

参考情報追記

(BA後に見つけた情報です)
cinとgetlineの併用

cinを使用した後にgetlineを仕様すると、getlineで取得した文字列には何も入っていないということが発生します。
引用テキストその原因は、cinは改行文字の前で入力が終わっているため、現在位置から改行までを読み込むgetlineを使用すると、空の文字列になってしまうからです。
引用テキスト併用したい場合には、以下のようにします。

C++

1int n; 2std::string s; 3 4std::cin >> n; 5std::cin.ignore(); // 次の改行文字まで最大1文字読み捨てる 6 7std::getline(std::cin, s);

質問

標準入力でcinの後にgetlineを行うと期待する出力が1行少なくなってしまいます
正しい方法ではないと思うのですがgetlineを1回余分に行うことで期待する出力は得られました。
getlineを1回余分に行わなくても期待する出力を得る為の方法があれば教えていただきたいです。

実現したいこと

C++

1#include <bits/stdc++.h> 2using namespace std; 3 4int main() { 5 int N; 6 cin >> N; 7 8 for (int i = 0; i < N; i++) { 9 string s; 10 getline(cin, s); 11 cout << s << '\n'; 12 } 13}

input

13 2a b c 3d e f 4x y z 5

output

1//現状の出力 2a b c 3d e f

試したこと

C++

1#include <bits/stdc++.h> 2using namespace std; 3 4int main() { 5 int N; 6 cin >> N; 7 8 //↓この処理をしないと次のforループが1回少ないのは何故? 9 string tmp; 10 getline(cin, tmp); 11 12 for (int i = 0; i < N; i++) { 13 string s; 14 getline(cin, s); 15 cout << s << '\n'; 16 } 17}

output

1//期待する出力 2a b c 3d e f 4x y z

補足情報(FW/ツールのバージョンなど)

Ubuntu 20.04 LTS
WSL2
VSCode 1.73.1
Windows10 19044
C++関連
c++17
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
gdb

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

//現状の出力 a b c d e f

本当にそうですか? 実際のところは

//現状の出力 a b c d e f

だったりしないでしょうか?

cin>>N;で何が起こるかというと、標準入力から順次データを読んでいくわけですが
まず先頭に空白や改行等区切り文字があれば読み飛ばし、
数値があったら順次読んでいって、
数値じゃない文字に出会ったら数値はその前の文字までで終わりなので、文字並びを数値に変換して格納し
数値じゃない文字は標準入力に戻します
なので、
3(改行) という入力に対して cin>>N;とした後は、Nに数値が取り込まれ、標準入力の先頭には改行が居ることになります。

その状態でgetline()したならば、いきなり改行があるので1行分のデータ入力が終わりになります。

getlineを1回余分に行わなくても期待する出力を得る為の方法

入力時に、3の後改行でなく

3 a b c d e f g h i

と入力するのが1案。

getline()を余計にやるのでさえなければいいなら、
char c; //ダミー変数
cin >> c;
cin.get();
として改行を読み取ってしまうのがもう一案。

投稿2022/11/29 14:44

編集2022/11/29 15:50
thkana

総合スコア7652

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mjk

2022/11/29 15:16 編集

>>本当にそうですか? 実際のところは 確かに1行目に空行が出てるようです。 最初にNを出力させておいて空行が出ることが確認できました。 見た感じだと区別がつかないのではっきりとはわからなかったのですが、 ループが1回足りないと思いこんでいました。
thkana

2022/11/29 15:22

あぁ、ちょっと勘違いしてました。C++のstreamあんまり使わないもので。 cin.get()で一文字読み込みなので、こいつに改行コードを喰わせてやれば行けるんじゃないでしょうか。
mjk

2022/11/29 15:27

cin.get(); いけました!ありがとうございます。 後ほどBAさせていただきます。 (回答修正されるならお待ちしてます) 並行して手探りしてて // getchar(); これでもいけるかもしれませんが自信ないです。 あれこれ試してます。
thkana

2022/11/29 15:48

では、回答もさっさと修正しますか... getchar()は一応「Cの世界」用です。なんだったかな、stdio.h(cstdio)とiostreamを混ぜるとなんだか妙な現象が起こるケースがあったような。ちょっと思い出せません。
yumetodo

2022/11/29 16:01

競技プログラミング界隈でよく見るsync_with_stdioを切ったときは動かないでしょうね
mjk

2022/11/29 17:21

回答とコメントありがとうございました。 cin.get()とgetchar()とsync_with_stdioを切ったときなどをあれこれ試してみます。
guest

0

cin >> N;(cin >> N).get(); または
char c; cin >> N >> noskipws >> c >> skipws; にする。
あるいは、string s; getline(cin, s); N = stoi(s); にする。

投稿2022/11/29 15:49

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mjk

2022/11/29 17:24

回答ありがとうございます。 (cin >> N).get();というのも良さそうですね。 他のも試してみます。 先に回答とコメントして頂いた方いたのでそちらへBAさせて頂きました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問