2010年第1回C言語講座資料

出典: ソフメWiki

目次

Hello World

最初に世界一有名なプログラムである「Hello World」を紹介したいと思います。

  1. #include <stdio.h>  /*プログラムを書く際のおまじない*/
  2.  
  3. int main()
  4. {
  5.   printf("Hello, World!\n");   //Hello,World!という文字列を出力
  6.   return 0;
  7. }

このプログラムをコンパイルして、実行すると

Hello, World!

と表示されます。 コンパイルに失敗してエラーが発生したり、表示された内容が違う場合は入力ミスがないか確認してください。

1行目:#include <stdio.h> 
includeディレクティブと呼ばれるもので、後で説明するprintf関数と呼ばれるものを使うために必要になります。詳しい説明は後の講座で行うので、今はプログラムを書く際の「おまじない」として、こういう記述が必要だということだけ覚えておいてください。
3,4行目:int main() { から 7行目 } まで 
main関数と呼ばれるものを定義しています。コンソールのアプリケーション(文字だけのアプリケーション)では、このmain関数が初めに実行される処理(エントリーポイント)となっているので、必要になります。 プログラムの処理はint main()のあとの「{ }」の間に書くと覚えておけば良いでしょう。
5行目:printf("Hello,World!\n"); 
printfは関数と呼ばれるもので、簡単に言ってしまえばコンピュータへの命令文の一つです。この関数でHello,World!という文章を画面に出力させています。ダブルクオーテーション(")で囲まれた文字の並びは文字列であると解釈されます。その文字列を 引数(ひきすう)(printf の後の丸括弧の中に入れたもの)としてprintfを呼び出すと、引数として受け取った文字列が出力されます。 文字列の中の「\n」は改行を表すエスケープシーケンスと呼ばれるものです。C言語では
 printf("Hello,World!
");

というように文字列の中でそのまま改行をすることはできないので、別の文字の並びを使用して改行を表現しています。 このように文字列の中で直接表現できない文字のために、様々なエスケープシーケンスが用意されています。ここではその一部を紹介します。

エスケープシーケンスの例
エスケープシーケンス意味
\n改行文字
\tタブ
\0ヌル文字(文字列の終端)
\\「\」という文字
\'「'」という文字
\"「"」という文字

この他にもエスケープシーケンスはあるので、興味があったら調べてみてください。


6行目:return 0; 
ここまで処理をしたらメイン関数は終了します。このreturnについても後々解説しますので、今はmain関数の最後にこの文を書くものだと覚えておいてください。

 また、5,6行目の文末にセミコロン(;)がありますが、これはそこまでが一つの文(命令)であることを示すものです。セミコロンを付け忘れてエラーが出てしまうことがよくあるので、しっかりセミコロンがあるか確認しましょう。 また、1行目の/*と*/で囲まれた部分と5行目の「//」の後の部分はコメントで、コンパイルの際には無視されて何もない空白と同じ意味になります。入力をしなくても動作は変わりませんが、後からプログラムを見たときに分かりやすいように説明などを書くことができます。 /*~*/は複数行を一気にコメントにすることができ、「//」は「//」の後の部分から行の終わりまで一行だけコメントにできます。

 今少し書いたようにプログラムにおいて空白(半角スペース・改行・タブ)は意味を持たないので、極端な話すべてを一行で書いてもエラーにはなりません。しかしプログラムが見にくいと後から修正・追加するのが大変なので、できるだけ見やすく書くことをお勧めします。

変数

ゲームではキャラクターの能力や得点等、様々なデータが存在しています。(ゲームでなくてもそうですが) そのデータを保存・変更・使用する方法を説明していきます。 一言にデータといっても、数値・文章・画像等様々な種類があります。コンピュータはそのデータが数値なのか、文章なのかという区別をしているわけではありません。全て2進数の0と1で処理されているからです。そこでC言語等の高級言語ではデータの種類を表すための型(type)という概念があります。 C言語では全てのデータがこの型を持っていて、このデータの事を値(value)と言います。

主な型の一覧(x86などの例)
型名サイズ値の範囲意味
int4バイト-2147483648~2147483647整数
unsigned int4バイト0~42649672965整数(符号なし)
short2バイト-32768~32767整数(short≦int)
unsigned short2バイト0~65535整数(符号なし)
long4バイト-2147483648~2147483647長整数(long≧int)
unsinged long int4バイト0~42949672965長整数(符号なし)
float4バイト1.2×10^-38~3.4×10^38単精度浮動小数点数
double8バイト2.2×10^-308~1.8×10^308倍精度浮動小数点数
long double10バイト3.4×10^-4932~1.2×10^4932浮動小数点数(long double≧double)
char1バイト-128~127文字
また、整数型はunsignedを前につける(例:unsigned int)と、0以上のみを表現する符号無し整数となります。特に何もつけなければ符号付き整数となります。また、この中で特によく使うものはint型,double型,char型の3つです。

特定の型の値を保存するため、メモリ上の場所に名前をつけたものが変数です。 イメージ的には好きなデータ(値)を入れることのできる箱だと思うと分かりやすいと思います。 まずは変数を使用したサンプルコードを見ていきましょう。

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.     int a;        /*int型の変数aを定義*/
  6.     double b;     /*double型の変数bを定義*/
  7.  
  8.     a = 1;        /*変数aに 1 を代入*/
  9.     b = 2.34;     /*変数bに 2.34 を代入*/
  10.  
  11.     printf("a = %d\nb = %f\n",a,b);    /*aとbの値をそれぞれ出力*/
  12.  
  13.     return 0;
  14. }

このプログラムの実行結果は

a = 1
b = 2.340000

となります。

5,6行目:int a; double b; 
int型のaという名前の変数と、double型のbという名前の変数を定義(宣言)している文です。これ以降はaをint型の変数として、bをdouble型の変数として扱うことができます。
8,9行目:a = 1; b = 2.34; 
変数aに型のintと同じ整数の「1」を、変数bに型のdoubleと同じ実数(小数)の「2.34」を代入しています。「=」は数学では等号を表しますが、C言語においては「左辺の変数に右辺の値を代入する」という意味になります。

変数使用時の注意

変数を使うときにはいくつか注意する点があります。

まずは変数の名前です、変数の名前は基本的には自由に付けられますが次のような規則があります。

1.変数名に使用できる文字はアルファベット・数字・アンダーバー(_)のみ

アルファベット・数字・アンダーバー以外の、かな文字・漢字・記号などは使用できないので注意してください。
アンダーバー(_)は複数の単語からなる変数名を単語ごとに区切ったりするのに良く使います。
例) number,enemy2,long_name等

