1. プログラミングの基礎、演算と型
INDEX

目標

  • プログラミングの手順を憶える。
  • printfを使った簡単な画面表示プログラムを作成できる。
  • 基本的な算術演算子を使って計算結果を求めることができる。
  • 整数と浮動小数点数を区別して計算式を作ることができる。
  • 演算子の優先順位を理解して式を作ることができる。
  • 変数を使った演算ができる。
  • データ型に合わせた書式指定、変換指定子の利用ができる。
  • キーボードから値を入力して、変数に格納することができる。

予習・復習

 以下のスライドを利用して、予習と復習をしよう。復習では、自分の理解度を確認するために、実際にプログラムを作成し、意図する結果が得られるか確認しよう。
  1. プログラミングの基礎
  2. 演算
  3. 型と変数
  4. printf
  5. エラーの取り除き方
note 講義で使用したサンプル・プログラム

本日の講義・演習予定

  1. プログラミングの準備
  2. はじめてのプログラミング
  3. ソースコードの書き方
  4. 文字、文字列、数値
  5. 計算してみよう
  6. 演算の優先順位
  7. 整数と小数点を含む数の演算
  8. 変数とデータ型
  9. いろいろな書式指定
  10. キーボードから入力する
本日前半の講義・演習予定
  1. プログラミングの準備
  2. はじめてのプログラミング
  3. ソースコードの書き方
  4. 文字、文字列、数値
  5. 計算してみよう
  6. 演算の優先順位
  7. 整数と小数点を含む数の演算

プログラミングの手順

 プログラムの作成から実行までの操作手順を下図に示します。
programming

手順1: ソースコードを書く
 プログラミング言語を使ってコンピュータが処理すべき手順を記述したものをソースコードと呼びます。ソースコードをファイルとして保存したものをソースコード・ファイルと呼びます。
ソースコードは、
  • 英数字と記号を主体とする文字だけの集まりで、
  • C言語の規格で決められた文法やルールに従って記述します。
ソースコード・ファイルは、
  • テキスト型式のファイルで、
  • ファイル名の拡張子に .c を付なければなりません。
 拡張子に.cを付けることによって、コンパイラや開発環境はC言語のソースコード・ファイルであることを判別します。

手順2: プリプロセッサ
ソースコードに書かれたプリプロセッサ指令を処理します。プリプロセッサ指令には、外部ファイルの読み込みや、定数定義、マクロ展開、コンパイラに対する指示があります。

手順3: コンパイル
ソースコードを機械語に翻訳したオブジェクトプログラムを生成し、オブジェクトファイル(*.obj)として保存します。もし、ソースコードにプログラムとして文法上の誤りがあれば「コンパイルエラー」として報告されます。このときは、ソースコードを修正する「デバッグ」作業を行い、再度コンパイルします。

手順4: リンク
入出力処理や数学関連処理など多くのプログラムでよく利用されるプログラムは「標準ライブラリ」として事前に用意されています。このライブラリをオブジェクトファイルに組み込む作業が「リンク」です。リンクによって実行可能形式ファイル(*.exe)が生成されます。

※手順2から4までの一連の処理は、コンパイラ・コマンドによって自動的に処理されます。また、開発環境MS Visual Stduioではこの一連の作業をビルドと読んでいます。


はじめてのプログラミング

Hello, World!

 Hello, World!と画面に表示する次のプログラムを作成して、実行してみましょう。
例 HelloWorld.c
#include <stdio.h>

int main(void)
{
	printf("Hello, World!\n");
	return 0;
}
		
 "Hello, World!"と画面に表示されましたか?画面に表示されたら、次は、ソースコードの中身を見ていきましょう。このプログラムは2つの命令文から構成されています。

5行目:画面にHello, World! を表示をさせる命令文

 この1行は、文字列 Hello, World! を出力装置であるディスプレイに表示させる命令文です。
printf("Hello, World!\n");
printfはその後に続くカッコ()内の文字列を画面に出力する命令で、printf関数と呼びます。printfのprintは印刷の意味ですが、その後に続くfはformat(書式)に由来しています。printfは書式に従って画面に表示させる役割を持つ関数だからです。なぜ、書式が出てくるかという理由は、後で説明します。また、カッコ内に記述するものを引数と呼びます。文の終端にはその文の終了を示す記号セミコロン(;)を記述しなければなりません。

5行目:改行を指示する特殊な記号\n

 文字列"Hello, World!"の最後に書かれた見慣れない \nは何でしょう?これは、改行を指示する特殊な記号です。ソースコード中に入力する「改行」や「半角空白」はコンパイラに無視されてしまいます。ですから、画面上で「改行」をさせたいときにはプログラム中に明示的に指示を記述してあげる必要があります。このような特殊な記号のことをエスケープシーケンスと呼びます。\nの\(バックスラッシュ)は日本語環境では¥(円マーク)として表示されることに注意しましょう。

6行目:プログラムの終了を示す

  次にその下の6行目に注目します。
return 0;
プログラムの最後に必ず書かなければならない命令文です。プログラムが正常に終了したことをこのプログラムの呼び出し元に0を返すことで知らせます。呼び出し元は、通常、オペレーティングシステム(Operating System)になります。オペレーティングシステムはリターンされた0を受け取って、プログラムが正常に終了したと判断するわけです。

3〜7行目:プログラム本体となるmain関数

 プログラム全体の中で最初に実行される関数がmain関数です。一つのプログラムには複数の関数を定義することができますが、その中で最初に呼び出されて処理される特別な関数です。エントリーポイントとも呼ばれます。
