C++入門 AtCoder Programming Guide for beginners (APG4b) 第1章(実践4)

APG4b第1章(実践4) プログラミング

前回の記事でC++入門 AtCoder Programming Guide for beginners(APG4b)第1章の「1.06.if文・比較演算子・論理演算子」~「1.06.ABC問題(A – Good Integer)」まで進みましたので、今回はその続きを進めて行きたいと思います。
まずは以下のサイトへアクセスしてログインしましょう。

AtCoderProgrammingGuideforbeginners(APG4b)トップ画面

引用元:https://atcoder.jp/contests/APG4b

1.07.条件式の結果とbool型

1.07.条件式の結果とbool型

ここのページに書かれている内容については特に補足説明することはありません。
true と false と bool の読み方が書かれていなかったので一応記述すると、true(トゥルー)、false(フォールス)、bool(ブール)です。
C++以外のほとんどのプログラミング言語でも使用するので覚えておきましょう。

EX7 – bool値パズル

EX7 – bool値パズル

この問題は以下の①~③の関連するifごとに整理して考えていく必要があります。

AtCoderProgrammingGuideforbeginners(APG4b)_C++_1.07.EX7解説

まずは12行目 if(a)がtrueなので a = true となり、6行目は bool a = true;となります。

次には19行目 if(!a && b)がfalseで 22行目 else if(!b || c)がtrueとなります。
でa = trueが決定しているので !a = false となり if(!a && b)はbの値に関わらずfalseとなります。
else if(!b || c)はb = false か c = true の少なくともどちらかを満たしていることは分かりますが、それ以上は分からないためではbの値もcの値も決まりません。

最後には26行目 if(a && b && c)がfalse、29行目 else if(true && false)もfalse、32行目 else if(!a || c)がtrueとなります。
29行目 else if(true && false)は意味の無い行なので無視しましょう。
32行目 else if(!a || c)がtrueでにてa = trueは決定しているので !a = falseであり、c = trueとなるので、8行目は bool c = true;となります。
また、26行目 if(a && b && c)がfalseであり、a = true 、 c = true であることから b = falseとなり、7行目は bool b = false;となります。

EX7 – bool値パズル:解答
#include <bits/stdc++.h>
using namespace std;

int main() {
  // 変数a,b,cにtrueまたはfalseを代入してAtCoderと出力されるようにする。
  bool a = true;
  bool b = false;
  bool c = true;

  // ここから先は変更しないこと

  if (a) {
    cout << "At";
  }
  else {
    cout << "Yo";
  }

  if (!a && b) {
    cout << "Bo";
  }
  else if (!b || c) {
    cout << "Co";
  }

  if (a && b && c) {
    cout << "foo!";
  }
  else if (true && false) {
    cout << "yeah!";
  }
  else if (!a || c) {
    cout << "der";
  }

  cout << endl;
}

1.08.変数のスコープ

1.08.変数のスコープ

ここのページに書かれている内容の「ブロック」について補足します。
「1.02.プログラムの書き方とエラー」の中でも説明しましたが、ブロックのインデントの位置を綺麗に揃えることはプログラムの読みやすさ(可読性)を高めるためにとても大切です。
適切な位置にインデントを設定する癖を付けましょう。
また、「EX6 – 電卓をつくろう」の中でも説明しましたが、AtCoderはブロックの範囲についてプログラムの行数を表す数字の右に▼マークが表示されるので、クリックするとブロックを閉じたり開いたり出来ます。複雑なプログラムではブロックをたくさん使用してそれぞれのブロックの範囲が分かりにくくなる時がありますので、分からなくなった時はこの機能を使って確認しましょう。

また、「スコープがある理由」についても補足します。
スコープがある理由として、スコープが分かれていないとプログラムの規模が大きくなった際に同じスコープ内では同じ名前の変数名を使えないので、まだ使われていない変数名を考えるのに手間がかかるためと書かれています。変数なんてプログラムの規模が大きくてもせいぜい数十~数百個なので気をつけていれば大丈夫だろうっと思うかもしれません。しかし、規模が大きいプログラムは通常1人で書くことはせず複数人で分担して書くため、同じような役割をする変数が存在する場合、偶然同じ名前になってしまう可能性がありますが、スコープが分かれていればそのような心配をする必要もありません。

