2つのデータの和と差

  プログラム例 3.1 等と同様のプログラムを C/C++ を利用して書いてみます.C/C++ のプログラムは,関数の集まりと言っても過言ではありません.プログラム例 3.1C に現れる printf や scanf も関数です.関数に関する詳細な説明は,後の章で行いますが,ある面で,数学の関数と非常に似ています.数学の関数は,その関数の中の変数に適当な値を代入すればそのときの関数値が得られます.C/C++ においても,例えば,正弦を計算する関数 sin(x) は,変数 x に適当な値を代入してやれば,その角度における正弦が計算されて返されます.ただし,printf や scanf のように,単に値を返すだけでなく,出力や入力といった複雑な処理を行う関数も多く存在します.

  完全に関数を理解することは,現在の段階では困難であり,また,printf や scanf という関数に対しても,初心者が誤って使用する例が多く見受けられます.そこで,C++ に興味がなくても,もし,C++ のコンパイラが手元にあるようでしたら,しばらくの間,入出力文だけはプログラム例 3.2C の方法を使用するのも良い方法かもしれません.

(プログラム例 3.1C ) 2 つのデータの和と差

01	/****************************/
02	/* 2つのデータの和と差     */
03	/*      coded by Y.Suganuma */
04	/****************************/
05	#include <stdio.h>
06
07	int main()
08	{
09	/*
10			データの入力
11	*/
12		double x, y;
13		printf("2つのデータを入力して下さい ");
14		scanf("%lf %lf", &x, &y);
15	/*
16			和と差の計算
17	*/
18		double wa = x + y;
19		double sa = x - y;
20	/*
21			結果の出力
22	*/
23		printf("和は=%f 差は=%f\n", wa, sa);
24
25		return 0;
26	}
		
1 ~ 4 行目

  プログラム全体に対する注釈です.注釈は,人間がプログラムを読む際,理解しやすくするためのものであり,コンパイラ等によって特別な処理はされません.プログラムを実行するのはコンピュータですが,プログラムを書いたり修正したりするのは人間です.従って,プログラムを書く際に最も注意すべきことは,如何に読み易く,かつ,分かり易いプログラムを書くかという点です.できるだけ多くの注釈を入れておいて下さい.そのことにより,他の人がプログラムを理解しやすくなると共に,プログラム上のエラーも少なくなるはずです.10~12 行目,15~17 行目,及び,20~22 行目も注釈であり,プログラムの該当する部分における処理内容を説明しています.

5 行目

  「#」で始まる文は,プリプロセッサにより処理され,結果がコンパイラに渡されます.#include は,ヘッダファイル stdio.h の取り込みを行います.C/C++ では,関数を多く使用します.例えば,13,14 行目の printf,scanf もシステムが用意した関数です.これらの関数を使用するためには,使用するに先立って,様々な宣言等を行う必要があります.その宣言等を自分で書くのは面倒なため,システムには,使用する関数毎に必要な宣言を記述したファイルが準備されており,それをヘッダファイルと呼びます.関数によってどのようなヘッダファイルを必要とするかは,マニュアル等に書いてありますので,その都度必要なヘッダファイルを記述して下さい.stdio.h は,関数 printf や scanf を使用するために必要なヘッダファイルであり,プログラムを作る場合,この行を常に付加しておいた方が良いと思います.

7 行目

  プログラムの最初であることを表します.8 行目の「{」と 26 行目の「}」に囲まれた部分がプログラムの本体になります.従って,7,8,25,及び,26 行目は,C/C++ のプログラムにとって常に必要となります.

  また,プログラムの本体に当たる 9 行目から 25 行目までは,段落が下げて書かれていますが,これも,プログラムを読みやすくするための一つの手段であり,必ず,このように,段落を下げて書いて下さい(どの程度下げるかは任意ですが,タブを使用する方法が一般的です).

12 行目

  14 行目で使用する変数の型を宣言している型宣言文です.変数 x,及び,y が double 型であることを宣言しています.初期値の指定を行っていませんので,この段階では 2 つの変数の値は未定となります.変数を最初に使用する位置,または,その前の任意の位置で変数の型宣言を行う必要があり,初期化も同時に行うことが可能です.