int main(void)
{
 ・・・
}
 波括弧で複数の文を囲うことで、処理のまとまりを作ります。これをコードブロックと言います。このブロックの前に関数の名前mainを記述します。

コンパイラへ指示をするプリプロセッサ

 最後に先頭行に注目しましょう。
#include <stdio.h>
これはプログラムの本体ではなくコンパイラに対する指示になります。プリプロセッサと呼ばれます。この例では、C言語に標準で用意されているヘッダファイルstdio.hを読み込み、このプログラムに含めるように指示しています。

 5行目のprintf関数は画面に出力するためのサービスを提供してくれるとても便利な関数ですが、実は、このprintf関数もC言語で書かれています。入力や出力といったよく利用される機能はあらかじめ関数として用意されていて、呼び出すだけで利用できるようになってるのです。このような関数をまとめたものをライブラリ(Library)と呼び、ヘッダファイル(Header file)として提供されています。
 ヘッダファイルstdio.hは、キーボード(標準入力装置)からの入力やディスプレイ(標準出力装置)に対する出力など標準入出力(Standard Input/Output)に関わる関数をまとめて定義してることから、このファイル名が付けられています。

ソースコードの書き方

シンタックス

 人間同士のコミュニケーションならば、文章中の一文字が大文字になっていても、その意味を理解することはできます。例えば、return を Return と書いたとしても意味は通じするはずです。けれでも、コンピュータはそれを C言語のreturn とは理解してくれません。C言語では定義されていないキーワードは構文エラー(Syntax Error)として扱われてしまうのです。
 ソースコードを記述する上では、次のような点に注意をしましょう。
  • C言語の規格、ルールに従って記述する。
  • 大文字と小文字、また、全角文字と半角文字は区別される。
  • 改行、半角空白文字は無視される。
  • 文(statement)の最後はセミコロン(;)で終わる。

初心者によくあるミスの具体例
  • 文末のセミコロン(;)を書き忘れる。
  • 閉じカッコを書き忘れる。(例 {に対する})
  • キーワードのスペルミス。(例 誤:studio.h 正:stdio.h)
  • 全角文字と半角文字を区別していない。(例 誤:{ 正:{)
  • 空白文字に全角空白を使う。(例 誤: 正: )
  • 似た記号の取り違え。
    例1) セミコロン(;)とコロン(:)
    例2) カンマ(,)とピリオド(.)
    例3) シングルクォーテーション(')とダブルクォーテーション(")
    例4) スラッシュ(/)とバックスラッシュ(\)
    例5) ハイフン(-)とアンダスコア(_)
    例6) 丸カッコ(( ))と波カッコ({ })

コーディングスタイル

 プログラム HelloWorld.cを次のように2行に収まるように記述してみました。さて、このプログラムは実行できるでしょうか?実際に編集して、コンパイル、実行してみましょう。
例 HelloWorld.c
#include <stdio.h>
int main(void){ printf("Hello, World!\n"); return 0; }
 はい、問題なく実行することができましたね。C言語ではソースコードのコーディングスタイル、すなわち記述様式まで厳密に定めているわけではありません。ですから、上記のようにフリースタイルで記述をしてもプログラムは正常に実行されます。しかし、フリースタイル=分かりやすいコードではありません。フリースタイルで書かれたプログラムが数百行、数千行と大きくなった場合を想像してみてください。暗号のようにしか見えないプログラムを読む気になるでしょうか。先人たちは読みやすく、その意味が他の人にも伝わるようにスタイルを工夫してきました。そのある程度定式化したスタイルが今現在、多くのプログラマー達に使われているのです。加えて、Pythonをはじめとする新しいプログラミング言語では、スタイルがその文法の一部として意味を持つようになっています。
 共通する基本なスタイルとは、次のような規則に従って書かれたコードです。
  • 演算子やキーワードの前後に空白を入れる。
  • 波カッコ{}で閉じたブロック内はインデント(字下げ)したレイアウトにする。
  • 適当な空白、空行を使ってプログラムの構造を示す。
  • 先人たちの優れた慣習に習う。

 ※具体的なコーディングスタイルは本講義のサンプルプログラムを見本としてください。

コメント

 ソースコードの中にタイトルや更新日、作成者名、また、解説や注意点などメモ書きを残しておきたいことがあります。このような時にはコメント文を利用します。コメントには複数行にわたって記述できる複数行コメントと、行末までの1行コメントがあります。複数行コメントは/*ではじまり*/で終わります。1行コメントは先頭に//と記述します。
以下はコメントを含むソースコードの例です。
例 HelloWorld.c
#include <stdio.h>

/*
*  Hello, World!
*  created on  2019/04/11
*  @author programmer@example.jp 
*/
int main(void)
{
	printf("Hello, World!\n");		//画面表示
	return 0;
}

