プログラミングおよび演習 NO.3

Last-Modified: 2015.05.07
変数の補足

先週は、int型とfloat型の変数について説明しました。変数を使う際の注意事項をまとめると以下のようになります。

変数を使うときの注意事項
1.宣言文で宣言してから使う(宣言していない変数は使えない)。
2.数値型変数の場合は、変数の表現可能な範囲や有効桁数に注意する。
3.printf(),scanf()の入出力関数に用いるときは、書式(%d, %e)に注意する。

変数の表現可能な範囲や有効桁数を、この表に説明していますが、 ここには、int型とfloat以外に、double型(倍精度実数変数)やshort型(2バイトの整数変数)の数値型変数が載っています。
これらの変数の宣言は、


double x,y,z;
short a,b;


のようにします。また、printf()やscanf()に使うときの書式変換は、double型はほぼfloat型と同じですが、倍精度の意味で、頭にl(アルファベットのエル)をつけて、

%le または  %lf

とします。同様に、short型の変数の場合はほぼint型と同じですが、頭にhをつけて

%hd

とします。ただし、printf()では、lやhをつけ忘れても正しく処理してくれます。これに対して、scanf()の場合は、lやhををきちんとつけないと、正しく読み込んでくれませんので注意が必要です。
この後に説明する文字型も含めて、下表に変数と定数の種類をまとめて示します。

定数および変数の種類

定数の種類宣言書式
整数定数short%hd
int%d
実数定数float%f, %e
double%lf, %le
文字定数char%c
文字列定数charの配列%s

変数の種類宣言書式
整数型short%hd
int%d
実数型float%f, %e
double%lf, %le
文字型char%c
文字列型charの配列%s
文字型定数および文字型変数

今までは数値型の変数や定数を説明してきましたが、数値型と対比する型として、文字や文字列を扱う目的の文字型の変数や定数があります。その文字型の定数は次のように表します。一つは、

'a'

のような1文字を表す文字定数(1文字の半角英数字を''で囲む)です。もう一つは

"Hello World!!"

のよう複数文字を表す文字列定数(複数文字列を""で囲む)です。例えば、これらの文字型データを画面表示するには、

printf("%c\n",'a');
printf("%s\n","Hello World!!");
/* 例1のプログラムと同じ結果になる */

とします。ここで重要なのは、文字定数の書式変換は%c、文字列定数の場合は%sを使うことです。

次に以上で定義した文字型定数を変数に代入することを考えます。そのための文字型変数は、定数の場合と同様に、 文字型と文字列型があります。それぞれ、次のように使います。

・文字型変数の宣言

char c; /*1文字の文字変数cの宣言*/
char string[100]; /* 100文字の長さの文字列変数配列string[]の宣言 */

・文字型変数へのデータの代入

c='a'

とします。これに対して、文字列変数の場合は、

string= "Hello World!!";/* これは間違い */

とすればよさそうですが、不思議なことにこれはできません(この理由を説明すると難しくなるのでここでは説明しません)。
代わりに、次のように変数を宣言するときの初期化データとして値を設定します。

char s[]="Hello World!!"; /*宣言文の初期化データとして値を設定/

・文字型データの入出力
入出力関数はつぎのように書きます。

scanf("%c",&c);
scanf("%s",s);
printf("c=%c\n",c);
printf("s=%s\n",s);



文字列データの扱い方を覚えるために次の練習問題をやってください。

例3-1
/* 文字型変数の練習 */
#include<stdio.h>
 
int main(void)
{
    char c='a'; /* 文字変数cの宣言文*/
    char s[]=" Hello World!!";  /* 文字列変数sの宣言文 */

    printf("文字定数'a'の表示:%c\n",'a');
    printf("文字列定数\"Hello World!!\"の表示:%s\n","Hello World!!");
    printf("文字変数cの表示:%c\n",c);
    printf("文字列変数sの表示:%s\n",s);

   return(0);
}

説明:
宣言文は、コンピュータが実際の処理を始める前の準備(変数の領域の確保と初期化)をします。C言語では、変数を使うときは、プログラムの先頭で必ず変数の型を宣言する必要があります。

char c='a';
char s[]="Hello World!!";

はこれまでと少し違う形をしています。文字型変数cに初期値'a'を代入する、文字列配列s[]に文字列"Hello World!!"を代入しています。 宣言文の書式は、一般的に

型 変数名[=定数];

となります。[=定数]の部分は、変数を定数の値で初期化することを意味します。必ずしもなくても構いません。



変数の型、演算、入出力 に関する以下の問題をやってみてください。 先週のint型、float型以外のdouble型、short型についても数値の範囲や有効桁数を確かめてください。

例3-2 (Revised : 2008/05/15)
/* 数値型データの表現可能な範囲と有効桁数を確かめるためのプログラム*/ 
#include <stdio.h> 

int main(void) 
{
    float a,b,c;
    short w;
    int x,d;
    float y,e,f;
    double z,g;

    printf("----addition and subtraction----\n");
    a=1e-12;
    b=1.23+a;
    c=b-1.23;

    printf("a=%e=%25.19e\n",a,a);
    printf("b=%e=%25.19e\n",b,b);
    printf("c=%e=%25.19e\n",c,c);
 
    printf("----Multiplications----\n");
    w=100000;
    x=100000;
    y=100000.0;
    z=100000.0;
    printf("w=%hd w*w=%hd\n",w,w*w);
    printf("x=%d x*x=%d\n",x,x*x);
    printf("y=%f y*y=%f\n",y,y*y);
    printf("z=%lf z*z=%lf\n",z,z*z);
    
    printf("----Divisions----\n");
    d=10/3*3;
    e=10.0/3.0*3.0;
    printf("d=10/3*3=%d\n",d);
    printf("e=10.0/3.0*3.0=%f\n",e);
    
    e=10/3*3;
    d=10.0/3.0*3.0;
    printf("d=10.0/3.0*3.0=%d\n",d);
    printf("e=10/3*3=%f\n",e);

    printf("----Output float and double values----\n");
    f=1.234567890123456789;
    g=1.234567890123456789;
    printf("f=%18.9f=%25.19e\n",f,f);
    printf("g=%18.9lf=%25.19le\n",g,g);

    return(0);
}