2.名前の先頭文字に数字は使用不可

書いてある通り、 01num,02num 等の数字を先頭においた変数名は使用できません。

3.C言語で特別扱いされている名前や、登録されている名前は使用不可

先程出てきた型名として扱われている名前(intやdouble)や、main,printf等、変数や関数で使用されている名前を使うことはできません。

4.大文字と小文字は区別される

例えば name という変数と Name という変数を両方定義すれば、別の変数として扱われます。

この4つの規則さえ守っていればどんな名前でもつけることができますが、「a1」「a2」・・・のような名前をつけてしまうと変数にどんな値が含まれているのかが分かりにくいので、変数に入れる値と関係のある名前にすることをお勧めします。


また、変数をプログラム中で使用する前には必ず値を代入してから使用してください。 変数を宣言しただけでは変数の中にはどのような値が入っているかわからない(0が入っているとは限らない)からです。 この部分が抜けている状態でプログラムを実行してしまうと、 起動するたびに違った値が変数に入ってしまい、プログラムが正しく動作しなくなってしまうので注意してください。 上のプログラムでは8,9行目でそれぞれの変数に値を代入しています。

では、プログラムの解説に戻ります。

11行目:printf("a = %d\nb = %f\n",a,b)
printfの1つ目の引数の文字列は書式化文字列というもので、その先の引数を様々な書式で出力することを可能にしています。(なお、引数と引数は「,」で区切られています) 今回の文字列の中にある%dや%fは変換指定というもので、%dは次の引数を整数として、%fは次の引数を小数として出力する、という物です。最初に書かれた%dは2番目の引数のaに、後に書かれた%fは3番目の引数のbに対応しています。