文字、文字列、数値

 C言語では、文字(character)、文字列(string)、数値(numerical value)を異なるデータタイプとして区別します。さらに、数値は整数(integer)と小数点(point)を含む数値である浮動小数点数(floating point number)に区別されます。
  1. 文字 : その文字をシングルクォーテーション(')で囲う
  2. 文字列: その文字列をダブルクォーテーション(")で囲う
  3. 数値 : 「式」として扱うときにはそのまま記述し、「文字列」として扱うときには書式指定子を使って変換する

 以下のプログラムでは、文字、文字列、整数、浮動小数点数を画面に表示します。printfは文字列を画面に表示する関数でした。文字列以外の文字、整数、浮動小数点数は変換指定子と呼ばれる特殊な記号を使って文字列に変換しなければなりません。文字は%cを、整数は10進数(decimal)表示を指定する%dを、浮動小数点数表示の場合には%fという変換指定子を使います。
例 DataFormat.c
#include <stdio.h>

int main(void)
{
	printf("123\n");		//string
	printf("%c\n", '1');		//character
	printf("%d\n", 123);		//decimal format
	printf("%f\n", 0.123);		//floating point number format

	return 0;
}
 一つ目のprintf文はそのカッコ内に文字列からなる引数を一つだけ持っています。その後の3つのprintf文ではカンマ(,)区切った2つの引数を持っています。1つ目の引数は変換指定子含む文字列であり、どのように画面に表示するかを指定するための書式指定(format)となっています。2つ目の引数は先の書式指定の中にある変換指定子に当てはめる値が記されています。例えば、3つ目のprintf文の変換指定子%dの位置には、2つ目の引数である整数123が文字列に変換されて、当てはめられます。

計算してみよう

計算結果を表示する

 コンピュータと言えば、やはり「計算」というイメージです。簡単な足し算をするプログラムを作成してみましょう。
例 plus.c
int main(void)
{
	2+3;	// 式
	
	return 0;
}
あれ?結果が表示されません。5という結果を期待したのですが。
例 plus.c
#include <stdio.h>

int main(void)
{
	printf("%d\n", 2+3);
	
	return 0;
}
 画面に表示するためにはprintf関数を使うのでしたね。

 今度は、計算内容がわかるように計算式も表示に加えてみましょう。
plus.c
#include <stdio.h>

int main(void)
{
	printf("2+3=%d\n", 2+3);
	
	return 0;
}
 printf文の書式文字列には、変換指定以外の文字列も含むことができます。また、ダブルクォーテーション("")で囲われた 2+3 が 5 と表示されないのは、式としてではなく文字列として評価されるからです。
ダブルクォーテーション("")で囲うと、文字列として扱われる。

加減乗除

 基本的な算術演算である加算、減算、乗算、除算の四則演算を使ったプログラムを作成します。演算を指示する記号を演算子(operator)と言います。加算と減算の演算子にはなじみの深い、"+"と"-"の記号を使います。掛け算と割り算に使われる×と÷の記号はコンピュータにはないので、代わりに乗算では"*"を、除算では"/"の記号を使います。
例 calc.c
#include <stdio.h>
/*
*    算術演算子
*/

int main(void)
{
	printf("2+3=%d\n", 2+3);	// 加算
	printf("8-6=%d\n", 8-6);	// 減算
	printf("5*4=%d\n", 5*4);	// 乗算
	printf("12/3=%d\n", 12/3);	// 除算

	return 0;
}

剰余演算

 プログラミング言語の基本的な演算子には四則演算に加えて割り算の余りを求める剰余演算子 %が用意されています。上記のプログラムに剰余演算子%を使った演算を追加してみましょう。
例 calc.c
#include <stdio.h>
/*
*    算術演算子
*/

int main(void)
{
	printf("2+3=%d\n", 2+3);	// 加算
	printf("8-6=%d\n", 8-6);	// 減算
	printf("5*4=%d\n", 5*4);	// 乗算
	printf("12/3=%d\n", 12/3);	// 除算
	printf("7%%2=%d\n", 7%2);	// 剰余

	return 0;
}
※ 文字%を表示したいときには、%%と記述することに注意する。

算術演算子一覧
演算子演算補足
+加算
-減算
*乗算
/除算整数演算においては小数点以下切り捨て
%剰余整数の場合のみ

演算の優先順位

 複数の演算子を含む式では、演算子の優先順位によって演算の順番が変わってきます。例えば、+と*ならば*の方が優先順位が高いので*の演算が先に評価され、同じ優先順位の+と-ならば左から順に評価されることになります。
  • +, -よりも*, /のほうが優先順位が高い
  • 同じ優先順位の場合は、左側から先に処理する
  • カッコ( )で囲むと、その中を先に処理する
※演算子の優先順位の一覧はこちらの表を参照してください。
c1-7.c
int main(void)
{
	printf("2*2+3*5 = %d\n", 2*2+3*5);
	printf("6*(3+2)/2 = %d\n", 6*(3+2)/2);
	printf("100/10/2 = %d\n", 100/10/2);
	
	return 0;
}

整数と小数点を含む数の演算

整数と整数の演算結果は整数になる

 6÷2の答えは?と問われれば3、7÷2の答えは?と問われれば3.5、と暗算でもすぐに答が出てくる計算ですが、コンピュータは期待通りの答を出力してくれるでしょうか。次のプログラム例を実行して確認してみましょう。
例 c1-8a.c
#include <stdio.h>
/*
*    算術演算子
*/

int main(void)
{
	printf("6/2=%d\n", 6/2);
	printf("7/2=%d\n", 7/2);		// 整数と整数の演算 -> 整数
	
	return 0;
}
 6÷2の計算結果は正しく3と出力されましたが、7÷2では期待する3.5という結果ではなく3という出力結果になってしまいました。これは、「整数」と「整数」の演算結果は必ず「整数」となるためです。小数部は切り捨てられてしまうのです。
整数 ÷ 整数 ⇒ 整数

整数と浮動小数点数は区別される

 1 ÷ 3 × 3 の計算を行うプログラムを作成してみました。
例 c1-8b.c
#include <stdio.h>

int main(void)
{
	printf("%d\n",1/3*3);
	
	return 0;
}
期待する実行結果は1ですが、このプログラムではそうはなりません。1/3*3のように同じ優先順位の演算子を複数含む式では、左から右に向かって評価が進むので、
  1. 1/3 =>評価結果 0
  2. 0*3 =>評価結果 0
結果は0となります。

 厳密な結果を得るためには、数値の小数部を切り捨てずに扱えるようにしなければなりません。そのためには、数値を浮動小数点数と呼ばれる小数点以下の値を含む実数として表現する必要があります。コンピュータは浮動小数点数と整数を異なるタイプの数値として区別し処理をするからです。
 具体的には、例えば、整数 1は 1.0 ように小数点を含む数値として表記します。先ほどのプログラムを浮動小数点数の計算として書き改めてみましょう。
例 c1-8c.c
#include <stdio.h>

int main(void)
{
	printf("%d\n",1/3*3);		// 整数の演算
	printf("%f\n",1.0/3.0*3.0);	// 浮動小数点数の演算
	
	return 0;
}
浮動小数点数を表示するために変換指定子が%fになることに注意しましょう。
浮動小数点数 ÷ 浮動小数点数 ⇒ 浮動小数点数

整数と浮動小数点数の計算

 整数と浮動小数点数が混ざった演算の結果はどうなるのでしょう? 5 ÷ 2の計算を例に見てみましょう。
例 c1-8d.c
#include <stdio.h>

int main(void)
{
	printf("%d\n",1/3*3);		// 整数
	printf("%f\n",1.0/3.0*3.0);	// 浮動小数点数
	printf("%f\n",5.0/2);		// 浮動小数点数と整数
	printf("%f\n",5/2.0);		// 整数と浮動小数点数
	
	return 0;
}
浮動小数点数÷整数も整数÷浮動小数点数もどちらも結果は浮動小数点数となりました。整数と浮動小数点数の演算の場合、整数は自動的に浮動小数点数に変換され、演算されたためです。これを格上げと言います。
整数と浮動小数点数の演算では、整数⇒浮動小数点数 へ格上げされる。
整数と浮動小数点数は区別される。

キャスト(型変換)

 明示的に型を指定することで他の型に変換することもできます。これをキャストと言います。例えば、整数5を浮動小数点数変換したい場合は、(double)5と整数5の直前に浮動小数点型を表すdoubleをカッコ()で囲います。もし、浮動小数点数を整数型に変換したければ、(int)5.6のように記述します。doubleやintといった型の名前については次節の変数のところで見ていきます。
例 c1-8e.c
#include <stdio.h>

int main(void)
{
	printf("%d\n",1/3*3);		// 整数
	printf("%f\n",1.0/3.0*3.0);	// 浮動小数点数
	printf("%f\n",5.0/2);		// 浮動小数点数と整数
	printf("%f\n",5/2.0);		// 整数と浮動小数点数
	printf("%f\n",(double)5/2);		// 整数を浮動小数点数へ型変換
	printf("%d\n", (int)5.6);		//小数を整数へ型変換
	
	return 0;
}
 浮動小数点数を整数 へキャストすると、小数部が切り捨てられてしまうので注意が必要です。浮動小数点数から整数へキャストを格下げと言います。

expand_lessBack to TOP
本日の後半の講義・演習予定
  1. 変数とデータ型
  2. いろいろな書式指定
  3. キーボードから入力する

変数とデータ型

 先の計算結果を受けて次の計算をしたいときがあります。例えば、合計値と平均点です。先に求めた合計値を次の平均値の計算で利用するためには、合計値を一旦どこかに記憶しておく必要があります。加えて、どこに記憶したかが分かるように名札(label)を付けておく必要もあります。この「記憶」の仕組みをプログラムでは変数(variable)と呼びます。記憶に付けた名札を変数名(variable name)と言います。
sumof.c
#include <stdio.h>

int main(void)
{
	int sum;		// 変数の宣言 int型で変数名はsum
	
	sum = 80+90+100;	// 計算結果を変数sumに代入する

	printf("合計 %d\n", sum);
	printf("平均 %d\n", sum/3);
	
	return 0;
}

変数の宣言

 変数を利用するためにはあらかじめ「変数宣言」をしておかなければなりません。「変数宣言」をすることで値を記憶する領域が確保されます。このとき、記憶領域のタイプを指示する「データ型」と、その記憶領域を識別するための変数名が必要になります。主な変数のデータ型には、整数を格納するための整数型(int型やlong型)、実数を格納するための浮動小数点数型(float型やdouble型)、文字を格納するための文字型(char型)があります。変数名にはあらかじめC言語で規定されている名前以外ならば、半角英数字と記号アンダスコア(_)を使って自由に組み合わせた名前を付けることができます。

変数への値の代入  変数に値を格納するときには、記号=を使います。=の右辺の値が左辺の変数に代入されます。数学の同等を表わす”イコール”とは違います。

変数は使う前に変数宣言をする データ型 変数名;
同じデータ型なら同時に複数の変数を宣言できる データ型 変数名、変数名、・・・;
= は「右辺の値」を「左辺の変数」に代入することを表わす

※変数宣言の位置について C言語の標準規格C99(1999年)以降に準拠したコンパイラでは、その変数を利用する前ならば、関数内のどこででも宣言することができます。しかし、それ以前の古い仕様のコンパイラでは、関数の先頭にまとめて記述する必要があります。

主なデータ型一覧

種類型名バイト数表現の範囲(Windows 32bitの場合)
文字型char1-128 〜 127
符号付き短整数型short2-32768 〜 32767
符号付き整数型int4-2147483648 〜 2147483647
符号なし整数型unsigned int40 〜 4294967295
符号付き長整数型long4-2147483648 〜 2147483647
単精度浮動小数点型float4-3.4x10-38 〜 3.4x1038
倍精度浮動小数点型double8-1.7x10-308 〜 1.7x10308
※ 文字型は整数型の一種です。格納できるデータ幅が1byte(8bit)なので、バイト文字と呼ばれる半角英数字記号1文字を格納することができます。

変数名の付け方

  • 変数名に利用できる文字は半角英数字(a〜z、A〜Z、0〜9)とアンダスコア(_)
  • 数字は先頭文字には使えない。
  • 大文字と小文字は区別される。
  • C言語であらかじめ定義されているキーワード(予約語)は利用できない。

キーワード(予約語)
auto double int struct break else long switch case enum register
typedef char extern return union const float short unsigned continue
for signed void default goto sizeof volatile do if static while

変数は箱のようなもの

 変数がよく理解できないという人は、下表のように「変数」を値を格納する箱のようなものだとイメージするとよいかもしれません。例えば、荷物を保管するときには段ボール箱に入れて所有者が分かるように名前を書いておきます。手に持ちきれない荷物があればコインロッカーを利用し、鍵に付いた札に書かれた番号でその場所を見つけます。プログラム上の値も保管しておかなければ再利用はできません。変数名という名前が付いた変数という箱にデータを保管し、変数名を使って保管場所を区別します。
処理コード動作 ⇒ 結果説明
変数宣言int num;変数宣言int型でnumという名前の変数が用意される。
値の代入num = 100;代入中代入変数に値100を代入する。
変数の初期化int num = 100;変数の初期化変数宣言と同時に値100を格納する。
値の代入
(上書き)
num = 100;

num = 200;
代入代入変数numに値100を代入する。次に、変数numを値200で書き換える。
代入代入
変数の代入
(上書き)
a = 123;

b = 456;

b = a;
代入代入変数aに値123を代入し、変数bに値456を代入する。変数aのコピーを使って変数bの値を書き換える。
代入代入
代入代入
※ 私たちは長い間、数学で 式a=b を等式として学んできました。いきなり、C言語の文a=b; は左辺が「値の格納先」を示し、右辺が「格納されている値」を示すのだという言われても、頭を混乱させられるだけかもしれません。しかし、これには慣れるしかありません。

データ型が違うと箱の大きさが違う、箱への収まり方も違う
char型文字型
int型整数型
double型不動小数点型
※ char型とint型は整数型、double型は浮動小数点型。浮動小数点数は(仮数)×(基数)(指数)で表現される値です。変数の最上位ビットには符号を、残りを仮数部と指数部に分けて値を格納します。値は2進数で格納されるので、基数は2となります。

変数を使った演算

 変数の初期化、変数への値の代入方法についてのいろいろな記述方法について確認しておきましょう。
variable.c
#include <stdio.h>

int main(void)
{
	int a,b;			//値は不定
	int c = 3;		//変数の初期化

	a = 1;			//代入
	b = 2;
	printf("a=%d, b=%d, c=%d\n",a,b,c);

	a = 100;		//上書き
	b = a;	
	printf("a=%d, b=%d\n",a,b);

	a = a + 23;		//演算結果を格納
	b = b - 50;
	printf("a=%d, b=%d\n",a,b);

	a = a/c;		//変数のみによる演算
	b = a/c;
	printf("a=%d, b=%d, c=%d\n",a,b,c);

	return 0;
}

いろいろな書式指定

 printf文を使って数値を画面表示するときには、整数ならば%d、小数ならば%fという変換指定を使いました。とても大きな実数やとても小さな実数を扱うときには指数表示といって仮数と指数を使った表示を使うこともできます。例えば、1.23×1016といった大きな実数なら、1.23e16 表記し、書式指定では%eという変換指定を使います。いろいろな数値の表示を扱ったプログラムを見てみましょう。

出力時の主な変換指定子

変換指定子対応する型説明
%cchar1文字を出力
%schar *文字列を出力
%dint符号付き整数を10進数で出力
%ldlong符号付き倍精度整数を10進数で出力
%oint整数を8進数で出力
%xint整数を16進数で出力
%ffloat実数を出力
%lfdouble倍精度実数を出力
%efloat実数を出力
%gfloat実数を最適な形式で出力
%ledouble倍精度実数を出力
%lgdouble倍精度実数を最適な形式で出力

整数の10進、8進、16進数表示

例 c1-10a.c
#include <stdio.h>

int main(void)
{
	int a = 123;

	printf("%d\n",a);	//10進数
	printf("%o\n",a);	//8進数
	printf("%x\n",a);	//16進数
		
	return 0;
}

浮動小数点数の書式指定

例 c1-10b.c
#include <stdio.h>

int main(void)
{
	double a = 1.234567;

	printf("%f\n",a);		//浮動小数点数表示
	printf("%e\n",a);		//指数表示
	printf("%g\n",a);		//%eか%fかを自動判別
	
	return 0;
}

2つ以上の値を表示

 一つのprintfで複数の変数の値を表示したい場合には、下記の例のように複数の変換指定子の並びに合わせて、変数をカンマで区切って記述します。
例 c1-10c.c
#include <stdio.h>

int main(void)
{
	int a=5, b=7, c;

	c = a+b;
	printf("%d+%d=%d\n",a,b,c);
		
	return 0;
}

桁指定、配置指定

例 c1-10d.c
#include <stdio.h>

int main(void)
{
	int a=123456789;
	double b=0.1234567;

	printf("%12d\n",a);	//12桁右詰め
	printf("%012d\n",a);	//12桁0詰め
	printf("%-12d\n",a);	//12桁左詰め

	printf("%9.3f\n",b);	//全9桁、小数部3桁
	printf("%.3f\n",b);	//小数部3桁
	printf("%.5f\n",b);	//小数部5桁
	printf("%.10f\n",b);	//小数部10桁

	return 0;
}

キーボードから入力する

 キーボード(標準入力)から値を入力するための関数に scanf があります。関数printfと同様に標準入出ライブラリstdio.hの中で定義されています。以下はキーボードから入力した数字を画面に出力するプログラムです。

整数を入力する

c1-11a.c
#include <stdio.h>

int main(void)
{
	int a;

	scanf("%d", &a);
	printf("%d\n", a);
	
	return 0;
}
scanfの引数の一つめはキーボードから読み込んだ値を格納する変数の変換指定で、二つ目が読み込んだ値を格納する変数名です。変数名の前にアンパサンド(&)が必要になります。
scanf 格納先の変数名の前に&を忘れずに!
※ MS Cにはscanfとは別にscanf_sという独自の関数が用意されており、こちらの使用を推奨しています。関数scanfにはバッファオーバーランと呼ばれる問題を引き起こす可能性があります。この問題に対処するために用意されたのがセキュア版の関数scanf_sです。

入力時の主な変換指定子

変換指定子対応する型説明
%cchar1文字を入力
%schar *文字列を入力
%dint符号付き整数を10進数で入力
%ldlong符号付き倍精度整数を10進数で入力
%ffloat実数を入力
%lfdouble倍精度実数を入力

入力を促すメッセージを追加してみましょう。
サンプル c1-11b.c
#include <stdio.h>

int main(void)
{
	int a;

	printf("整数を2倍します。\n");
	printf("整数を入力してください >>");
	scanf("%d", &a);

	printf("%d\n", a*2);
	
	return 0;
}

キーボードから実数を入力する

サンプル c1-11c.c
#include <stdio.h>

int main(void)
{
	double b;

	printf("実数を2.5倍します。\n");
	printf("実数を入力してください >>");
	scanf("%lf", &b);

	printf("%f\n", b*2.5);
	
	return 0;
}
※ scanfを使って倍精度浮動小数点数を入力するときの変換指定は %lf ですが、printfを使って浮動小数点数を表示するときには%fとなることに注意しましょう

二つの値を入力し、その計算結果を表示する

 複数の値をまとめて入力したい時には、scanfの書式指定を利用します。例えば、以下の表のようにint型変数aとbにそれぞれキーボードから二つの値をカンマ(,)区切って入力する場合は、scanfの書式も%dと%dの間にカンマ(,)を挟んでこれに合わせます。半角空白で区切って入力したければ、scanfの書式も%dと%dの間に半角空白を挟みます。
実行画面対応するソースコード(一部)
整数(a,b)>> 23,56
printf("整数(a,b)>> ");
scanf("%d,%d", &a,&b);
整数(a b)>> 23 56
printf("整数(a b)>> ");
scanf("%d %d", &a,&b);

 以下は、2つの整数を入力して、その加減乗除剰余の計算結果を表示するプログラム例です。
サンプル c1-11d.c
#include <stdio.h>

int main(void)
{
	int a,b;

	printf("算術演算の結果を求めます。\n");
	printf("コンマで区切って、2つの整数を入力してください >>");
	scanf("%d,%d", &a, &b);		//書式指定と入力が一致します

	printf("%d + %d = %d\n", a, b, a+b);
	printf("%d - %d = %d\n", a, b, a-b);
	printf("%d * %d = %d\n", a, b, a*b);
	printf("%d / %d = %d\n", a, b, a/b);
	printf("%d %% %d = %d\n", a, b, a%b);
	
	return 0;
}
文字'%'を表示する場合には、"%%" と記述します。

scanf使用時のワーニング回避方法

 Visual Studio (MS Cコンパイラ)を利用して、関数scanf()を含むソースコードをビルドすると、ソースコードがC言語のルールを満たしていたとしてもワーニングが出力されます。これは、Microsoft社がセキュリティ上の脆弱性がある関数scanf()の代替として独自に対策を施した関数scanf_s()を使いなさいとの警告です。このワーニングを回避するには以下のような複数の方法があります。

方法1:scanf_sを直接使う
 scanfを使わずにscanf_sを利用するようにします。この方法のデメリットはMS Cコンパイラ以外のコンパイラではエラーとなってしまう点です。

方法2:警告を抑制する
 ソースコードの先頭に以下の1行を追加することで、C言語の標準関数によって引き起こされるワーニングを抑制することができます。この方法では、MS Cコンパイラ以外のコンパイラにも対応できます。
#define _CRT_SECURE_NO_WARNINGS
方法3:警告をオフにする
 ソースコードに以下の1行を追加することで、そのファイル内の警告をオフにします。アンセキュアな状況を回避する訳ではないことに注意が必要です。
#pragma warning(disable : 4996)
 プロジェクト単位で警告をオフにしたい時は、IDEで以下の設定を行います。
  1. メニューから[プロジェクト] -> [プロジェクト名のプロパティ]を開く。
  2. 左側ペインの[構成プロパティ] - [C/C++] - [詳細設定]を選択する。
  3. [指定の警告を無効にする]のプロパティを編集して4996に設定し、OKする。

方法4:scanf_sを再定義して使う
 scanfの記述をscanf_sに常に置き換えるように、以下の1行をプリプロセッサに追加します。MS Cコンパイラ以外の時にはこの1行をコメント化することで対応できるようになります。ただし、scanf_sは文字配列(char型配列)に対しては第3引数を必要とするため、この方法では解決できません。
#define scanf scanf_s

番外編:代わりにfgetsを使う
 標準関数であるfgetsを代わりに利用します。そうすれば、標準関数ではないscanf_sを使うことなく、また、ワーニングを回避するといった本質的ではない方法を使わずに済みます。ここではfgetsの使い方については触れません。

expand_lessBack to TOP

演習問題

  1. あなたのプロフィール(氏名、学籍番号、所属、趣味など)を表示するプログラムex1-1.cを作成しなさい。

  2. あなたの名前のイニシャルを下図のように、一文字に縦5個、横7個の文字を使って表示するプログラムex1-2.cを作成しなさい。
    ex2-1

  3. 次のプログラムex1-3.cには3つの間違いがあります。正しく動作するように修正しなさい。
  4. ex1-3.c
    int main(void)
    {
    	printf("足し算 2017+4=%d, 2017+4)
    	
    	return 0;
    }
    

  5. 12+34+56の計算式とその計算結果を表示するプログラムex1-4.cを作成しなさい。

  6. 次のプログラムex1-5.cの実行結果を予測しなさい。次に、実際にこのプログラムを実行して、その結果が予測と一致したか確認しなさい。もし、予測が外れた場合にはその原因について調査しなさい。
  7. ex1-5.c
    #include <stdio.h>
    
    int main(void)
    {
    	printf("%d\n", 66/11/3);
    	printf("%d\n", 6*3-5*2);
    	printf("%d\n", 1+2+3*4/2);
    	printf("%d\n", 1+(2+3)*4/2);
    	printf("%d\n", 9/2);
    	printf("%f\n", 9.0/2.0);
    	printf("%f\n", 9.0/2);
    	printf("%f\n", 9/2.0);	
    
    	return 0;
    }
    
  8. 次のプログラムの実行結果を予測しなさい。
  9. ex1-6.c
    #include <stdio.h>
    
    int main(void)
    {
    	int a,b;
    
    	a = 2;
    	b = 3;
    	a = a + 1;
    	b = b + a;
    	printf("a=%d, b=%d\n", a,b);
    	
    	return 0;
    }
    
  10. 次は、二つの整数を入力して除算の結果とその余りを表示するプログラムです。空欄を埋めて完成させなさい。
  11. ex1-7.c
    #include <stdio.h>
    
    int main(void)
    {
    	[[空欄ア]] a,b;
    
    	printf("被除数,除数> ");
    	scanf("%d,%d", [[空欄イ]]);
    
    	printf("%d ÷ %d = %d 余り %d\n", [[空欄ウ]]);
    
    	return 0;
    }
    

  12. 次のプログラムは実数値を入力してその2乗値求めます。空欄は埋めてプログラム完成させなさい。
  13. ex1-8.c
    #include <stdio.h>
    
    int main(void)
    {
    	[[空欄ア]] x;
    
    	printf("実数の2乗値を求めます。\n");
    	printf("実数> ");
    	scanf("%lf", [[空欄イ]]);
    
    	printf("%f\n", [[空欄ウ]]);
    
    	return 0;
    }
    

  14. 次は台形の上底と下底の長さと高さを入力して、その面積を求めるプログラムです。空欄を埋めて完成させなさい。但し、得られた面積の値は小数点以下2桁まで表示すること。
  15. ex1-9.c
    #include <stdio.h>
    
    int main(void)
    {
    	[[空欄ア]] upper,lower,height,area;
    
    	printf("台形の面積を求めます。\n");
    	printf("上底(m)> ");
    	scanf("%f",&upper);
    	printf("下底(m)> ");
    	scanf("%f",[[空欄イ]]);
    	printf("高さ(m)> ");
    	scanf("%f",&height);
    
    	area = [[空欄ウ]];
    
    	printf("面積:[[空欄エ]]平方メートル\n", area);
    
    	return 0;
    }
    

  16. 三角形の底辺の長さと高さを入力して、その面積を求めるプログラムex1-10.cを作成しなさい。但し、得られた面積の値は小数点以下1桁まで表示すること。

  17. 円の直径の長さを入力して、その円の面積を求めるプログラムex1-11.cを作成しなさい。但し、得られた面積の値は小数点以下3桁まで表示すること。

  18. 整数を入力して1桁目のみを表示するプログラムex1-12.cを完成させなさい。(ヒント:剰余演算)
  19. ex1-12.c
    #include <stdio.h>
    
    int main(void)
    {
    	int num
    	
    	printf("整数 >> ");
    	scanf("%d", &num);
    	
    	printf("%dの一桁目の値は、%dです\n", num, [[空欄ア]]);
    	
    	return 0;
    }
    

  20. 日本円とUSドルの為替レートを入力してUSドルに換算するプログラムex1-13.cを作成しなさい。ドルとセントに分けて表示しなさい。但し、得られた値に小数は含めないものとする。

  21. 次のプログラムは整数を入力して何を求めているでしょうか?
  22. ex1-14.c
    #include <stdio.h>
    
    int main(void)
    {
    	int a0,a1,a2,a3,a4,a5,a6,a7;
    	int d1,d2,d3,d4,d5,d6,d7,d8;
    
    	printf("整数(0-255)>> ");
    	scanf("%d", &a0);
    
    	d1 = a0%2;
    	a1 = (a0-d1)/2;
    	d2 = a1%2;
    	a2 = (a1-d2)/2;
    	d3 = a2%2;
    	a3 = (a2-d3)/2;
    	d4 = a3%2;
    	a4 = (a3-d4)/2;
    	d5 = a4%2;
    	a5 = (a4-d5)/2;
    	d6 = a5%2;
    	a6 = (a5-d6)/2;
    	d7 = a6%2;
    	a7 = (a6-d7)/2;
    	d8 = a7%2;
    
    	printf("%d%d%d%d%d%d%d%d\n",d8,d7,d6,d5,d4,d3,d2,d1);
    	return 0;
    }
    

OPEN ANSWER
  1. 省略

  2. 省略

  3. 修正点

  4. 1) 1行目前に #include <stdio.h> を挿入
    2) 3行目の文字列を"で閉じる  "足し算 2017+4=%d",
    3) 3行目の行末に;を追加 );
  5. ex1-4.c
  6. #include <stdio.h>
    int main(void)
    {
    	printf("12+34+56=%d", 12+34+56);
    	
    	return 0;
    }
    
  7. 省略

  8. 省略

  9. ア.int イ.&a, &b ウ.a, b, a/b, a%b

  10. ア.double イ.&x ウ.x*x

  11. ア.float イ.&lower ウ.(upper+lower)*height*0.5 エ.%.2f

  12. 回答例
  13. #include <stdio.h>
    
    int main(void)
    {
    	double base,height;
    
    	printf("三角形の面積を求めます。\n");
    	printf("底辺(m)> ");
    	scanf("%lf",&base);
    	printf("高さ(m)> ");
    	scanf("%lf",&height);
    
    	printf("面積%f平方メートル\n",base*height*0.5);
    
    	return 0;
    }
    
    
  14. 回答例
  15. #include <stdio.h>
    
    int main(void)
    {
    	double r;
    
    	printf("円の面積を求めます。\n");
    	printf("直径(m)> ");
    	scanf("%lf",&r);
    
    	printf("面積%f平方メートル\n",3.14159265*r*r*0.5*0.5);
    
    	return 0;
    }
    
  16. 回答例
  17. ア.num%10

  18. 回答例
  19. #include <stdio.h>
    
    int main(void)
    {
    	int yen,doll,cent;
    	float rate;
    
    	printf("日本円をUSドルに変換します。\n");
    	printf("日本円> ");
    	scanf("%d",¥);
    	printf("為替レート(円/ドル) ");
    	scanf("%f",&rate);
    	
    	doll = yen/rate;
    	cent = (yen-doll*rate)*100/rate;
    
    	printf("%dドル%dセント\n",doll,cent);
    
    	return 0;
    }
    
  20. 10進数・2進数変換


