C言語の基礎
C言語,ソースファイルの作成,コン パイル,実行
A-1
C言語
• プログラムとは,“計算機を動かす手順を 記述したもの”.
– 計算機に命令を与えて動かすには“プログラ ムを作成する”ことになる.
• C言語はプログラミング言語の1個 – 手続き型言語に分類される.
– C/C++ は非常に多くの場面で使われる言語
• C++はC言語をオブジェクト指向に拡張したもの
A-3
C言語プログラミングの手順
• ソースファイルを作成し,コンパイルし,実 行.
ソースファイル source file
C言語 人間が記述する.
実行ファイル executable exe
マシン語 通常人間に読めない
“hello.c” “hello.exe”
コンパイルする compile
コンパイラcompiler (Visual C++, gcc, bcc など)
・C言語では,ソースファイルを直接実行することができない.
ソースファイルをコンパイルして実行ファイルを作成し,実行ファイルを実行する.
・“ソースファイル” を “原始ファイル” と呼ぶこともある(ごくまれ).
・実行ファイルの拡張子はOSに依存する.Windows では “.exe” となる.
・厳密には,コンパイルとリンク(link)を行い実行ファイルを作る.
A-4
コンパイルとリンク
ソースファイル
“abc.c”
ソースファイル
“def.c”
エディタ エディタ
コンパイル
コンパイル
オブジェクト ファイル
“abc.o”
オブジェクト ファイル
“def.o”
標準ライブラリ コンパイラ
コンパイラ
リンク 実行ファイル
“xyz.exe”
リンカ
A-5
C言語のソースファイルの骨格
#include <stdio.h>
void main(){
}
ヘッダ(header)ファイルの 読み込み.
先頭に必ず書く.
ここにプログラムの本体を 記述する.
void main(){
と }
でプログラム本体を 挟む
void main(){
と }
でプログラム本体を 挟む
A-6
何も起きないプログラム
1 #include <stdio.h>
2
3 void main(){
4 }
半角で記述する.大文字と小文字は明確に区別される.
上記を入力し,実行する.
Error メッセージ,Warning(警告)メッセージ を確認する.
Errorは明確な誤りへのメッセージ
Warningは誤りではないが好ましくないことへのメッセージ
A-7
文字列を表示するプログラム
1 #include <stdio.h>
2
3 void main(){
4 printf("Hello, World!¥n");
5 }
“Hello world!” と 表示するプログラム.
printf を 使えば,” ” で囲った文字列を表示できる.
“¥n”は,改行を意味する.
printf(“Hello¥nWorld!¥n”);
として実行.動作を確認.
C言語の式と文
式
a 10 3+4 a+4 a++ a = 7
3 < a "hello" printf("hello")
文
(式文
)は 式
;printf("hello"); a=3; a++; a;
正しいが,
通常あり得ない
C言語の文 (関数の呼び出し)
printf("Hello, World!¥n");
関数の引数は()で囲み,中に式を書く.
関数名 関数の引数 セミコロン
A-10
文字列を表示するプログラム
1 #include <stdio.h>
2
3 void main(){
4 printf("Hello,¥n");
5 printf("C lang.¥n");
6 printf("World!¥n");
7 }
hello01.c
上 か ら 下 に 進 む
A-11
インデントとフリーフォーマット
#include <stdio.h>
void main(){
int i;
for(i=0; i<5; i++){
printf("i=%d¥n", i);
} }
プログラム内の 空白,TAB文字,改行は 無視される.
よって,どのように 書いても問題ない.
当然,見やすく書くことが 好ましい.
#include <stdio.h>
void main(){
int i;
for(i=0; i<5; i++){
printf("i=%d¥n", i);
} }
#include <stdio.h>
void main(){ int i; for(i=0; i<5; i++){ printf("i=%d¥n", i); }}
↑理解が困難.対応関係が分かりづらい.
#include <stdio.h>
void main(){
int i;
for(i=0; i<5; i++){
printf("i=%d¥n", i);
} }
↑対応関係が誤り.
↑対応関係がわかりづらい.
A-12
コメント
1 #include <stdio.h>
2
3 void main(){
4 /* print hello */
5 // print hello 6 printf("Hello,¥n");
7
8 /*
9 printf("World!¥n");
10 */
11 }
hello02.c
/* と*/ で挟まれた領域は,
コメントとして 無視される.
実行されない.
// から行末までの領域も,
コメントとして無視される.
実行されない.
ただし,これはC++の機能であり C言語の機能ではない.
(実際はほとんどのC言語のコンパ イラにこの機能が付いている) コメント部にはデタラメに書 いても問題ない.
正しいC言語の文も無視さ れる.
A-13
数値計算を行う
変数,演算
A-14
型
• 整数型(符号付き,符号とは+か-)
– char型,short int型,int型,long int型,long long int型
– 整数を格納.格納できる値の範囲(最大値,最小値)と,消費メ モリが異なる
– サイズは処理系依存.charは必ず1バイト.intは最近は4バイ トであることがほとんど.
– charは-128以上127以下の値を格納可能
• 整数型(符号無し)
– unsigned char型,unsigned short int型,unsigned int型,…
– unsigned charは0以上255の値を格納可能
A-15
型
• 浮動小数点型
– float型,double型
–
消費メモリサイズと精度が異なる
–計算処理速度が異なる.
•実はdoubleの方が速いことも…
A-16
演算子
• + 加算
• - 減算
• * 乗算
• / 除算
• % 剰余
A-17
• x+=2 xが2増える
x=x+2 と同じ
• x-=2 xが2減る
X=x-2 と同じ
• x*=2 xが2倍になる
x=x*2と同じ
• x/=2 xが半分になる
x=x/2 と同じ
• x++ xが1増える
x+=1 と同じ
• x-- xが1減る
x=-1
と同じ
演算結果の型
• X型とX型の演算結果はX型.
int a=7, b=2;
double d;
d = a + b;
d = a / b;
a + b はint型とint型の演算.
演算結果もint 型.
a+b は9 (int型).
dには9.0 (double型)が入る.
a / b はint型とint型の演算.
演算結果もint 型.
a / b は3 (int型).
dには3.0 (double型)が格納される.
3.5 は格納されない.
A-18
演算結果の型
• X型とY型の演算結果はXorY型.
優先度の高い型が勝つ.
double > float > long > int > char
の優先順
int a=7;double d=2.0, e;
e = a / d;
a / b はint型とdouble型の演算.
double型が勝つので,
演算結果はdouble型.
7.0 / 2.0 と解釈され,
演算結果は3.5 (double型).
A-19
演算結果の型
double d;
d = 7 / 2; /* intとintの演算.結果はintの 3 */
d = 7 / 2.0; /* intとdoubleの演算.
結果はdoubleの3.5 */
d = 7.0 / 2; /* doubleとintの演算.
結果はdoubleの3.5 */
d = 7.0 / 2.0; /* doubleとdoubleの演算.
結果はdoubleの3.5 */
A-20
制御文
A-21
真偽
条件が成り立つ場合,その条件式は真であ る.
例えば,
(3 < 4) は真 true (3 == 4) は偽 false
A-22
比較演算子
a==b : aとbが等しい a!=b : aとbが等しくない a<b : bはaより大きい
a<=b : bはa以上(大きいか等しい) a>b : a は b より大きい
a>=b : a は b 以上
OK NG
!=
<=
>=
=!
=<
=>
注意!
比較 代入
a==b a=b
A-23
条件分岐 if 文
if( 条件式X ){
プログラムA
}if( 条件式X ){
プログラムA
} else {プログラムB
}式Xが真の場合(成り立つ場合),
中身(プログラムA)が 実行される.
偽の場合(成り立たない場合)は 何も実行されない.
条件Xが真の場合 前半のプログラムAが
実行され,
偽の場合(成り立たない場合) 後半(else部)の プログラムBが実行される
条件分岐 if 文
if( 条件式X ){
プログラムA
} else if( 条件式Y ){
プログラムB
} else if( 条件式Z ){
プログラムC
} else {プログラムD
}プログラムE
条件式Xが成り立つ場合,
プログラムAが実行され,
その後プログラムEに移る.
プログラムB,C,Dは全て“条件式Xのelse”の 中にあるため,たとえ条件式Yや条件式Zが成り立っ ても実行されない.
条件式Xが偽の場合に限り,条件式Yが検証さ れる.
条件式Xが偽で かつ 条件式Yが真 の場合,プ ログラムBが実行され,プログラムEに移る.
プログラムC,Dは実行されない.
条件式Xが偽,条件式Yが偽,条件式Zが真の 場合,プログラムC,Eが実行される.
全てが偽の場合,プログラムD, Eが実行され る.
条件分岐 if 文
1 #include <stdio.h>
2 void main(){
3 int a=12;
4 if( a < 10 ){
5 printf("a < 10 (a = %d)¥n", a);
6 } else {
7 printf("10 <= a (a = %d)¥n", a);
8 } 9 }
A-26
条件分岐 if 文
1 #include <stdio.h>
2 void main(){
3 int a=8;
4 if( a < 10 ){
5 printf("a < 10 (a = %d)¥n", a);
6 } else {
7 printf("10 <= a (a = %d)¥n", a);
8 } 9 }
A-27
条件分岐 if 文
#include <stdio.h>
void main(){
int a=8;
if( a < 10 ){
printf("A¥n");
}
printf("B¥n");
}
A B
実行結果
A-28
条件分岐 if 文
#include <stdio.h>
void main(){
int a=12;
if( a < 10 ){
printf("A¥n");
}
printf("B¥n");
}
B
実行結果
A-29
条件分岐 if 文
#include <stdio.h>
void main(){
int a=23;
if( 10 <= a ){
printf("A¥n");
}
if( 20 <= a ){
printf("B¥n");
}
if( 30 <= a ){
printf("C¥n");
} }
A B
実行結果
A-30
条件分岐 if 文
#include <stdio.h>
void main(){
int a=8, b=8;
if( a < 10 ){
if( b < 10 ){
printf("A¥n");
} else {
printf("B¥n");
} } else {
if( b < 7 ){
printf("C¥n");
} else {
printf("D¥n");
} }
} A
実行結果
A-31
条件分岐 if 文
#include <stdio.h>
void main(){
int a=12, b=8;
if( a < 10 ){
if( b < 10 ){
printf("A¥n");
} else {
printf("B¥n");
} } else {
if( b < 7 ){
printf("C¥n");
} else {
printf("D¥n");
} }
} D
実行結果
A-32
おまけ
著しく読みづらいソースコード
#include <stdio.h>
void main(){
int a=12, b=8;
if( a < 10 ){
if( b < 10 ){
printf("A¥n");
} else { printf("B¥n");
} } else { if( b < 7 ){
printf("C¥n");
} else { printf("D¥n");
} } }
A-33
論理演算子
条件 && 条件
論理積 (and) :両方成り立つ場合に真
条件 || 条件
論理和(or):少なくとも片方が成り立つ場合に真
!条件
否定(not):条件が成り立たないときに真.
真偽が逆転される
A-34
条件分岐 if 文
#include <stdio.h>
void main(){
int a=12, b=8;
if( a < 10 && b < 10 ){
printf("A¥n");
} else {
printf("B¥n");
} }
B
実行結果
A-35
条件分岐 if 文
#include <stdio.h>
void main(){
int a=12, b=8;
if( a < 10 || b < 10 ){
printf("A¥n");
} else {
printf("B¥n");
} }
A
実行結果
A-36
条件分岐 if 文
#include <stdio.h>
void main(){
int a=12, b=8;
if( ! (a<10||b<10) ){
printf("A¥n");
} else {
printf("B¥n");
} }
B
実行結果
A-37
真偽
厳密には,C言語には条件や真や偽はない.
値(式分)が「0以外」なら真,「0」なら偽とみ なす.
注意:NULL は「0」なので 偽 である.
if( 1+2 ){
プログラムA
} else {プログラムB
}if( 4-4 ){
プログラムA
} else {プログラムB
}「3」は真を意味する.
結果,プログラムAに入る
「0」は偽を意味する.
結果,プログラムBに入る
C言語になれるまでは,このような変な(?)表現は使わなくて良い.A-38
繰り返し for 文
int i;
for( i=0; i<5; i++){
処理A;
}
• 同じ処理を何度も繰り返すには for 文を使う.
処理Aを 5 回繰り返す.
int i;
for(i=0; i<3; i++){
printf("Hello!¥n");
}
Hello!
Hello!
Hello!
int i;
for(i=0; i<7; i++){
printf("World!¥n");
}
World!
World!
World!
World!
World!
World!
World!
例
結果
結果
A-39
繰り返し for 文
(i=0; i<3; i++)
「i が0 から3未満の範囲で(2まで),
繰り返す.i は1ずつ増える.」
という意味の 繰り返し.
i=0 → iが0から始まる.
i<3 → iが3未満である限り続ける i++ → i は1ずつ増える i が“0から3未満(2まで)”なので,
i =0, i =1, i=2 の3回繰り返す.
printf("Hello,¥n");
printf("World!¥n");
i=0 として
printf("Hello,¥n");
printf("World!¥n");
i=1 として
printf("Hello,¥n");
printf("World!¥n");
i=2 として int i;
for(i=0; i<3; i++){
printf("Hello,¥n");
printf("World!¥n");
}
printf("Hello,¥n");
printf("World!¥n");
printf("Hello,¥n");
printf("World!¥n");
printf("Hello,¥n");
printf("World!¥n");
繰り返し for 文
「i が10 から始まり13未満の範囲で
(12まで),繰り返す.i は1ずつ増える.」
という意味の 繰り返し.
結局,i=10, i=11, i=12 の3回繰り返す.
int i;
for(i=10; i<13; i++){
printf("i=%d¥n",i);
}
「i が0 から始まり6未満の範囲で,
繰り返す.i は2ずつ増える.」
という意味の 繰り返し.
結局,i=0, i=2, i=4 の3回繰り返す.
int i;
for(i=0; i<6; i+=2){
printf("i=%d¥n",i);
}
「i が2 から始まり0 以上の範囲で,
繰り返す.i は1ずつ減る.」
という意味の 繰り返し.
結局,i=2, i=1, i=0 の3回繰り返す.
int i;
for(i=2; 0<=i; i--){
printf("i=%d¥n",i);
}
繰り返し for 文
「i が10 から始まり,3未満の範囲で,
繰り返す.i は1ずつ増える.」
という意味の 繰り返し.
結局,(10<3が偽なので)1回も実行しない.
int i;
for(i=10; i<3; i++){
printf("i=%d¥n",i);
}
「i が3 から始まり,0以上の範囲で,
繰り返す.i は1ずつ増える.」
という意味の 繰り返し.
結局,無限に繰り返す.
int i;
for(i=3; 0<=i; i++){
printf("i=%d¥n",i);
}
「i が0 から始まり,無条件で,
繰り返す.i は1ずつ増える.」
という意味の 繰り返し.
結局,無限に繰り返す.
int i;
for(i=0; ; i++){
printf("i=%d¥n",i);
}
A-42
繰り返し for 文
int i;
for(i=0; i<3; i++){
printf("Hello,¥n");
printf("World!¥n");
}
printf("End¥n");
• 動作原理
i=0;
i<3?
printf("Hello,¥n");
printf("World!¥n");
i++;
printf("End¥n");
N Y
A-43
繰り返し for 文
i=0;
int i;
for(i=0; i<3; i++){
printf("Hello,¥n");
printf("World!¥n");
}
i<3?
printf("Hello,¥n");
printf("World!¥n");
i++; /*i=1となる*/
i<3?
printf("Hello,¥n");
printf("World!¥n");
i++; /*i=2となる*/
i<3?
printf("Hello,¥n");
printf("World!¥n");
i++; /*i=3となる*/
i<3?
終了
• 動作原理
A-44
繰り返し for 文
for( 式1; 式2; 式3 ){
プログラム
}最初に式1を行う 式2が真である限り,
ブロックの中身を繰り返す.
1回繰り返すたびに式3を 行う.
int i;
for (i=0; i<2; i++){
printf("i=%d¥n",i);
}
iが0になる.
i<2 の真偽を調べる.真である(i=0).
よって,forの中のブロックに入る.
printf()を実行.
ブロックが終わり,i++を行い,ブロックの 最初に戻る.
i<2 の真偽を調べる.真である(i=1).
よって,forの中のブロックに入る.
printf()を実行.
ブロックが終わり,i++を行い,ブロックの 最初に戻る.
i<2 の真偽を調べる.偽である(i=2).
よって,forを終了する. A-45
繰り返し for 文
• for文の中にfor文
int i, j;
for(i=0; i<3; i++){
for(j=0; j<4; j++){
printf("Hello¥n");
} }
黄:Helloと1回表示.
青:Helloと4回表示.黄色を4回繰り返す.
結果,4回×3回=12回繰り返す.
int i, j;
for(i=0; i<3; i++){
printf("Hello¥n");
printf("Hello¥n");
printf("Hello¥n");
printf("Hello¥n");
}
同義
A-46
繰り返し for 文
• for文の中にfor文
int i, j;
for(i=0; i<3; i++){
for(j=0; j<4; j++){
printf("i=%d,j=%d¥n",i,j);
} }
『printf() をj=0~3の4回繰り返す』を
i=0~2の3回繰り返す.結果,4回×3回=12回繰り返す.
A-47
繰り返し while 文
while( 条件式X ){
プログラムA
}int i=0;
while( i<2 ){
printf("i=%d¥n",i);
i++;
}
iが0になる.
i<2 の真偽を調べる.真である(i=0). よって,whileの中のブロックに入る.
printf()を実行.
i++ により i が1になる.
ブロックが終わり,ブロックの最初に戻る.
i<2 の真偽を調べる.真である(i=1).
よって,whileの中のブロックに入る.
printf()を実行.
i++ により i が2になる.
ブロックが終わり,ブロックの最初に戻る.
i<2 の真偽を調べる.偽である(i=2). よって,whileを終了する.
条件Xが真である限り,
中身(プログラムA)を 繰り返し実行する.
毎回,条件式を評価してから,
プログラムを実行する.
A-48
繰り返し do-while 文
do{
プログラムA
}while(条件式X );int i=0;
do{
printf("i=%d¥n",i);
i++;
} while( i<2 );
iが0になる.
printf()を実行.
i++ により i が1になる.
ブロックが終わり,i<2 の真偽を調べる.
真である(i=1).
よって,再度,whileブロックの中を実行.
printf()を実行.
i++ により i が2になる.
ブロックが終わり,i<2 の真偽を調べる.
偽である(i=2).
よって,再度,whileブロックの中を実行.
条件Xが真である限り,
中身(プログラムA)を繰り返し実行する.
毎回,プログラムを実行してから,
条件式を評価する.
よって,最低でも1回は実行される.
A-49
break による 繰り返しの中断
int i;
for(i=0; i<10; i++){
printf("i=%d¥n",i);
if( i==3 ){
break;
} }
printf(“Fin!¥n“,i);
i=0 i=1 i=2 i=3 Fin!
繰り返し中断
break; を実行すると,
繰り返しが中断される.
実行結果
A-50
無限ループ
for(;;){
printf("Hello, World!¥n");
}
while(1){
printf("Hello, World!¥n");
}
for文で条件部を書かないと,
無条件で繰り返し.
無限ループとなる.
while文で条件部に1と書くと,
条件が必ず成立するので 無限ループとなる.
(1は真偽における“真”である ため.)
A-51
例
1, 4, 9, 16, 25, 36,…,100 と出力
int i, x;
for(i=1; i<=10; i++){
x = i*i;
printf("%d¥n", x);
}
A-52
switch文
switch( 値X ){
case 値A:
プログラムA
break;case 値B:
プログラムB
break;default:
プログラムC
break;}
A-53
もし,値x が 値A と等しければ,
“case 値A:”までジャンプして,
そこから“break”まで実行.
もし 値B と等しければ,
“case 値B:”までジャンプして,
“break”まで実行.
もしどれとも等しくなければ,
“default:”までジャンプして,
“break”まで実行.
もしどれとも等しくなく,“default:”
がなければ,何も実行しない.
switch文
int i;
i= ?;
switch( i ){
case 1:
printf("one¥n");
break;
case 2:
printf("two¥n");
case 3:
printf("three¥n");
break;
case 4:
case 5:
printf("four or five¥n");
break;
default:
printf(“another");
break;
} A-54
i=1
なら
one i=2 なら two three i=3 なら three実行結果
i=4 なら four or five i=5 なら four or five i=6 なら another
配列
A-55
C言語:変数の宣言と利用
• 変数の宣言
i=3, d=5.700000 int i;
double d;
i = 3;
d = 5.7;
printf("i=%d, d=%lf¥n", i, d);
実行結果 プログラム
“ i ”という名前の整数型変数を宣言.
以後i を使用可能.
i は,整数を格納(記録)できる箱.
変数i に整数3 を代入.
以後, i には3 が入っている.
“ d ”という名前の 浮動小数点型変数を宣言.
C言語:配列の宣言と使用
• 配列
int data[3];
int i;
data[0] = 3;
data[1] = 4;
data[2] = 5;
for(i=0; i<3; i++){
printf("data[%d]", i);
printf("=%d¥n", data[i]);
}
data[0]=3 data[1]=4 data[2]=5
プログラム 実行結果
int
型が
3個の配列.
data[0]~data[2]
が使用可能.
"0から始めて,3未満"
で
for文を使うと やりやすい.
配列の宣言
(変数の作成)配列の使用
(作成済みの変数の使用)