変換指定について

今回の%dや%fのような後の引数の種類と表示形式を指定する者を変換指定子と言います。ここではまず主な変換指定子の例をあげておきます。

良く使う変換指定子
変換指定子意味
d,i符号付き整数(10進数・int)
u符号無し整数(10進数・unsigned int)
o符号無し整数(8進数)
x,X符号無し整数(16進数 Xは大文字で出力する)
f小数形式(float・double)
c文字
s文字列
pポインタの値(後の講座で説明)
%「%」を出力する

さらに変換指定子の前には長さ修飾子というものを入れることもあります。

長さ修飾子の例
修飾子意味
hshort型(%hdなど)
llong型(%ldなど)
Llong double型(%Lfなど)

また、dやfの前に数値を入れることで、出力する引数に使う最小の文字幅や小数点以下の桁数(文字列の場合は取り出す文字数)を設定することができます。 最小の文字幅の事をフィールド幅、小数点以下の桁数や取り出す文字数の事を精度と言います。小数の精度は設定しなかった場合は6桁となります。 言葉だけでは分かりづらいと思うので例を見てみましょう。


  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5. 	long a = 99;
  6. 	double b = 1.123456;
  7.  
  8. 	printf("%4ld\n",a);    /*long (int)型の変数aをフィールド幅4で出力*/
  9. 	printf("%f\n",b);      /*double型の変数bを出力*/
  10. 	printf("%8.3f\n",b);   /*変数bをフィールド幅8、精度3で出力*/
  11. 	printf("%8.0f\n",b);   /*変数bをフィールド幅8、精度0で出力*/
  12.  
  13. 	return 0;
  14. }

このプログラムの実行結果は

  99
1.123456
   1.123
       1

となります。 なお、5,6行目にlong a = 99; double b = 1.123456; と書かれています。 このように変数を定義(宣言)すると同時に値を設定することも可能で、この事を初期化といいます。


ここでは書式化文字列において良く使うと思われる物を紹介しましたが、この他にも様々な書式設定が存在するので興味のある人はぜひ調べてみてください。 文字列の出力は基本的な部分ですが非常によく使うものなので、使い方をしっかり覚えておきましょう。

算術演算子

演算子とは名前の通り演算を表す記号の事です。「1 + 1」の「+」が演算子です。 私たちが普段使う四則演算以外にも様々なものがあるので表にまとめたものを見ていきましょう。

※下の表での 変数aは int型で、値として「5」が入っている事とします。(int a = 5;)

算術系の演算子
演算子意味書き方の例例の結果
+和を計算(加算演算子)5 + 27
-差を計算(減算演算子)5 - 23
*積を計算(乗算演算子)5 * 210
/商を計算(除算演算子)5 / 22
%割った余りを計算(剰余演算子)5 % 2 1
=代入(代入演算子)a = 2aの値は2
+=加算して代入(加算代入演算子)a += 2aの値は7 (a = a + 2)
-=減算して代入(減算代入演算子)a -= 2aの値は3 (a = a - 2)
*=乗算して代入(乗算代入演算子)a *= 2aの値は10 (a = a * 2)
/=除算して代入(除算代入演算子)a /= 2aの値は2 (a = a / 2)
%=割った余りを代入する(剰余代入演算子)a %= 2aの値は1 (a = a % 2)
++変数の値に1加算する(インクリメント演算子)a++aの値は6
--変数の値から1減算する(デクリメント演算子)a--aの値は4

