第2章:演算と型
はじめに
もしも「身長と体重を教えてください。」と尋ねられて、「身長は175cmで体重は62kgです。」と答えたとする。しかし、それは嘘(?)である。身長が175cmピッタリということは、まずあり得ない。身長計で計って、175.3cmであったとしても、これも本当の値ではないだろう。真の値は、おそらく175.2869758…cmといった値のはずである(しかも時間の経過とともに刻一刻と変化するだろう)。
でも、通常は「身長は175cmで体重は62kgです。」で十分である。誰も真に正確な値を知る必要がないのだから。
プログラムの世界でも同じである。現実の値を必ずしも正確に表す必要はない。
この章では、C言語で数値を扱うために最低限の知識といえる、演算と型の基本について学習する。
2-1 演算
加算を行う+や、乗算を行う*などの記号は、演算子と呼ばれる。本節では、基本的な演算子を学習していく。
演算子とオペランド
前章では、加算と減算と乗算を行った。今度は、除算(割り算)もやってみる。
二つの整数値を読み込んで、その和・差・積・商・剰余を表示する。
プログラムをList 2-1に示す。
// 二つの整数値の和・差・積・商・剰余を表示
#include <stdio.h>
int main(void)
{
int x, y;
puts("二つの整数を入力せよ。");
printf("整数x:"); scanf("%d", &x);
printf("整数y:"); scanf("%d", &y);
printf("x + y = %d\n", x + y); // 和
printf("x - y = %d\n", x - y); // 差
printf("x * y = %d\n", x * y); // 積
printf("x / y = %d\n", x / y); // 商
printf("x %% y = %d\n", x % y); // 剰余
return 0;
}
実行例
注意
書式文字列内に%を2個並べると1個の%が表示される
演算を行う+や*などの記号は演算子(operator)と呼ばれ、演算の対象となる変数や定数はオペランド(operand)と呼ばれる(Fig.2-1)。
たとえば、和を求めるx + yでは、演算子は+で、そのオペランドがxとyである。
各オペランドは、次のように呼ばれる。 - 左側のオペランド:第1オペランド/左オペランド - 右側のオペランド:第2オペランド/右オペランド
Fig.2-1 演算子とオペランド
C言語には数多くの演算子がある。全演算子の一覧表はp.221に示している。
なお、本プログラムでのx - yは、xからyを減じた値を求めるものであり、必ずしも差を求めるわけではない(xよりもyのほうが大きければ、x - yは負の値となる)。差を求めるプログラムは、次章のList 3-16(p.59)で学習する。
乗除演算子と加減演算子
本プログラムで使った5個の演算子は、Table 2-1の乗除演算子(multiplicative operator)とTable 2-2の加減演算子(additive operator)とに大別される。
Table 2-1 乗除演算子
演算子 | 記法 | 説明 |
---|---|---|
2項*演算子 | a * b | aとbの積。 |
/演算子 | a / b | aをbで割った商(整数どうしの場合は小数点以下は切捨て)。 |
%演算子 | a % b | aをbで割った剰余(aとbは整数でなければならない)。 |
Table 2-2 加減演算子
演算子 | 記法 | 説明 |
---|---|---|
2項+演算子 | a + b | aとbの和。 |
2項-演算子 | a - b | aからbを引いた値。 |
除算の商と剰余
除算を行う演算子は、2種類ある。
- /演算子 ... 商を求める
商を求めるのが/演算子である。整数どうしを対象とした
整数 / 整数 商の整数部
では、商の整数部(小数部は切捨て)が得られる。たとえば、5 / 3は1で、3 / 5は0である。
- %演算子 ... 剰余(あまり)を求める
剰余を求めるのが%演算子であり、オペランドは両方とも整数でなければならない。
整数 % 整数 剰余
では、剰余が整数として得られる。たとえば、5 % 3は2で、3 % 5は3である。
これら二つの演算子については、次ページのColumn 2-1で学習する。
printf関数での%文字の表示
剰余の表示を行う箇所では、書式文字列中に%%と書かれている。
書式文字列中の文字%は、変換指定の開始文字である。そのため、書式指定を行うのではなく、本当に%と表示したい場合は、%%と表記することになっている。
書式指定の機能をもたないputs関数による表示では、%%としてはいけない(%%と表示されてしまう:"chap02/percent.c")。
最下位桁の値を求める
剰余を求める%演算子をうまく使って、次の問題を解いてみる。
読み込んだ整数値の最下位桁の数字を表示する。
プログラムをList 2-2に示す。
// 読み込んだ整数値の最下位桁の数字を表示
#include <stdio.h>
int main(void)
{
int no;
printf("整数を入力せよ:");
scanf("%d", &no); // 整数値を読み込む
printf("最下位桁は%dです。\n", no % 10);
return 0;
}
実行例
整数値noの最下位桁を、noを10で割った剰余として求めている。
演習2-1
右に示すように、二つの整数値を読み込んで、前者の値が後者の何%であるかを表示するプログラムを作成せよ。
Column 2-1 除算の演算結果
第2版以降の標準Cでは、除算を行う二つの演算子の演算結果は、次のように定義されている。
/演算子 ... 代数的な商から小数部を切り捨てた値。 %演算子 ... (a / b) * b + a % bがaと等しくなる値。
この定義を読むだけでは、特にオペランドが負の場合の結果は把握しづらいかもしれない。 Table 2C-1に、オペランドの符号ごとの具体例を示しているので、この表を参考にするとよい。
Table 2C-1 除算の演算結果の一例
x / y | x % y | |
---|---|---|
正 ÷ 正 | 例:x = 22でy = 5 | 4 |
負 ÷ 負 | 例:x = -22でy = -5 | 4 |
正 ÷ 負 | 例:x = 22でy = -5 | -4 |
負 ÷ 正 | 例:x = -22でy = 5 | -4 |
注意
第2オペランドが0の場合、両演算子の挙動がどうなるのかは、言語では定義されていない(多くの場合、プログラムの実行が中断する)。
複数の変換指定
次は、二つの整数値を読み込んで、商と剰余を表示するList 2-3を理解してみよう。
// 二つの整数値を読み込んで商と剰余を表示
#include <stdio.h>
int main(void)
{
int a, b;
puts("二つの整数を入力せよ。");
printf("整数a:"); scanf("%d", &a);
printf("整数b:"); scanf("%d", &b);
printf("aをbで割ると%dあまり%dです。\n", a / b, a % b);
return 0;
}
実行例
演算結果を表示する書式文字列に、変換指定%dが2個置かれている。Fig.2-2に示すように、先頭側から順に、第2実引数と第3実引数に対応する。
Fig.2-2 printf関数で二つの値を書式化して表示
Note
もちろん、実引数と一対一で対応するのであれば、変換指定は3個以上あっても構わない。
なお、scanf関数による読込みでも、変換指定を2個以上置くことができる。
Tip
たとえば、本プログラムを次のように変更すると、変数aとbへの整数値の読込みを一度に指示できる("chap02/list203a.c")。
入力時は、二つの整数の区切りとして、スペース、タブ、改行のいずれかを入れる必要がある。演習2-2
右に示すように、二つの整数値を読み込んで、その和と積を表示するプログラムを作成せよ。
単項の算術演算子
次の問題を考えてみよう。
読み込んだ整数値と、その符号を反転した値を表示する。
たとえば、7と入力されたら7と-7を表示して、-6と入力されたら-6と6を表示する。そのプログラムがList 2-4である。
// 読み込んだ整数値の符号を反転した値を表示
#include <stdio.h>
int main(void)
{
int num;
printf("整数を入力せよ:");
scanf("%d", &num); // 整数値を読み込む
printf("%dの符号を反転した値は%dです。\n", +num, -num); // 単項演算子
return 0;
}
実行例
これまで利用してきた演算子のオペランドは2個であった。そのような演算子は、2項演算子(binary operator)と呼ばれる(Fig.2-3)。
その他に、オペランドを1個だけ必要とする単項演算子(unary operator)と、3個のオペランドを必要とする3項演算子(ternary operator)がある。
Fig.2-3 2項演算子と単項演算子
本プログラムで使っているのは、Table 2-3に示す単項+演算子(unary + operator)と単項-演算子(unary - operator)である。
Table 2-3 単項+演算子と単項-演算子
演算子 | 記法 | 説明 |
---|---|---|
単項+演算子 | +a | aの値。 |
単項-演算子 | -a | aの符号を反転した値。 |
Note
演算子+と-は、いずれも、2項版と単項版の2種類があることが分かった。
Tip
単項+演算子は、実質的には演算を行わない。そのため、プログラム水色部分の+numから+を取り除いて、単なるnumとしても動作は同じである("chap02/list204a.c")。
もう一つの単項-演算子は、オペランドの符号を反転した値を生成する。
なお、単項+演算子、単項-演算子、!演算子(p.77)、~演算子(p.202)の四つの演算子の総称が、単項算術演算子(unary arithmetic operator)である。
代入演算子
これまでのいくつかのプログラムでは、Table 2-4の単純代入演算子(simple assignment operator)と呼ばれる=演算子を利用した。
演算子の名称が長いため、一般には、代入演算子と呼ばれる。
オペランドが2個であるから、代入演算子は、2項演算子である。
Table 2-4 単純代入演算子
演算子 | 記法 | 説明 |
---|---|---|
単純代入演算子 | a = b | bをaに代入。 |
式と代入式
変数や定数、さらに、それらを演算子で結合したものを、式(expression)と呼ぶ。
Example
たとえば、
x + 32 加算を行う式
では、x、32、x + 32 のいずれもが式とみなせる。また、
a = b - 5 代入式
では、a、b、5、b - 5、a = b - 5 のいずれもが式とみなせる。
代入演算子=に着目すると、aが左オペランドであって、b - 5が右オペランドである。
一般に、○○演算子を用いた式のことを、○○式と呼ぶ。そのため、代入演算子を用いた式は、代入式(assignment expression)と呼ばれる。
式文
既に学習したように、原則として、文の末尾はセミコロン;である。そのため、先ほど示した代入式は、次の形となって、初めて正しい文となる。
a = b - 5; 式文(式の後ろにセミコロン)
このように、式の後ろにセミコロン;を置いた文は、式文(expression statement)と呼ばれる。
式文に関しては、第4章(p.101)でより詳しく学習する。なお、次章以降では、if文やwhile文など、いろいろな種類の文を学習していく。
2-2 型
これまで利用してきたint型は、整数だけを取り扱う型であった。int型以外にも多くの型が提供される。本節では、実数を取り扱うdouble型や演算と型の関係などを学習する。
整数型と浮動小数点型
次の問題を考えてみよう。
二つの整数値を読み込んで、その平均値を求める。
そのプログラムをList 2-5に示す。
// 二つの整数値を読み込んで平均値を表示
#include <stdio.h>
int main(void)
{
int a, b;
puts("二つの整数を入力せよ。");
printf("整数a:"); scanf("%d", &a);
printf("整数b:"); scanf("%d", &b);
printf("それらの平均は%dです。\n", (a + b) / 2);
return 0;
}
実行例
式a + bを囲む()は、演算を優先的に行うために置かれた記号である(Fig.2-4 a)。
もし、図bのように、a + b / 2となっていれば、『a』と『b / 2』の和が求められる。日常の計算と同じで、加減算よりも、乗除算のほうが優先されるからである。
Fig.2-4 ()による演算順序の変更
すべての演算子と、その優先順位は、Table 7-13(p.221)にまとめている。
プログラムを実行して41と44を入力すると、平均値は42.5ではなく42と表示される。
Note
小数部が切り捨てられるのは、整数しか扱えないintという型(type)の性質である。
C言語では、実数を浮動小数点数(floating point number)という形式で表す。その型には3種類あるが、本節で学習するのは、double型である。まずは、整数のint型と浮動小数点数のdouble型との違いをList 2-6のプログラムで確認してみよう。
// 整数と浮動小数点数
#include <stdio.h>
int main(void)
{
int n; // 整数
double x; // 浮動小数点数
n = 9.99;
x = 9.99;
printf("int 型変数 nの値:%d\n", n); // 9
printf(" n / 2:%d\n", n / 2); // 9 / 2
printf("double型変数 xの値:%f\n", x); // 9.99
printf(" x /2.0:%f\n", x / 2.0); // 9.99 / 2.0
return 0;
}
実行結果
最初にint型の変数nと、double型の変数xを宣言して、それから両方の変数に9.99を代入している。同じように見える代入も、まったく違った働きをする(Fig.2-5)。
Fig.2-5 整数と浮動小数点数
- int型変数nに対する代入
!!! note int型変数に実数値を代入する際は、小数部が切り捨てられる。そのため、nに格納される値は9である。
もちろん、n / 2すなわち9 / 2は、『整数 / 整数』という整数どうしの演算であるから、その結果も小数部が切り捨てられた4となる。
- double型変数xに対する代入
!!! note double型の変数xは実数値を表現できるので、格納される値は9.99である。
それを2.0で割るx / 2.0の演算結果は4.995となる。
Tip
なお、printf関数でdouble型の値を表示するための変換指定は、%dではなく%fである。
変換指定%fのfは、浮動小数点floatingの頭文字である。小数点以下の部分が6桁表示されるが、この桁数は変更できる(p.38で学習する)。
型とオブジェクト
型と変数について、学習を進めていこう。Fig.2-6をご覧いただきたい。
Fig.2-6 型とオブジェクト
この図では、int型とdouble型を点線の箱で表し、それらの型をもつ変数nと変数xを実線の箱で表している(変数の箱の大きさは、型の箱と同じである)。
int型の変数は、整数のみを表現でき、double型変数は、小数部をもつ実数値を表現できることは既に確認した。実は、表現できる値の範囲も型に依存する。たとえば、int型で確実に表現できる値は、-32767から32767までである(p.188)。
このように、各型には固有の性質がある。その性質をそっくり受け継いで作られた変数を表す専門用語が、オブジェクト(object)である。
重要
型は、その諸性質を内に秘めた設計図であり、オブジェクト(変数)は、設計図である型をもとに作られた実体である。
Example
たとえると、型はタコ焼きの力タで、カタから作られた本物のタコ焼きがオブジェクトである。
なお、オブジェクトよりも変数のほうが、一般的であって柔らかい感じである。本書では、厳密さが要求されない文脈では、オブジェクトではなく、変数という用語を使っていく。
型と定数
変数だけでなく、プログラムに埋め込まれた定数にも型がある(Fig.2-7)。
Fig.2-7 定数と型
-
整数定数(integer constant) 5や37などである。基本的にint型となる。
-
浮動小数点定数(floating constant) 3.14や2.0などである。基本的にdouble型となる。
定数の型は、値の大きさや特別な指示によって、変わる。
詳細は第7章で学習する。
double型の演算
本章の冒頭で作ったList 2-1は、二つの整数値の加減乗除の結果を求めるプログラムであった。これを実数値に書きかえたのが、List 2-7のプログラムである。
// 二つの実数値の和・差・積・商を実数で表示
#include <stdio.h>
int main(void)
{
double x, y; // 浮動小数点数
puts("二つの実数を入力せよ。");
printf("実数x:"); scanf("%lf", &x);
printf("実数y:"); scanf("%lf", &y);
printf("x + y = %f\n", x + y); // 和
printf("x - y = %f\n", x - y); // 差
printf("x * y = %f\n", x * y); // 積
printf("x / y = %f\n", x / y); // 商
return 0;
}
実行例
二つの実数を入力せよ。
実数x:45.77
実数y:35.3
x + y = 81.070000
x - y = 10.470000
x * y = 1615.681000
x / y = 1.296601
まずは、キーボードからの実数値の読込みに着目する。Table 2-5にまとめているように、double型の変数に実数値を読み込む際にscanf関数に与える変換指定は%lfである。
Info
ℓは小文字のエルである(数字の1ではない)。
Table 2-5 変換指定の使い分け
10進数のint型 | double型 | |
---|---|---|
scanf関数による読込み | scanf("%d", &n); | scanf("%lf", &x); |
printf関数による表示 | printf("%d", n); | printf("%f", x); |
本来は"%F"であるが、現在では"%lf"も許容される
次は、加減乗除の演算である。List 2-1では、和・差・積・商・剰余の五つの値を求めていたが、本プログラムでは剰余が求められていない。
Table 2-1(p.25)に示すように、剰余を求める%演算子は、その性格上、整数どうしの演算でのみ使えて、浮動小数点数の演算では使えない。そのため、本プログラムに
を追加すると、コンパイル・実行が行えなくなる("chap02/list207x.c")。
重要
剰余を求める%演算子は、整数型のオペランドにのみ適用できる。
型と演算
ここまでの学習で、『整数 / 整数』の演算では、小数部を切り捨てた整数値が得られ、浮動小数点数どうしの演算では、切り捨てが行われずに実数値が得られることが分かった。
それらの演算の様子を図にしたのが、Fig.2-8の図aと図bである。
Fig.2-8 オペランドの型と演算結果
『int / int』や『double / double』といった、両方のオペランドの型が同一であれば、得られる演算結果は演算対象のオペランドと同じ型である。
重要
オペランドの型が同一であれば、得られる演算結果も同じ型となる。
それでは、二つのオペランドの型が異なっていたら、どうなるであろうか。
図cと図dは、次のことを示している。
『double / int』と『int / double』の演算では、int型のオペランドの値がdouble型に格上げされるという暗黙の型変換が行われた上で、double型どうしの演算として行われる。
図cではint型の2がdouble型の2.0へと格上げされ、図dではint型の15がdouble型の15.0へと格上げされている。
両方のオペランドがdouble型となるわけであるから、当然、その演算結果もdouble型となる。
もちろん、ここに示した規則は、/だけでなく、+や*などの演算にも適用される。
C言語には、たくさんの型があるので、細かい規則は複雑である。
詳しい規則はp.222で学習するので、それまでは、次のように理解しておくとよい。
重要
演算の対象となるオペランドの型が異なるとき、小さいほうの型のオペランドは、より大きくて懐の深いほうの型に変換された上で演算が行われる。
Note
ここで、"大きく"という表現を使っているが、必ずしもdouble型が、物理的にint型より大きいわけではない。小数部を格納する"余裕がある"という意味である。
型と演算の確認
ここで学習した規則を、List 2-8のプログラムで確認してみよう。
// 型と演算の確認
#include <stdio.h>
int main(void)
{
int n1, n2, n3, n4; // 整数
double d1, d2, d3, d4; // 浮動小数点数
n1 = 15 / 2; // n1 ← 7(代入時に小数部を切捨て)
n2 = 15.0 / 2.0; // n2 ← 7.5(代入時に小数部を切捨て)
n3 = 15.0 / 2; // n3 ← 7.5(代入時に小数部を切捨て)
n4 = 15 / 2.0; // n4 ← 7.5(代入時に小数部を切捨て)
d1 = 15 / 2; // d1 ← 7
d2 = 15.0 / 2.0; // d2 ← 7.5
d3 = 15.0 / 2; // d3 ← 7.5
d4 = 15 / 2.0; // d4 ← 7.5
printf("n1 = %d\n", n1);
printf("n2 = %d\n", n2);
printf("n3 = %d\n", n3);
printf("n4 = %d\n\n", n4);
printf("d1 = %f\n", d1);
printf("d2 = %f\n", d2);
printf("d3 = %f\n", d3);
printf("d4 = %f\n", d4);
return 0;
}
実行結果
本プログラムで行われている代入は、次のようになっている。
- int型変数n1~n4への代入
Note
int型の変数n1には7が代入され、n2とn3とn4には7.5が代入される。もっとも、代入時に小数部が切り捨てられるので、四つの変数はすべて7となる。
- double型変数d1~d4への代入
Note
double型の変数d1には7が代入される(ただし、d1の型がdouble型であるから、7は実数の7.0と解釈される)。d2とd3とd4には7.5が代入される。
演習2-3
右に示すように、読み込んだ実数値をそのまま表示するプログラムを作成せよ。
演習2-4
整数定数、浮動小数点定数、int型の変数、double型の変数を、掛けたり割ったりするなど、いろいろな演算を行うプログラムを作成し、本文に示した規則を確認せよ。
キャスト
List 2-5(p.30)のプログラムは、二つの整数値の平均値の整数部を求めて表示するものであった。今度は、小数部を切り捨てることなく求めて表示するようにしよう。List 2-9に示すのが、そのプログラムである。
// 二つの整数値を読み込んで平均値を実数で表示
#include <stdio.h>
int main(void)
{
int a, b;
puts("二つの整数を入力せよ。");
printf("整数a:"); scanf("%d", &a);
printf("整数b:"); scanf("%d", &b);
printf("それらの平均は%fです。\n", (a + b) / 2.0);
return 0;
}
実行例
平均を求める赤い式に着目しよう。
最初に行われる演算は、()で囲まれたa + bである。この演算は、『int + int』であって、その演算結果もint型である。そのため、この式の演算は、次のように行われる。
int / double 整数を実数で割る
この演算で得られる結果はdouble型である。プログラムを実行すると、41と44の平均値が42.5として求められて表示される。これで、うまくいった。
*
Tip
さて、私たちが平均を求めるときは、「2.0で割ろう。」と考えるのではなく、「2で割ろう。」と考えるのが普通である。
二つの整数の和をいったん実数に変換し、それを2で割ることによって平均値を求めるように変更しよう。それが、List 2-10のプログラムである。
変更された赤い式に着目しよう。演算子/の左オペランド(double)(a + b)は、初登場の形式であり、次の形をしている。
(型)式 キャスト式
これは、式の値をもとにして、「()の中に指定された型としての値」を生成する式である。
Example
次に示すのが、具体例である。
(int)5.7 ... 浮動小数点定数5.7から小数部を切り捨てたint型の5を生成。 (double)5 ... 整数定数5からdouble型の5.0を生成。
これらの式のイメージを図で表したものを、Fig.3-7(p.55)に示している。
このような、明示的な型変換はキャスト(cast)と呼ばれる。Table 2-6に示すように、()の名称はキャスト演算子(cast operator)である。
Table 2-6 キャスト演算子
演算子 | 記法 | 説明 |
---|---|---|
キャスト演算子 | (型名)a | aの値を型名で指定された型の値に変換したものを生成。 |
Info
英語のcastは数多くの意味をもつ語句である。他動詞のcastには、「役を割り当てる」「投げかける」「ひっくり返す」「計算する」「曲げる」「ねじる」などの意味がある。
Note
なお、()は、優先的に演算を行うための区切り子(p.109)、関数呼出し演算子(p.146)など、いろいろな顔をもっている(文脈によって働きが異なるわけである)。
それでは、本プログラムのキャスト式を理解しよう(aが41でbが44であるとする)。
Fig.2-9 キャスト式の値
Fig.2-9に示すように、a + bの演算結果は、int型の85である。その整数値をdouble型にキャストするキャスト式(double)(a + b)の演算結果は、double型の85.0である。
そのため、平均を求める演算は、次のように行われることになる。
double / int 実数を整数で割る
右オペランドのintがdoubleに格上げされた上で、『double / double』という演算が行われる。得られる演算結果は、double型の実数である。
演習2-5
右に示すように、二つの整数値を読み込んで、前者の値が後者の何%であるかを実数で表示するプログラムを作成せよ。
変換指定
次は、合計値と平均値の対象を2値ではなく3値にしよう。List 2-11に示すのが、そのプログラムである。前のプログラムと同様、キャスト演算子を使って平均を求めている。
// 三つの整数値を読み込んで合計値と平均値を表示
#include <stdio.h>
int main(void)
{
int a, b, c;
puts("三つの整数を入力せよ。");
printf("整数a:"); scanf("%d", &a);
printf("整数b:"); scanf("%d", &b);
printf("整数c:"); scanf("%d", &c);
int sum = a + b + c; // 合計値
double ave = (double)sum / 3; // 平均値(キャスト式で求める)
printf("それらの合計は%5dです。\n", sum); // 99999形式で出力
printf("それらの平均は%5.1fです。\n", ave); // 999.9形式で出力
return 0;
}
実行例
さて、printf関数に渡している書式文字列中の変換指定%5dと%5.1fは、初めての形式である。それぞれが、次の指示を行っている。
%5d ... 整数を少なくとも5桁の10進数で表示。 %5.1f ... 浮動小数点数を少なくとも5桁で表示。ただし、小数点以下は1桁。
Fig.2-10 変換指定の構造
Fig.2-10に示すのが、変換指定の構造である。
図に示すように、変換指定は、%を含めて、5個のパーツで構成されている。
右ページのList 2-12と、その実行結果を対比しながら、各パーツの意味を理解していこう。
List 2-12
// 整数と浮動小数点数を書式化して表示
#include <stdio.h>
int main(void)
{
printf("[%d]\n", 123);
printf("[%.4d]\n", 123);
printf("[%4d]\n", 123);
printf("[%04d]\n", 123);
printf("[%-4d]\n\n", 123);
printf("[%d]\n", 12345);
printf("[%.3d]\n", 12345);
printf("[%3d]\n", 12345);
printf("[%03d]\n", 12345);
printf("[%-3d]\n\n", 12345);
printf("[%f]\n", 123.13);
printf("[%.1f]\n", 123.13);
printf("[%6.1f]\n\n", 123.13);
printf("[%f]\n", 123.13);
printf("[%.1f]\n", 123.13);
printf("[%4.1f]\n\n", 123.13);
return 0;
}
実行結果
[123]
[0123]
[ 123]
[0123]
[123 ]
[12345]
[12345]
[12345]
[12345]
[12345]
[123.130000]
[123.1]
[ 123.1]
[123.130000]
[123.1]
[123.1]
Note
なお、-4のように、フラグに-が指定されている場合は左側にふせて表示され、指定がない場合は右側にふせられる。
A フラグ
0が指定されていると、数値の前に余白があるときに、0をつめて表示する。なお、このフラグを省略した場合は、空白がつめられる。
B 最小フィールド幅
最低限の表示文字数の指定である。少なくとも、この桁数だけの表示が行われる。この指定が省略された場合や、実際に表示する数値が指定された値を超えるときは、その数値を表示するのに必要な桁数で表示される。
C 精度
表示する最小の桁数の指定である。省略すると、整数の精度は1とみなされ、浮動小数点数の精度は6とみなされる。
D 変換指定子
ここが、もっとも重要な部分である。
d ... int型の整数を10進数で表示することの指定である。 f ... double型の浮動小数点数を10進数で表示することの指定である。
Info
ここに示した変換指定の仕様は、ごく一部である。printf関数に関する詳細は、p.376で学習する。
演習2-6
右に示すように、身長を整数値として読み込んで、標準体重を実数で表示するプログラムを作成せよ。
標準体重は(身長 - 100)* 0.9によって求め、その小数点以下を1桁だけ表示すること。
まとめ
-
演算を行うための+や*などの記号は演算子である。演算の対象となるオペランドの個数に応じて、単項演算子、2項演算子、3項演算子の3種類に大別される。
-
演算子によって優先度が異なる。たとえば、乗除算は加減算よりも優先的に行われる。特定の演算を優先的に実行するには、その演算を()で囲む。
-
乗除演算子は、三つある。乗算を行う2項*演算子は二つのオペランドの積を求める。除算を行う/演算子は除算の商を求めて、%演算子は剰余を求める。なお、%演算子のオペランドの型は両方とも整数でなければならない。
-
加減演算子は、加算を行う2項+演算子と、減算を行う2項-演算子の二つである。
-
単項+演算子はオペランドそのものの値を生成する演算子であり、単項-演算子はオペランドの符号を反転した値を生成する演算子である。
-
右オペランドの値を左オペランドに代入する=は、(単純)代入演算子と呼ばれる。
-
変数や定数、さらに、それらを演算子で結合したものが式である。
-
式の後ろにセミコロンを置いたものが、式文である。
-
"○○演算子"を利用する式は、"○○式"と呼ばれる。たとえば、代入演算子=を利用する式a = bは、代入式である。
-
型は、その諸性質を内に秘めた設計図(タコ焼きのカタ)であり、オブジェクト(変数)は、設計図である型をもとに作られた実体(カタから作られた本物のタコ焼き)である。
-
整数型のint型は、整数を表す。小数部をもつ値が代入されても、小数部は切り捨てられる。5や37などの定数は整数定数と呼ばれる。基本的にint型となる。
-
浮動小数点型のdouble型は、浮動小数点数(小数部をもつ実数値)を表す。3.14や2.0などの小数部をもつ定数は浮動小数点定数と呼ばれる。基本的にdouble型となる。
-
整数どうしの算術演算の結果は整数であり、浮動小数点数どうしの算術演算の結果は浮動小数点数である。
-
異なる型のオペランドが混在した演算では、暗黙の型変換が行われる。演算の対象となるオペランドの型が異なるとき、小さいほうの型のオペランドは、より大きくて懐の深いほうの型に変換された上で演算が行われる。そのため、int型とdouble型が混在した演算は、各オペランドがdouble型に変換された上で行われる。
-
ある式の値を、別の型として表現された値に変換するには、キャスト演算子()によるキャスト(型変換)を行う。たとえば、キャスト式(double)5は、int型の整数定数の値5をdouble型に変換した値5.0を生成する。
-
double型の値をprintf関数で表示する際の変換指定が%fであるのに対し、scanf関数で読み込む際の変換指定は%lfである。
-
printf関数やscanf関数に与える書式文字列には、複数の変換指定を置ける。各変換指定は、先頭から順に、第2実引数、第3実引数、…に対応する。
-
printf関数で%文字を表示するには、書式文字列中に%%と書かなければならない。
-
変換指定は、0フラグ、最小フィールド幅、精度、変換指定子などで構成される。
演習問題
演習問題2-1:BMI計算プログラム
問題の説明
BMI(体格指数)を計算するプログラムを作成してください。プログラムは身長(cm)と体重(kg)をユーザーから入力として受け取り、BMI値を計算して小数点以下1桁まで表示します。BMI計算式は:体重(kg) ÷ (身長(m)の2乗)です。
期待される結果
ヒント
- 身長はセンチメートルからメートルに変換する必要があります。100ではなく100.0で割ることで浮動小数点除算を確保します
scanf()
関数は一度に複数の入力値を読み込むことができます。入力時は空白で区切ります- 結果表示時に
%.1f
を使用すると、小数点以下1桁まで表示できます
演習問題2-2:整数の割合計算(キャスト式使用)
問題の説明
二つの整数a、bを入力として受け取り、aがbの何パーセントであるかを計算して小数点以下1桁まで表示するプログラムを作成してください。計算には明示的な型変換(キャスト式)を使用する必要があります。
期待される結果
ヒント
(double)
を使用して明示的な型変換を行い、浮動小数点除算を確保します- パーセントを計算する際は100を掛ける必要があります
- printfでパーセント記号
%
を表示するには%%
を使用する必要があります
演習問題2-3:円の面積と周囲長
問題の説明
ユーザーが入力した円の半径(実数)を受け取り、円の面積と周囲長を計算して小数点以下2桁まで表示するプログラムを作成してください。円周率として3.14を使用します。
期待される結果
ヒント
const double PI = 3.14
で定数を定義すると、コードの可読性が向上します- 浮動小数点入力には、scanfで
%lf
の書式指定子を使用します %.2f
の書式を使用して小数点以下2桁まで表示します
演習問題2-4:温度変換プログラム
問題の説明
ユーザーから摂氏温度と華氏温度を入力として受け取り、摂氏温度を華氏温度に、華氏温度を摂氏温度に変換するプログラムを作成してください。変換式は: - 華氏 = 摂氏 × 9/5 + 32 - 摂氏 = (華氏 - 32) × 5/9 結果は小数点以下1桁まで表示します。
期待される結果
ヒント
- 数学計算では
9.0
、5.0
など小数点付きの数値を使用して、浮動小数点計算を確保します - 温度変換式の演算順序は重要です。必要に応じて括弧を使用して優先順位を明確にします
- 特殊文字°の使用に注意してください
- scanfでの入力値区切りにはカンマ(
,
)を使用します。フォーマット指定子は%lf,%lf
となります
演習問題2-5:時間の変換(キャスト式使用)
問題の説明
カンマ区切りで複数の秒数(整数)を入力し、それぞれを「時間:分:秒」形式に変換して表示するプログラムを作成してください。計算過程では型変換を使用する必要があります。
期待される結果
ヒント
- 整数除算(/)を使用して時間単位を計算し、余り演算(%)を使用して残りの部分を取得します
- 計算の順序に注意してください:まず時間を計算し、残りの秒数から分を計算し、最後に秒を計算します
- 1時間=3600秒、1分=60秒です
- カンマ区切りの入力を受け付けるため、scanf関数のフォーマット指定子は
%d,%d
となります - 複数の値を処理する場合は、それぞれの値に対して計算を繰り返す必要があります