13 ~ 14,23 行目

  13,14 行目は,2 つのデータを入力するための文です.単に,入力のためだけなら,14 行目の scanf だけで十分ですが,その場合,何のメッセージも出力されずキーボードからの入力待ちになってしまうため,一見コンピュータが止まってしまったように感じます.また,多くの入力を要求するような場合は,scanf だけでは,どの入力を要求しているのかが分かりません.そのため,13 行目の printf が使用されています.

  標準入出力装置(一般的には,キーボードとコンソール)に対して入出力を行う場合,対象とするものは文字列です.キーボードから入力する場合,たとえ数値であっても,2 進数を使用したコンピュータの内部表現ではなく,例えば「123.45」のように,我々が読むことができる文字列として入力します.しかし,数値データを,入力された文字列としてそのまま記憶したならば,演算等を行うことができません.そのため,入力された文字列をコンピュータ内部で使用する表現方法に変換して記憶してやる必要があります.例えば,「123.45」という文字列を数値として扱いたければ,浮動小数点表現に変換して記憶しておく必要があります.もちろん,「123.45」を文字列として内部的に扱いたければ,文字列として記憶しておく必要があります.

  また,コンソールに出力する場合も,メモリ(変数)に記憶されているデータを文字列に変換して出力します.さもなければ,我々は,0 と 1 の並びとして出力される結果を自分自身で解釈しなければなりません.次に示すプログラム例 3.2C のように,C++ における cin や cout を使用する場合は,これらの変換を自動的に行ってくれますが,scnaf や printf を使用する場合,これらの変換方法を指定してやる必要があります.

  例えば,scanf は,以下のようにして使用します(以下の説明において,char 部分に対する説明は,ここでは無視して下さい).
  double d_data;
  int i_data;
  char c_data[10];
  scanf("%lf %d %s", &d_data, &i_data, c_data);			
「"%lf %d %s"」の部分が,入力されたデータをどのように変換するかを指定する部分です.「%」に続く文字列が 3 つありますので,3 つのデータが入力されることを意味します.入力された文字列に対して,「%lf」は double 型の浮動小数点表示に変換して,「%d」は int 型の整数に変換して,また,「%s」は文字列としてそのまま,記憶することを意味しています.これら 3 つの「%」で始まる文字列は,次に続く 3 つのデータに順番に対応していますので,この scanf 関数に対して,例えば,
  3.14 123 abc			
のように入力すると,d_data に「3.14」が double 型に変換され,i_data に「123」が int 型に変換され,また,c_data に文字列「abc」が,記憶されます.各変数に対して,そのアドレスを指定しなければならない(アドレスについては,後の章で説明します.ここでは,変数に「&」記号が付くという程度で理解しておいてください)点に注意してください.

  printf は,scanf とは逆に,記憶されたデータを文字列に変換する操作を行います.例えば,以下のようにして使用します.
  double d_data;
  int i_data;
  char c_data[10];
    ・・・・・
  printf("結果は %f %10.3f %d %5d %s\n", d_data, d_data, i_data, i_data, c_data);			