EX8 – たこ焼きセット

1.08.EX8 – たこ焼きセット

この問題はA君が書いたプログラムに誤りがあるので誤りを修正(デバッグ)する問題です。
今回はコードテスト画面にてプログラムがエラーだった際に、どこにエラーの原因があるのか標準エラー出力結果を読み取って探る練習をしてみようと思います。
まずは問題文に記載されているA君のプログラムをコピーしてコードテスト画面にそのまま貼り付けて、標準入力欄に入力例1の値(1 80 5)を入力して実行すると、標準エラー出力として以下の結果が表示されました。

【A君のプログラム】

AtCoderProgrammingGuideforbeginners(APG4b)_C++_1.08.EX6解説1

【実行結果】

AtCoderProgrammingGuideforbeginners(APG4b)_C++_1.08.EX6解説2

標準エラー出力は全て読む必要はなく、たいていの場合は上から2~3行に書かれている部分がエラー原因なので、まずはそこに着目します。

このエラーメッセージを要約すると「Main関数内の24行目左から11文字目 ‘text’という変数がこのスコープでは宣言されていなかった事がエラー原因です。」と書かれています。
改めてA君のプログラムを見てみると’text’という変数は16行目で宣言されているので、この変数は15行目~19行目のパターン2のスコープの範囲内でのみ有効です。
問題文を読むとたこ焼きセットの説明文textはパターン2の時のみ、末尾に「!」を付けてたこ焼き1セット当たりの値段より先に表示する必要があるため、24行目の内容を18行目と19行目の間に入れるように修正しましょう。

【A君のプログラム(修正版)】

AtCoderProgrammingGuideforbeginners(APG4b)_C++_1.08.EX6解説3

この修正したプログラムを再度コードテストで標準入力欄に入力例1を入力して実行すると、今度は以下の標準エラーが表示されました。

【実行結果】

AtCoderProgrammingGuideforbeginners(APG4b)_C++_1.08.EX6解説4

この標準エラー出力も上から2~3行に書かれている部分がエラー原因の可能性が高いので、そこに着目します。

このエラーメッセージを要約すると「Main関数内の25行目左から11文字目 ‘proce’という変数がこのスコープでは宣言されていなかった事がエラー原因です。」と書かれています。
改めてA君のプログラムを見てみると’price’という変数は10行目と17行目で宣言されているので、この変数は9行目~12行目のパターン1のスコープと15行目~20行目のパターン2のスコープの範囲内でのみ有効です。
問題文を読むとたこ焼き1セットあたりの値段(= N × proce )はパターン1とパターン2どちらのパターンでも最終行に表示する必要があるため、7行目で変数’price’の宣言をして10行目と17行目を削除するように修正しましょう。

【A君のプログラム(修正版2)】

AtCoderProgrammingGuideforbeginners(APG4b)_C++_1.08.EX6解説5

この2回目の修正したプログラムを再度コードテストで標準入力欄に入力例1を入力して実行すると、今度は正しい結果が表示されました。

【実行結果】

AtCoderProgrammingGuideforbeginners(APG4b)_C++_1.08.EX6解説6

入力例2と入力例3でも正しい結果が表示されることを確認して、提出しましょう。

EX8 – たこ焼きセット:解答
#include <bits/stdc++.h>
using namespace std;

int main() {
  int p;
  cin >> p;
  int price;
  
  // パターン1
  if (p == 1) {
    cin >> price;
  }

  // パターン2
  if (p == 2) {
    string text;
    cin >> text >> price;
    cout << text << "!" << endl;
  }

  int N;
  cin >> N;

  cout << price * N << endl;
}

以上で1.07と1.08は終わりです。
最後の問題(EX8 – たこ焼きセット)で実践したようにコードテストを実行してエラーが出た時に、標準エラー出力の内容をヒントにエラーの原因を探っていくことは慣れるまで難しいかも知れませんが、プログラミングを一人で進められるようになるために練習してみてください。
ある程度英語が読めないと難しいかもしれませんが、困ったら翻訳サイトなどを使って翻訳してみましょう。
それでは今回はここまでにして、次回は「1.09.複合代入演算子」から続きを進めて行きましょう。
お疲れさまでした。

<<1つ前の記事  1つ後の記事>>

コメント

タイトルとURLをコピーしました