演算子はこれ以外にもたくさんの種類がありますが、計算に良く使用するものは大体この様になっています。 それでは演算子を使用したプログラムを見ていきましょう。

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.     int num;    /* int型変数numを定義 */
  6.     int num2;   /* int型変数num2を定義 */
  7.  
  8.     num = 5 % 2;    /* 5 % 2の結果(=1)をnumに代入 */
  9.     printf("num = %d\n",num);    /* numの値を出力 */
  10.  
  11.     num = 2 + 3 * 4;     /* 2 + 3 * 4の結果(=14)をnumに代入、演算順序は通常の四則演算と同じ */
  12.     printf("num = %d\n",num);    /* numの値を出力 */
  13.  
  14.     num -= 5;      /* 現在のnumの値(=14)から5をマイナスした結果(=9)をnumに代入 */
  15.     printf("num = %d\n",num);    /* numの値を出力 */
  16.  
  17.     num++;        /* numの値に1をプラスした結果(=10)をnumに代入 */
  18.     printf("num = %d\n",num);    /* numの値を出力 */
  19.  
  20.     num2 = 9;     /* num2 の値に9を代入 */
  21.     printf("num + num2 = %d\n",num + num2);  /* num + num2 の値を出力 */
  22.  
  23.     return 0;
  24. }

出力結果は

num = 1
num = 14
num = 9
num = 10
num + num2 = 19

となります。

この演算子の事をオペレータともいい、演算の対象となる値や変数の事をオペランドと言います。 演算子の左側のオペランドを左オペランド、右側のオペランドを右オペランドと呼びます。

%演算子は普段の数学ではあまり使わないような計算ですが、プログラミングでは奇数や偶数などを判断するときによく使ったりするので、きちんと使いこなせるようになりましょう。

例題にもありましたが、演算子には計算する優先順位があります。四則演算などがそうです。この他にもたくさんあるので、そちらについては次の講座で解説します。

値を入力する

ここまでは画面に文字や数字を出力する方法を勉強してきました。今度はユーザ側から値を入力するプログラムを作ります。 ユーザから入力を受け取ることによりいっそう面白いプログラムができます。 では、キーボードからの入力を受け付ける簡単なプログラムを作ってみましょう。

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.     int num;      /* int型の変数 num を定義 */
  6.  
  7.     printf("整数値を入力してください:");       /* 入力要求(プロンプト)を表示 */
  8.     scanf("%d",&num);                           /* 整数を入力し、変数numに代入 */
  9.     printf("入力された値は %d です。\n",num);   /* 入力した値を表示する。 */
  10.  
  11.     return 0;
  12. }
8行目:scanf("%d",&num); 
ユーザから整数値の入力を受け取るためにscanf関数を使用している文です。ここの%dは先程書いた変換指定子と同じで整数を意味しています。このようにscanfはprintfと似た使い方をすることができますが、次の引数にある変数名の初めに&がついて&numとなっていることに注意してください。この&の意味などは「ポインタ」と呼ばれる部分で詳しい解説をするので、とりあえずはscanfを使って変数に値を入力する時には、変数名の前に「&」をつけると覚えておいてください。

このプログラムを実行するとまず

整数値を入力してください:

と、表示されて入力を待ちます。 ここで例えばキーボードから「2」を入力してエンターキーを押すと

整数値を入力してください: 2
入力された値は 2 です。

このように入力した値が表示されます。色々な整数を入力して結果を確認してみてください。

scanfについての注意

今使ったように、scanfはprintfと同じように使う事が出来る便利な関数であることから、この講座資料以外でも色々な教科書で使用されています。しかし、scanfはいくつもの危険な部分を持っている関数でもあります。 特に文字列を読み込むための書式指定である %s を使用する時は、セキュリティホールとなるバグの1つであるバッファオーバーランの危険を持っています。 よって、大学での講義や、この講座等のC言語の練習・演習以外の実用的なプログラムで使用することは避けましょう。 ここでは演習用と言う事で使用していきます。 今の所は int型 を読み込むための %d と double型 を読み込むための %lf を覚えておいてください。 なお、Visual C++ 2005以降の開発環境を使用して scanf を使用したプログラムをコンパイルしようとすると警告文が表示されますが、先ほど言ったように実用的なプログラムでなければ無視してしまってかまいません。

課題

  1. int型の変数を定義して、その変数に整数の入力を受け取り表示するプログラムを作ってみましょう。
  2. 同様にdouble型のプログラムを作りましょう。
  3. int型の変数を二つ定義して値を受け取り、二つの変数を加算して表示するプログラムを書いてみましょう。
  4. 開発環境のセットアップをして、自宅PCで実行・コンパイルをしてみましょう。また、資料に書かれているプログラムを打ち込んでみましょう。
個人用ツール