この結果,まず,「結果は 」という文字列が出力されます.printf においては,「%」で始まる文字列とエスケープシーケンス(後述)以外は,記述された内容がそのまま出力されます.次に,以下の順序で 5 つのデータが出力されます(各データ間には,1 つのスペースが入る).

  1. 「%f」は double 型のデータを固定小数点表現の文字列に変換します( 1.23x10-3 のような表現方法に対応する 1.23e-03 という方法-浮動小数点表現-も存在します).「%」と「f」の間に何も記述しなければ,全体の桁数や小数点以下の桁数がシステムの標準形式に従います.この場合,d_data の内容が,システムの標準形式に従って出力されます.

  2. 最初のデータと変換方法は同じですが,この場合は,出力形式を指定しています.d_data の内容が,小数点以下 3 桁,全体の桁数 10 桁で出力されます(例: △△△-12.345 ).桁数が 10 桁に満たない場合は,左側にスペースが挿入されます.全体の桁数を指定しない場合は,「10」の部分を省略しても構いません.

  3. 「%d」は int 型のデータを文字列に変換します.「%」と「d」の間に何も記述しなければ,システムの標準形式に従って出力されます.この場合,i_data の内容が,システムの標準形式に従って出力されます.

  4. 上の i_data と変換方法は同じですが,この場合は,出力形式を指定しています.i_data の内容が,全体の桁数 5 桁で出力されます(例: △△-12 ).桁数が 5 桁に満たない場合は,左側にスペースが挿入されます.

  5. c_data の内容が文字列として出力されます.なお,1 文字に対する入出力には,「%c」を使用します.

  以上の説明に従うと,13 行目の printf は,入力を促すメッセージを出力するだけです.23 行目では,wa と sa の値を出力しています.23 行目の「"」の中の最後の記号「\n」も 1 文字を表し,そのまま出力されますが,「\」の付いた記号は,エスケープシーケンス(escape sequence)といって,特別な働きをします.例えば,「\n」が出力されると改行が行われます.

  14 行目の scanf では,キーボードから入力された 2 つのデータが変数 x 及び y に代入されます.ここで初めて,2 つの変数の値が確定することになります.この関数では,各変数の前に「&」を付加する必要があることに注意して下さい.

18 ~ 19 行目

  これらの文では,見て明らかなように,和と差の計算をし,結果を変数 wa と sa に代入しています.変数 x,及び,y に対しては,それらの値が参照されているだけですので,14 行目で確定した値がそのまま保たれています.

  一般的に,変数の値が変化する(記憶されている値が破壊される)のは,その変数に対して,代入,または,入力が実行された場合だけです.たとえば,19 行目以降で,変数 sa に対して,
  scanf("%lf", &sa);			
または,
  sa = 20;			
のような文が実行されると,19 行目で代入された値は失われ,新たに入力された値(最初の文),または,代入された値( 2 番目の文,この場合は,20 )が,変数 sa の値として記憶されます.

  このプログラムを実行し,5 と 3 を入力すると,以下のような結果が得られます.
和は=8.000000 差は=2.000000			

(プログラム例 3.2C ) 2 つのデータの和と差(cout,cin)(C++)

  プログラム例 3.1C と全く同じ内容を C++ で使用できる入出力方法を使って書いてみました.初心者は,printf や scanf の使用に際し,特にデータ型の不一致が原因である誤りをよく起こします.そのため,結果が正しく出力されなかったり,場合によっては,プログラム自身を破壊してしまうことも少なくありません.このプログラムの入出力文では,変数の型を考慮せず,単に変数を並べるだけで入出力が行えるようになっています.

  このプログラムは,プログラム例 3.1C と,5 行目のヘッダファイル,及び,13,14,23 行目の入出力文が異なっているだけです.以下に現れるプログラムにおいても,上の箇所だけを修正してやれば,全く同じように実行できるはずです.なお,23 行目の std::endl は,改行を意味し,"\n" または '\n' と記述しても構いません.

  cout,cin,endl の前に付加してある「std::」の意味については,「 C/C++ 言語 」の名前空間に関する説明を参照して下さい.現時点では,形式的に std:: 付加しておいてください.なお,5 行目の後ろに,
using namespace std;		
という行を挿入することによって,std:: を付加せず,単に,cout,cin,endl と記述することも可能です.

01	/****************************/
02	/* 2つのデータの和と差     */
03	/*      coded by Y.Suganuma */
04	/****************************/
05	#include <iostream>
06
07	int main()
08	{
09	/*
10			データの入力
11	*/
12		double x, y;
13		std::cout << "2つのデータを入力して下さい ";
14		std::cin >> x >> y;
15	/*
16			和と差の計算
17	*/
18		double wa = x + y;
19		double sa = x - y;
20	/*
21			結果の出力
22	*/
23		std::cout << "和は=" << wa << " 差は=" << sa << std::endl;
24
25		return 0;
26	}