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

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

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

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

Q&A

解決済

4回答

11131閲覧

for文の1回目でgetlineが無視される

退会済みユーザー

退会済みユーザー

総合スコア0

C++

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

0グッド

0クリップ

投稿2018/01/29 00:58

int n,i;
cin >> n;
string str[n];

for(i=0;i<n;i++)
{
getline(cin,str[i]);
}

この時なぜか1回目つまりiが0の時のループの時getline関数が無視されて
n = 3の時なぜか2回しか実行されません

なぜでしょうか?

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

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

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

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

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

guest

回答4

0

ベストアンサー

iが0の時のループの時getline関数が無視されて

厳密には無視されたのではなく、最初のgetlineでは空文字列(文字数0の文字列)が勝手に入力されて、2回目から文字列を読み取るという状況です。

cin>>では、必要なものを読み取ったら、それ以上の読み取りはしません。
どういうことかというと、最初に数値を入力したとき、改行コードも入力されます。cin >> nでは、数字は読み取りますが、改行コードは残されます。そして、ループに入って最初のgetlineではいきなり改行コードが現れるので、空行(改行のみの行)が入力されたと思って空文字列が設定されます。

読み取り方法の違うものを混在させると問題が起きやすいので、cinを使いたいならcinだけ、getlineを使いたいならgetlineだけにした方が良いと思います。
このケースなら、私なら最初の数字もgetlineで文字列として読み取りstoiで数値に変換、という風にします。

投稿2018/01/29 02:53

catsforepaw

総合スコア5938

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

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

退会済みユーザー

退会済みユーザー

2018/01/29 15:37

ありがとうございます どっちかを使う方が良いのですね 参考になりました 皆さんの回答も大変勉強になりました ありがとうございました
guest

0

一応、改行文字まで読み飛ばすという方法もありますよ。

cpp

1std::cin >> n; 2std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 3std::getline(std::cin, str);

ただ注意すべき点があります。この方法を用いると、そもそもバッファに改行が残っていない場合 (=始めての入力や、前の入力で改行まで読み取っている場合など。たとえば、上のサンプルの一行目をコメントアウトした場合など) に最初の入力が無視されてしまうことです。 (「改行文字が出てくるまでの入力」には「これから入力される文字」を含みますので、最初に改行を入力するまでの新たな入力も捨てられてしまうのです。) そういう意味でも、 catsforepaw さんのおっしゃる通り、統一した方がミスも少なくなると思います。

ところで、 cin の便利な点として、複数の数字でも空白区切りで簡単に取れるという利便性があります。こういう利便性が欲しい場合は、getline() した string を istringstream につっこむと、cin と同様に扱うことができます。C言語で言うところの fgets() + sscanf() の組み合わせになります。

たとえば空白区切りで3つの数字 a, b, c を受け取りたい場合:

cpp

1std::getline(std::cin, str); 2std::istringstream is{str}; 3is >> a >> b >> c;

あくまで入力は改行まで受け取っておいて、その後加工するという方針なので、先の問題は起こりません。

投稿2018/01/29 08:23

Eki

総合スコア429

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

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

0

読み込みバッファーの読み取り位置の競合が起きているからです。

詳しい理由と解決策はこちら。
C++のstd::cinを思い通りに動作させる。

投稿2018/01/29 01:22

Zuishin

総合スコア28656

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

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

Eki

2018/01/29 07:59

参考先のページのコードを試させていただいたところ、参考先に書かれているように空白で途切れることなく、意図された通りに読み込まれました。 https://wandbox.org/permlink/Fnv8B3dSxGvbdDwI だとすると、これは環境依存なのでしょうか...? 個人的には同じストリームに対する読み書きなので、もし参考先の挙動が起こるようならバグのような気がするのですが。
guest

0

理由までは調べてませんが、cinとgetlineを組み合わせると質問のような現象が起きますね。
試しにgetlineを使わずにcinを使うと問題なく動きます。

c

1 for(i = 0; i < n; i++) 2 { 3// getline(cin,str[i]); 4 cin >> str[i]; 5 }

併用する場合、cinのあとにダミーでgetlineを入れておくと問題なく動きます。

c

1 int n,i; 2 cin >> n; 3 string str[n]; 4 string t; // 追加 5 getline(cin, t); // 追加

改行コード周りの処理が異なるのでしょうかね。

投稿2018/01/29 01:17

ttyp03

総合スコア16996

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.53%

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

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

質問する

関連した質問