最初のところで行っている計算、

c=(1.23+a)-1.23;

の結果は、aに等しくなるはずですが、そうなりません。その理由について述べてください。また、aが1.0e-4や1.0e-8の場合についても結果を求め、1.0e-12の場合の結果と比較して考察をしてください。
次に、

printf("w=%hd w*w=%hd\n",w,w*w);
printf("x=%d x*x=%d\n",x,x*x);
printf("y=%f y*y=%f\n",y,y*y);
printf("z=%lf z*z=%lf\n",z,z*z)
;

については、正しく計算できていない場合 (手計算と異なる結果を出力する場合)があります。それはどれでしょうか?理由を付けて答えなさい。
また、既に説明していますが、

x=100000;
y=100000.0;


の様に、数値に小数点をつけないと整数型定数、小数点をつけると実数型定数を表します。
従って、

d=10/3*3;
e=10.0/3.0*3.0;


の右辺はそれぞれ、整数型と実数型の数値演算になります。dとeには異なる結果が入ることをプログラムを動かして確認し、 その理由について考察してください。

その下ではeとdを入れ替えて、

e=10/3*3;
d=10.0/3.0*3.0;

としていますが、結果はどうなるでしょうか?先ほどの結果と比較して考察してください。
最後に示した以下のプログラムから出力されるfとgには違いがあります。違いの理由について考察してください。

f=1.234567890123456789;
g=1.234567890123456789;
printf("f=%18.9f=%25.19e\n",f,f);
printf("g=%18.9lf=%25.19le\n",g,g);


printfの書式: 

上記の例題において、float型の変数fを画面表示するためのprintf文には、

printf("f=%18.9f=%25.19e\n",f,f);

のように、書式の%の直後に数字が入っています。これは表示桁数を指定するために使います。すなわち、

%18.9f

は、全体を18桁、小数点以下の桁数を9桁(例:123456789.123456789)、の固定小数点形式で表示することを意味します。
同様に、

%25.19e

は全体を25桁、小数点以下の桁数を19桁の指数形式で表示します。一方、double型の変数gの場合は、

printf("g=%18.9lf=%25.19le\n",g,g);

のように、桁指定はfloat型の場合と同様の約束になります。ただし、double型の変数であることを断るために、 桁指定の後に"l"(アルファベットのエル、数字の1と間違えないこと)をつけて、

%18.9lf  %25.19le

のように記述しています。

各々の変数の型に応じて、%書式を正しく記述する必要があります。間違ってもコンピュータはエラーメッセージを出してくれません。計算結果が変になるだけですので注意が必要です。

演習問題3-1 (Revised : 2015/05/07)

例3-1、3-2のプログラムを実行しなさい。例3-1については文字型変数の特徴を踏まえてプログラムの動作説明をしなさい。また、例3-2では、上に示した指示に従って結果を示し、解答や考察をしなさい。考察のポイントは、変数の表現可能な範囲や有効桁数です。

(時間が余った人に) 
(※時間がある人は以下の課題にもチャレンジしなさい。(時間が余った人に)の課題をレポートに含めることで加点されます)
例3-2のプログラムの最後に、

printf("----addition and subtraction----\n");
a=1e-12;
b=1.23+a;
c=b-1.23;

printf("a=%e=%25.19e\n",a,a);
printf("b=%e=%25.19e\n",b,b);
printf("c=%e=%25.19e\n",c,c);

のa,b,cを、新しく定義したdoubleの変数、例えば、
double s,t,u;
に置き換えたプログラムを追加し(printf文の書式を%leにすることを忘れずに)、
float a,b,c;
を用いた場合の結果との違いについて考察しなさい。



演習問題3-2(時間が余った人に)

 時間が余った人は、気分転換に以下の課題をやってみてください。
(来週この問題を発展させた演習問題をやってもらいますので無駄になりません。
今までと違ってプログラムの雛型は示していませんが、簡単に作れるはずです。)。

自分の身長をキーボードから入力すると、BMI(Body Mass Index)と標準体重を計算して表示するプログラムを作ってください。なお、それぞれの計算式は以下のとおりです。

      体重(kg)
 BMI=              
     身長(m)×身長(m)

 標準体重(kg)=身長(m)×身長(m)×22

さらに、以下の計算式を用いて、体重を入力すると肥満度を算出するようにしてください。

          (実測体重-標準体重)×100
 肥満度(%)=                   
               標準体重

肥満度(%)から以下のように判定できます。

 -10%未満       やせ
 -10%~+10%未満   正常
 +10%~+20%未満   肥満ぎみ
 +20%以上       肥満

また、BMIの値が25, 27, 29以上でそれぞれ以下の病気の発病率が2倍以上に大きく 増えると言われています。

 BMI≧25→高血圧症, 高中性脂肪血症
 BMI≧27→糖尿病  
 BMI≧29→高コレステロール血症