C++ Learning

第7回 確認問題(使ってみる)

STEP 1 で扱った iostream / string / vector / auto / 範囲 for / sort の総合確認クイズです。全 12 問、カテゴリ別に採点されます。選択問題・穴埋め・出力予測が混ざっています。回答すると即座に解説が表示され、上部のスコアバーが伸びていきます。

進め方

スコア 0 / 12 回答済み 0 iostream string vector auto/range-for sort
iostream 入出力(std::cout / std::cin) 0 / 2

Q1 次のコードの出力は?

std::cout << 1 << 2 << 3 << "\n";
1 2 3
6
123
コンパイルエラー
<< は左から順に出力。区切りは入りません。「1 2 3」と空白区切りで出したいなら std::cout << 1 << " " << 2 << " " << 3; と自分で空白を挟む必要があります。

Q2 std::endl の振る舞いとして正しいものは?

"\n" と全く同じ
改行を出力し、かつバッファを flush する
改行を無視してバッファだけ flush する
Windows では \r\n を出す
endl は「改行 + flush」。ループで大量に呼ぶと遅くなるので、通常は "\n" を使い、即時表示が必要な箇所だけ endl を使うのが現代の流儀です。
string std::string 0 / 3

Q3 2 つの string の中身が等しいかを調べる書き方として正しいものは?

strcmp(s1, s2) == 0
s1 == s2
&s1 == &s2
s1.compare(s2) がそのまま bool
std::string== がオーバーロードされているので自然に比較できます。compare() は存在しますが、戻り値は int(-1/0/+1)なので bool として直接使うと 0 でない戻り値で「true」になってしまい意図が逆転します。

Q4 下のコードで pos の値は?

std::string s = "hello world"; auto pos = s.find("xyz");
-1
0
std::string::npos(size_t の最大値)
コンパイルエラー
find の戻り値は符号なし整数 size_t。見つからないときに -1 は返せないので、代わりに std::string::npos(size_t の最大値)が返ります。if (pos == std::string::npos) がイディオム。

Q5 空欄を埋めてください。s の長さを取得する最も推奨される書き方。

auto n = s. ;
答え: size() または length()(どちらも同じ)。string / vector / list など STL の多くのコンテナが size() を持つので、習慣として size() を使うのが無難です。
vector std::vector 0 / 3

Q6 次のコードを実行したあと、v.size()v.capacity() の関係として常に正しいものは?

std::vector<int> v; v.reserve(100); v.push_back(42);
size() == 100, capacity() == 100
size() == 1, capacity() == 1
size() == 1, capacity() ≧ 100
size() == 100, capacity() == 1
reserve は capacity だけを増やし、size は変えません。そのあと 1 回 push_back すれば size は 1 に。capacity は reserve で確保した 100 のまま(push_back の段階では再確保不要)。

Q7 下のコードの出力は?(再確保が起きないと仮定)

std::vector<int> v = {1, 2, 3}; v.push_back(4); v.pop_back(); std::cout << v.size() << " " << v.back();
3 4
3 3
4 4
4 3
push_back で 4 が追加されて {1,2,3,4}、pop_back で末尾を取り除いて {1,2,3} に戻ります。したがって size=3、back()=3。

Q8 空欄を埋めて、要素数 10・全要素 -1 の vector を作ってください。

std::vector<int> v ;
答え: (10, -1)std::vector<int> v(10, -1); で「10 要素、全部 -1」の vector が作れます。第 1 引数が要素数、第 2 引数が初期値。1 引数版 v(10) は「10 要素、全部 0」になります。
auto / range-for auto と範囲 for 0 / 2

Q9 次のループ実行後の v の中身は?

std::vector<int> v = {1, 2, 3}; for (auto x : v) { x += 10; } // v は?
{11, 12, 13}
{1, 2, 3}(変わらない)
{10, 11, 12}
コンパイルエラー
auto x : v は値コピー。x += 10コピーを書き換えているだけで、v 自体は変わりません。書き換えたいなら for (auto& x : v)(参照)にします。「値が更新されない」あるあるの王様。

Q10 次のうち、std::vector<std::string> を読むだけで回すとき最も良い書き方は?

for (auto s : v)
for (auto& s : v)
for (std::string s : v)
for (const auto& s : v)
const auto& ならコピーゼロ(速い)、かつ const で不用意な書き換えも防げる(安全)。string/vector/クラスを読むときの既定の書き方です。小さい型(int など)なら値コピー auto でも構いません。
sort std::sort 0 / 2

Q11 vector を降順に並べるコードとして正しいものは?

std::sort(v.begin(), v.end()); // 自動的に降順
std::sort(v.end(), v.begin()); // 引数を逆に
std::sort(v.begin(), v.end(), [](int a, int b){ return a > b; });
std::reverse_sort(v);
比較関数を第 3 引数に渡します。a > b が真のとき a を左(= 降順)。std::greater<>{} を渡しても同じ効果が得られます。②の begin/end 逆は未定義動作、④のような関数は存在しません。

Q12 空欄を埋めて、vector の最初の 3 要素だけ最小のものを並べるコードを完成させてください(残りは未定順でよい)。

std:: (v.begin(), v.begin()+3, v.end());
答え: partial_sortstd::partial_sort(first, middle, last) は [first, middle) に「もし全体をソートしたとき先頭に来る要素」を入れ、残りは未定順。「トップ K 個だけ欲しい」ケースで sort より速いことがあります。

お疲れさまでした 🎉

0 / 12
次へ: STEP 2 参照