先生、こんにちは! 今日も今日とて、前回の復習はバッチリです。
前回の記事はこちら↓↓↓
今回もよろしくお願いします!
姫野さんはいつも元気ですね。よろしくお願いします。
バイトの面接も元気のおかげで受かりました。元気だけが取り柄です!
そうでしたか。そんな元気で天才の姫野さんに、今回は「変数」の話をしたいと思います。
変数とは
へんすう……ですか……。何だか数学のほろ苦い思い出が蘇ります……。
プログラミングにおける変数は、数学とは少し違うイメージを持っていただけるとよいかと思います。例えばコンビニのレジのシステム。
コンビニのレジ、週4でいじってます!
(コンビニでバイトしてるんだ……)
コンビニでは、色々なお客さんが色々なものを買いますね。
コンビニでは、色々なお客さんが色々なものを買いますね。
そうですねー。常連さんに10円する棒状のお菓子を3つだけ買ってく人がいます。絶対30円ぴったり出してくれるので楽なんですけど、それも変数なんですか?
1つ10円のお菓子を3つで30円、30円支払ったのでお釣りは0円。
あとは、週2くらいで100円のコーヒーと150円の菓子パンを買う人もいますね。いつも300円払うんですよ。ちゃんとぴったり用意しておけばいいのに。そんなに50円が欲しいんでしょうか?
1杯100円のコーヒーを1杯、1つ150円の菓子パンを1つ。合計250円。300円支払ったので、お釣りは50円。
……ええと、先生、さっきからレジの物真似ですか?
変数の話をしていますよ。レジは様々な品物、数量、価格に対応していますが、それぞれの状況に合わせた会計をするためには、「お菓子1つ10円」「(10円のお菓子を)3つ買う」「30円支払った」「お釣りは0円」「コーヒー1杯100円」「(100円のコーヒーを)1つ買う」「菓子パン1つ150円」「(150円の菓子パンを)1つ買う」「300円支払った」「お釣りは50円」などの細かな情報が必要になります。
確かに。
その細かな情報が変数なのです。
なるほど……!?
身近な例をもう一つ挙げると、お天気アプリがありますね。
今日の東京の天気は晴れです、気温は15度です、みたいなやつですね! わたしも毎日チェックしてます。
日付、場所、天気、気温が変数ですね。姫野さんの挙げた例は、変数と文字を組み合わせて、「【日付の変数】の【場所の変数】の天気は【天気の変数】です。気温は【気温の変数】です」のように表示されています。
言われてみれば。天気も気温も、いつも同じじゃないですもんね。変数のこと、ちょっとだけわかってきたかもしれません。
それでは、話の本題に入っていきましょう。プログラミングにおける変数は、データを入れたり取り出したりする器、箱のようなものです。変数を決めるイメージは、箱の中に入れるデータの種類と箱の名前を決めるイメージです。
変数を決めるということは、データの種類と箱の名前を決めるということ……。
はい。データの種類のことを「型」といいます。
int型の箱には整数を入れるってことですね!
はい。そして「型 変数;」とすることで、変数を作成することができます。これを「変数の宣言」と呼びます。
「わたしこれからこの変数を使います!!」って宣言するってことですかね。へえ……。変数は好きな名前にしていいんですか?
変数の命名にはふつう半角英数字を用います。大文字と小文字は区別されます。数字から始めることはできません。
int nenrei; とか、String namae; みたいな感じですか?
ローマ字ですと少し読みにくいので、ageやnameなど、基本的には英語の名詞を用いた分かりやすい名前を付けるといいでしょう。ただし、英単語があまりにもわかりにくい場合(一般的でない用語など)は、あえてローマ字表記にすることもあります。
英語かあ……。英語も数学とどっこいどっこいだったなあ。変数の名前は2単語以上にしてもいいんですか?
はい。2単語以上にする際は、fullNameやfamilyNameのように、2単語目以降の単語の先頭を大文字にします。
なるほど、読みやすい。単語は小文字スタートにするわけですね。
途中で登場する大文字がラクダのコブに見えることから、この慣習は「キャメルケース」と呼ばれています。
それはおもしろいですね!
あれ? boolean型は文っぽくなってますね……。
boolean型は、「それが○○されたかどうか」「○○済みかどうか」などを表すため、過去分詞や形容詞を用いて変数の命名を行なうこともよくあります。
何か、ひとつずつ宣言するの、結構めんど……大変ですね。
実は、String name, tel, address, email; のように、カンマで区切ることで、複数の同じ型の変数を同時に宣言することができます。複数行に分けて書いても構いません。
それならよかった! 他に注意することってありますか?
同じスコープ(ブロックとも。{から}までの区間)では、型が同じであろうとなかろうと、同じ名前の変数は1つしか作れません。例えば、
int age;
String age;
boolean age;
int age;
のように変数を宣言することはできません。ふつう年齢を真偽型で表すことはありませんが。
int age;
String age;
boolean age;
int age;
のように変数を宣言することはできません。ふつう年齢を真偽型で表すことはありませんが。
真実がいつも1つであるように、同じ変数はいつも1つなんですね!
そ、そうですね……。
代入とは
次は代入について説明します。
だいにゅう……数学でさんざんやらされた記憶が……。
代入には数学と同様に「=」を用います。しかし、プログラミングの代入は、数学とは全く異なります。
そうなんですね! 「A = B」とか言ってるけど、実はAとBは同じではない……みたいな?
その通りです。「A = B」は、「値Bを変数Aに書き込む(すでにデータが存在する場合は上書きする)」と翻訳できます。左から右ではなく、「右から左」です。「A←B」というイメージを持ってくださいね。
代入は右から左……覚えました!
宣言と代入を行なうと、次のようになります。
int age;
age = 30;
System.out.println(age);
実行結果30
boolean isDone;
isDone = true;
System.out.println(isDone);
System.out.println(!isDone);
実行結果true
false
false
String name;
name = "福沢"
System.out.println(name);
実行結果福沢
これって、public static void main(String[] args){ }の中に書くってことで合ってますか?
はい。今後、特に理由がない限りは簡略化して表記することとします。
こっちのほうが見やすいですしね。わかりました!
public static void mainについての記事はこちら↓↓↓
さて、話を変数に戻します。変数を扱う際は、まず変数を宣言したうえで、「=」を用いて任意の値を代入します。変数を宣言しないと代入はできません。
なるほど……。宣言と代入って一緒にできるんですか?
はい。宣言時の代入のことを「初期化」といいます。
int age = 30;
System.out.println(age);
実行結果30
String familyName, givenName;
familyName = "福沢";
givenName = "諭吉";
System.out.println(familyName + givenName);
実行結果福沢諭吉
変数、思ってたより簡単ですね!
では、ここで問題です。以下のプログラムはどのような実行結果になると思いますか?
int age;
age = "30";
age = true;
ええと……。状況としては、まずint型で変数ageを宣言して、そのあとString型やboolean型のものを代入してますよね。つまり、intの種類の箱の中に、intじゃないデータを入れてる。これ、Eclipseでちゃんと実行できるんでしょうか……?
お察しの通りです。原則として、型が異なる場合は変数の代入ができないので、注意しましょう。Eclipseでは「型の不一致」としてエラーが出ます。
わかりました!
では、int型の変数ageに数値を代入したうえで、それらを文字列として表示させるにはどのようにすればよいと思いますか?
そんなことできるんですか?
はい、可能です。まずは以下の実行結果を予想してみましょう。
int age1, age2;
age1 = 30;
age2 = 40;
System.out.println(age1 + "歳と" + age2 + "歳");
それなら簡単です! 「30歳と40歳」ですよね!
実行結果30歳と40歳
この時、age1とage2は文字列扱いされていますね。
確かに! 途中に文字列があると、数値も文字列になるんでした!
その通りです。そのルールを利用すれば、int型の変数ageに数値を代入し、そのうえで文字列として表示させることができます。
途中で文字列を入れる……。前にやった空文字列を使って、
System.out.println(age1 + "" + age2);
でどうでしょうか!
System.out.println(age1 + "" + age2);
でどうでしょうか!
System.out.println(age1 + "" + age2);
実行結果3040
正解です。
やったー!
では、次の話に進みましょう。
どんと来いです!
以下のプログラムの実行結果はどうなると思いますか?
int age;
age = 10;
age = 50;
System.out.println(age);
2回も代入してますね……。どっちを優先すればいいんでしょうか?
いい質問です。変数Aにある数Bを代入した時、それまで変数Aにどんな値が入っていても、変数Aの値はBになります。新しいものに上書きされるのです。
なるほど! ってことは、実行結果は後から代入したほうの「50」ですね!
実行結果50
その通りです。int型のageという器の中には元々10が入っていた。けれど50に上書きされた。新たな代入のイメージは「上書き」です。このことを念頭に置いて、今度は以下のプログラムの実行結果を予想してみましょう。
int a, b;
a = 100;
b = 200;
System.out.println(a + b);
これは文句なしの300です!
そうですね、100+200を計算しました。では、次はどうでしょう?
int a, b;
a = 100;
b = 200;
System.out.println(a + b);
a = 50;
System.out.println(a + b);
1つ目は300でいいとして、2つ目は……。途中でaが50に変わったので、50+200で250でしょうか?
はい。初め変数aには100が代入されていたため、4行目では100+200を計算しました。しかし、5行目で変数aに50が新たに代入されたため、6行目では50+200を計算しました。
ですよね! わたしはまだまだいけますよ!
次はどうでしょうか?
int a, b;
a = 100;
b = 200;
System.out.println(a + b);
a = 50;
System.out.println(a + b);
a = b;
System.out.println(a + b);
300と250と……問題は3つ目ですよね……。「a = b」をどうしたものか。
「a = b」とは、どのような意味でしょうか?
それならわかります。代入は右から左。「bをaに代入します」ですよね。
ということは、何を何に代入しましたか?
bは200だから、200をaに代入したんですね! ってことは、200+200で400でしょうか……?
ご名答。さすがは天才の姫野さんですね。
(先生、もしかして「天才の姫野さん」って言葉、気に入ってる……?)
では、追加でもう1問。
int a, b;
a = 100;
b = 200;
System.out.println(a + b);
a = 50;
System.out.println(a + b);
a = b + 30;
System.out.println(a + b);
実行結果を予想してみてください。
300と250はいい……問題は……「a = b + 30」だ……!
そ、そうですね。
さっきと同じように考えればいいんですよね。代入は右から左。「aにb+30を代入します」だから、aは230になる。ええと、確認なんですけど、bの中身って何か変わりましたか?
非常にいい質問ですね。aには変更が加えられましたが、bの中身には変更が加えられていないことに注意しなければなりません。
読みが当たった! そうすると、230+200を計算すればいいから、答えは430です!
実行結果300
250
430
250
430
やったー! やっぱりわたしって天才!
(今回はそっとしておこう……)
ここまではint型の変数の代入について見てきましたが、String型も少しだけ見ておきましょう。次のプログラムの実行結果はどうなると思いますか?
ここまではint型の変数の代入について見てきましたが、String型も少しだけ見ておきましょう。次のプログラムの実行結果はどうなると思いますか?
String familyName, givenName, fullName;
familyName = "福沢";
givenName = "諭吉";
fullName = familyName + givenName;
System.out.println(familyName + givenName);
System.out.println(fullName);
何かカッコいいプログラムになりましたね!
変数名のご利用は計画的に。
その変数名のおかげで、名字と名前を組み合わせて「福沢諭吉」を表示させたいんだなーっていうのは何となくわかるんですが……。
実行結果福沢諭吉
福沢諭吉
福沢諭吉
実行結果については仰る通りです。なぜそうなるのか考えてみましょう。
まず3つの変数を宣言して、その次にそれぞれ文字列を代入してますよね。で、fullNameにはfamilyNameとgivenNameの文字列結合をした「福沢諭吉」が代入されてます。
その通りです。
代入、結構わかってきました!
自己代入とは
次は「自己代入」の話をしましょう。
じこだいにゅう。
変数を今までと異なる値に上書きせずに、これまでの値を保持したまま何らかの計算をして、これまでの値に変更を加えることです。
んー。なるほどわからん。
例を挙げます。
int a;
a = 100;
a = a + 30;
System.out.println(a);
実行結果130
姫野さん、いかがでしょうか?
「a = a + 30」は「a+30を変数aに代入します」ですね。……あ、だから100+30で130になったんですね! 自己代入、意外と簡単だった。
でもこれ、そんなに使い道あるんでしょうか?
先程、全く別のものに上書きする代入を扱いましたね。僕の体感では、先程の代入よりもこちらの自己代入のほうがプログラミングではよく出てきます。
そうなんですね。例えばどういう時に使えるんでしょう?
コンビニで会計をする時、例えば「コーラ150円」「お弁当600円」「袋3円」の順番でバーコードを読み取るとします。
お弁当とコーラ、買ってく人いますね。わたしはお弁当だったらお茶派です。あと、最後の袋3円、地味に大事です。時々忘れそうになります。
(僕はココナッツミルク派、とは言わないでおこう)
この時、全く別のものに上書きする代入を用いると、合計金額はどうなるでしょう?
この時、全く別のものに上書きする代入を用いると、合計金額はどうなるでしょう?
int total;
total = 150; //コーラ
total = 600; //お弁当
total = 3; //袋
System.out.println(total);
実行結果3
最後に代入したものに上書きするから……え、3円!?
そうです。しかしそれでは困ってしまいますよね。
コーラとお弁当……どこ行った……?
そこで自己代入を用います。自己代入ならば、今までに足した数値が消えないように計算することができるため、コーラ、お弁当、袋の合計をきちんと出せるのです。
なるほど。バーコードが1つずつ商品を読み取ってくイメージで……こんな感じでしょうか?
int total = 0; //最初は合計ゼロ円
total = total + 150;
total = total + 600;
total = total + 3;
System.out.println(total);
実行結果753
実際は商品の情報も変数なのでもう少し複雑になりますが、姫野さんは自己代入を上手に使いこなせていますね。
何といっても天才の姫野さんですからね!
変数の応用
そんな天才の姫野さんに、今回も問題を用意しました。
ひえー、調子に乗ってごめんなさい!
与えられた条件を満たす計算式を正しく出力する問題です。
①はダブルクォーテーションで囲めばいいですよね。②は……あ、計算の優先順位が高い () を使うやつか!
System.out.println("100+200=300です");
System.out.println("100+200=" + (100 + 200) + "です");
実行結果100+200=300です
100+200=300です
100+200=300です
(ドヤァ)
ここまでは前回の復習ですね。③はどうでしょうか? 変数名はa, bとしましょう。
まずは変数を宣言して100と200を代入して……。=の前までは①②と変えずに、=の後ろを変数にして……。
int a, b;
a = 100;
b = 200;
System.out.println("100+200=" + a + b + "です");
実行結果100+200=100200です
あれー?
「a + b」よりも前に文字列があるので、「a + b」の部分が文字列結合になってしまっていますね。この問題を解決するためにはどうすればいいでしょうか?
……あ! さっき②でやったみたいに、() を使うとか?
思いついたら、実行してみましょう。
int a, b;
a = 100;
b = 200;
System.out.println("100+200=" + (a + b) + "です");
実行結果100+200=300です
やった、できましたー!
いい調子です。次は④ですね。なるべく変数だけを用いて「100+200=300です」を表示させます。
③の「100」と「200」を変数に直せばいいのかな? 「+」「=」「です」は文字列だから……。
int a, b;
a = 100;
b = 200;
System.out.println(a + "+" + b + "=" + (a + b) + "です");
実行結果100+200=300です
よし、きたー!
姫野さん、とても筋がいいですね!
今気付いたんですけど、①から④って、初めは文字列だけだったのをちょっとずつ変えて、最終的には変数にしてますね。何か導かれてる感じがします!
とても重要な点に気付きましたね。仰る通り、初めから全て変数で考えるのではなく、出力したいものをまずイメージしてから、各所を変数に置き換えていくのがポイントです。
ってことは、⑤と⑥は④をちょっと変えるだけでよかったりしますか?
思い立ったら、書いて実行です。
はい! まずは⑤の「200-100=100です」から……。
int a, b;
a = 200;
b = 100;
System.out.println(a + "-" + b + "=" + (a - b) + "です");
実行結果200-100=100です
算術演算子の+を-に変えただけなのにちゃんと動いた! すごいですね!
仰る通りです。正しい式を一度作ってしまえば、変数や式を少し書き換えることで、自由自在に計算させたり表示させたりすることが可能なのです。
プログラミングって感じがして楽しいです!
では、⑥はどうでしょうか?
「-10×20=-200です」だから、掛け算にするだけじゃなくて変数もいじらなくちゃ……。
int a, b;
a = -10;
b = 20;
System.out.println(a + "×" + b + "=" + (a * b) + "です");
実行結果-10×20=-200です
素晴らしいです。
今日のわたし、調子よすぎ……? 才能に溢れる自分がいっそ恐ろしい……。
そ、そうですね……。
(予想外に引かれた……)
最後は、実行結果を考える問題です。
boolean a, b;
a = true;
b = false;
System.out.println(a && b);
論理演算の復習も兼ねています。才能に溢れる姫野さんの見解をお聞かせください。
ええと……。「a && b」に変数を代入するとtrue && false になるから、「「true・false」は両方ともtrueですか」になりますよね。実際はそうじゃないから、実行結果はfalseです!
実行結果false
よくできました。int型、String型、boolean型の変数を使いこなしていきましょう。
はい、頑張ります!