本日前半の講義・演習予定
- プログラミングの準備
- はじめてのプログラミング
- ソースコードの書き方
- 文字、文字列、数値
- 計算してみよう
- 演算の優先順位
- 整数と小数点を含む数の演算
プログラミングの手順
プログラムの作成から実行までの操作手順を下図に示します。
- 手順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)に区別されます。
- 文字 : その文字をシングルクォーテーション(')で囲う
- 文字列: その文字列をダブルクォーテーション(")で囲う
- 数値 : 「式」として扱うときにはそのまま記述し、「文字列」として扱うときには書式指定子を使って変換する
以下のプログラムでは、文字、文字列、整数、浮動小数点数を画面に表示します。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/3 =>評価結果 0
- 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