この記事は先日志望度の高かった企業のコーディングテストにて、まったく本質でない入力の部分で時間の8割を溶かしたため、同じ道を歩む人が出ないようにと願いを込めて執筆した記事です。(検索で出やすいようにキーワードもりもりにしました。)
はじめに
おそらく、競技プログラミング(Atcoder)をやっている方でC++を使用している場合
#include <bits/stdc++.h>
using namespace std;
int main () {
int N;
cin >> N;
vector<long> data(N);
for(int i = 0; i < N; i++)cin >> data.at(i);
return 0;
}
のような入力の受け取り方をしている方が多いと思います。
入力から入力数Nをcinで読み込んで、その後N回cinで読み込むというよくあるやつですね。
何をやらかしたか
コーディングテストでは入力数がわかる入力+入力数がわからない入力が与えられる形式でした。(問題内容は口外禁止なため最大限ぼやかしています。)
そのため
#include <bits/stdc++.h>
using namespace std;
int main () {
int N;
cin >> N;
vector<long> data(N);
for(int i = 0; i < N; i++)cin >> data.at(i);
string line;
while(!cin.eof()){
getline(cin, line);
cout << line << endl;
}
.....
return 0;
}
というふうに、入力から入力数Nをcinで読み込んで、その後N回cinで読み込む、残りのラインを行ごとに読み込んでその後パースし処理を書くという方針を取りました。
.....ただ、入力数が合わず永遠エラーを出し続け時間を溶かしていきました。
何が悪かったか
処理後の入力を調べるとgetlineで読み込まれる最初の行が悪さしていることを突き止めました。
提出したコードは最初の行をcontinueで読み飛ばしましたが、テスト後に調べるとcinで入力し終わった最後の行の改行文字が残っているらしいことがわかりました。
解決法
#include <bits/stdc++.h>
using namespace std;
int main () {
int N;
cin >> N;
vector<long> data(N);
for(int i = 0; i < N; i++)cin >> data.at(i);
string line;
cin.ignore();
while(!cin.eof()){
getline(cin, line);
cout << line << endl;
}
return 0;
}
のように、cinで入力した後に
cin.ignore();
を呼びましょう。これで要らないもの(改行)を捨てられます。
おわりに
この記事で救われる人がいれば幸いです。
(にしてもgetlineでやらかした人結構いるっぽいですね...この記事とか...)