expand_lessBack to TOP

確認テスト


理解度クイズ

  1. ファイルsample.cは何のファイルでしょう。
  2. ソースコードファイルをコンパイルした際のエラーとワーニングの違いは何?
  3. "A"は文字列である。正しい?正しくない?
  4. printf("A\n\n\nB");を実行した時の正しい表示結果が予想できる。
  5. #include<stdio.h>の役割を説明できる。
  6. "3+5"の評価結果は"8"になる。正しい?正しくない?
  7. 式7/2の評価結果はいくつ?

  8. x=5; の時、x=x+1; の処理結果は6になる。正しい?正しくない?
  9. 0,1,2,3,4,5,6,...といった値を扱いたいときに、使う変数の型はint型である。正しい?正しくない?
  10. 次のプログラムの間違いを見つけよう。

  11.  #include <stdio.h>
    
    int main(void)
    {
    	int a,b;
    	
    	a = 2;
    	b = 3;
    	printf("%d + %d = %d¥". a,b,a+b);
    	
    	return 0:
    {
    


    確認テスト解答:
  • 1. (1)×、(2)○、(3)×、(4)×、(5)×
  • 2. (1)○、(2)×、(3)○、(4)×、(5)○
  • 3.
    			                3 + 7 = 10
    			                12 - 5 = 7
    			                 3 * 2 = 6
    			                15 / 2 = 7
    			                15 % 2 = 1
    		                
  • 4. ア. %d + %d = %d\n

提出課題

以下の各プログラムを作成しなさい。
  • 課題1
  • 整数aを読み込んで、aの3乗値を表示するプログラム。

  • 課題2
  • 長方形の縦と横の長さを読み込んで、その長方形の面積と周の長さを表示するプログラム。

  • 課題3
  • 秒数sを読み込んで、h:m:sの形式へ変換して表示するプログラム。ここで、hは時間、mは60未満の分、sは60未満の秒とする。

 

  • [提出方法]
    1. ideone.comでの実行結果を含むURLをCoursePowerへ提出のこと。
    2. プログラムの正当性について、コメントを記すこと。
    3. [例] 各課題とも、複数回異なる値を与えて得られた結果と期待される結果を比較することで、正しい結果が得られることを確認した。
    4. 詳細はスライド「ideoneの使い方」参照のこと。

  • [評価について]
  • プログラムの内容の評価とは別に以下の要件を満たすことを評価の前提とする。
    1. C言語で記述されていること。
    2. ideone.comでの実行結果にワーニングやエラーが出力されていないこと。
    3. 所定の実行結果が得られるていること。
    4. ソースコードは、インデントや適当な改行が施された見やすい状態であること。

  • [提出期限]
  • 2023年 4月17日(月)までとする。ただし、以降の提出も受け付ける。