C言語基礎編

C言語 「基礎編」

C言語の文法についてのレポート。

最近、C言語を研究中。僕も勉強中なのですが。

※何度も言いますが、勉強中なので、新しいことが分かったら

適宜改善、付け加え、修正をします。

※無断転載は禁止。転載したい時は僕にメール等で一声かけて下さい。


〜目次〜

0.なぜC言語?

1.文字の入出力

2.変数の使い方

3.変数の使い方その2

4.制御文の数々

5.配列

6〜



0.なぜC言語?


■C言語の特徴

まずプログラムは大別するとインタープリタとコンパイラに分かれます。
インタープリタの代表としてBASIC、コンパイラ型の言語の代表としてC言語があげられます。
世の中ではC言語が主流です。なぜC言語は普及しているのでしょう。
とりあえずBASICとC言語の違いについて述べておきます。
BASICは、ハッキリ言って単純です。なので、誰にでもかけます。
でも、そのうち限界を感じます。その理由の一つとして、
○遅い
ことがあげられます。それに比べC言語は速いです。なぜこのように違いが生じるのでしょう ?

そもそもプログラムがどう動くか考えてみます。
まず人間が書いたプログラムは機械(パソコン)には分かりません。
そこで、プログラムを機械が分かる言葉(以下、マシン語)に翻訳する必要があります。
このマシン語に翻訳する作業を、コンパイルと呼びます。

話を元に戻すと、インタープリタは、その場で実行できるかわりに、
実行時に翻訳しながら実行しています。対してコンパイラは、
実行前にコンパイルを終わらせてるので、あとはマシン語を実行するのみ!
と言うわけで、C言語はコンパイル分実行が速くできます。

C言語の利点は速いだけではありません。
BASICでは使えない関数や構造体等を使って、プログラムをきれいにまとめることが可能です。
そしてC言語は汎用性に優れています。あと基本的にBASICでできることはC言語でも出来ます。


■開発環境を手に入れよう


最後に、主な開発環境を紹介して、今回は終わりにします。

○Borland C .... Windowsで有名なコンパイラ。ただで入手可能。

○Visual C++ .... 市販のコンパイラ。Win対応。

○MPW     .... フリーのMac対応コンパイラ。

Borland Cの場合、テキストエディタがないので、有名なものを紹介します。

○CPad .... コンパイラのパスを渡すとと自動でコンパイルしてくれる

○BCC developer .... 普通はこちらを使いましょう。多機能で便利。

○ボーランド帳   .... CRenさん作のエディタ。ホームページから入手可。(リンクページからどうぞ)



1.文字の出力


■世界に挨拶を!

<サンプルプログラム>
#include <stdio.h &rt;
void main(){
  printf("Hello world");
}

はい。これをエディタに打ち込んで、コンパイルし、走らせましょう。
うまくいけば、「Hello world」と画面に表示されます。


では、ソースコードの解説。
1行目   #include <stdio.h&rt;
include・・・<>内にあるファイルを読み込む。
どう言う意味でしょう?
stdio.hには、普通の入出力の関数が書かれています。(関数についてはあとで話します)
このstdio.hというファイルが、全部このプログラムの一行目に読み込まれ、
三行目のprintfを使えるようになります。
ちなみに、拡張子(.h)がつくファイルは、ヘッダファイルと呼ばれ、
機能ごとにファイルに分割されています。
必要に応じてincludeして、その関数(命令)を使えるようにします。
また、#から始まる文は、プリプロセッサと呼ばれ、
コンパイル時に実行されます。


2行目   void main(){
まず、mainは、C言語の命令が始まった時、一番初めに呼ばれる関数です。
C言語は関数が次々に呼ばれて処理を実行するので、どこから始めるのか
コンピュータに教えなければいけないって訳です。
次にvoidって何? 何も値を返さないってことなんですが、
関数とは命令を実行させるだけでなく、その結果出た値を関数を呼び出した所に返すことができます。
このmainという関数は、何も値を返さないので、voidです。
関数の所でもう一度説明するので、今は分からなくていいですが。
次。()って何に使う?
関数は値を返すだけでなく、変数の値などをもらって、
それらをその関数の命令内で使うことができます。
()にはその渡す値(引き数といいます)を書くわけですが、
詳しいことはまたあとで。ここは()だから、なにも引き数がないと思ってください。
{は? 関数の始まりの印です。 反対に、}は関数の終わりの印です。


3行目。printf("Hello world");
このプログラムのメインです。Hello worldと画面に表示します。
printf("文字"); で画面に文字を出力できます。
;(セミコロン)は、文末の印。付け忘れないようにしてください。
よく見ると、この命令のあいだに、空白が入っていますが、なくてもいいんです。
ただ、空白が入っていると、「この関数の命令ですよ」というのが、
一目で分かります。


■今回のまとめ


mainは、プログラムで一番始めに呼びだされる。
○関数の始めと終わりは、{ }(中括弧)で区切る
printf("文字"); で画面に文字を表示できる。
○printfなどの命令の文末には「;」を忘れずつける。


2.変数の使い方


■変数の宣言、代入、表示

今回は変数の使い方を説明したいと思います。
下のサンプルを見て下さい。

<サンプルプログラム>
#include <stdio.h&rt;
void main(){
  int a;
						a=3;
      printf("a=%d",a);
}

実行結果は...(予想はつくと思いますが)画面にa=3と表示されます。
ここでは、aは変数です。
printfはこのように変数の値を表示することも出来ますよ。


では、ソースコードの解説へといきます。
1行目   #include <stdio.h&rt;
これは前回と一緒。分かりますね。


2行目   void main(){
これも同じ。C言語はmain関数から始まります。


3行目。int a;
これは何?>「これからaという変数を使いますよ」と宣言をしているのです。
intの後のaが変数名です。
じゃあ、intとは何ぞや?ってことですが、
C言語の変数には変数の種類によって使える数の範囲が違うのです。
このintを変数の「型」といいます。
変数を箱にたとえると、名前は箱の名前で、
型は箱の大きさ。
図2_1
では、変数の型の種類をざっと紹介しましょう。
型名使える範囲
char-128〜+127
short-32768〜+32767
int -2147483648〜+2147483647
long-2147483648〜+2147483647


4行目。a=3;
予想はつきますね。代入文です。
ここでは、変数aに3が代入されています。
セミコロンをつけるのを忘れないよう注意しましょう。


5行目。printf("a=%d",a);
aの値を画面に表示します。
%dって何?
""で囲まれた部分を文字列と言い、そのまま画面に表示させるのですが、
この%dは、画面にはあらわれず、
カンマの後の数字を%dに持ってこさせるようにしてます。

図2_2
つまり、%dには,の後のaの値、つまり3が入ります。
二つの変数を表示させるには?
printf("a=%d b=%d",a,b);
一つ目の%dはaを、二つ目の%dはbを持ってこさせています。
図2_3
頭に%がつく文字は、幾つか種類があります。
種類効果扱う変数の型
%d数字を表示int,short,long,float,double
%i整数を表示int,short,long
%f小数を表示float,double
%c一文字を表示char
%s文字列を表示char(配列)
%%%を表示--

ここで紹介したのは一部ですが、これだけあれば十分です。


■変数の演算

<サンプルプログラム2>
#include <stdio.h&rt;
void main(){
  int a,b,c=7;
						char  d;
						a=3;
      b=12-a;
      c++;
  a*=2;
      d = 'A'
      printf("a=%d",a);
      printf("b=%d",b);
      printf("c=%d",c);
      printf("d=%c",d);
}


実行結果は..?予想してみて下さい。(後で解答があります)
では、ソースコード2を解説します。


まず3行目のint a,b,c=7;ですが、
複数の変数を宣言したい時には、カンマで区切って下さい。
型が違う時は別にしなきゃ行けませんが。
c=7ですが、宣言といっしょに代入することも出来ます。


4行目。char d;
char型の変数dを宣言しています。


5行目のb=6+a;
予想はつくと思います。
4行目でaには3が代入されているので、
bには12-3で9が代入されます。


6行目。c++;
...? これはインクリメントといって、変数の値を+1します。
だから、cには8が入ります。また、++c;という書き方も出来て、これでもOKです。
ちなみに、逆にデクリメント(--)というのもあって、変数の値を-1します。


7行目。a*=2;
これも何か変。僕も始め見た時は訳が分かりませんでした。
*=は、特殊な代入演算子で、ここではaに2をかけたものをaに代入します。
つまり、a=a*2;と同じ意味です。ただ、aを2つ書かなくてよく、便利です。
他にも、+=,-=,/=,^=などがあります。


8行目。d = 'A'
'A'をchar型の変数に代入しています。
char型は整数だけだなく、一文字(1byte)も扱えます。
別に他の型でもいいのですが、無駄なメモリが割り当てられてしまいます。
あと注意したいことは、一文字を表す場合は「'」で囲むことです。
前に書きましたが、printfで出力するには%cを使います。


9〜12行目は出力をしているのですが!
予想した結果とは、違いますね。
一行に連なって出力されてしまいました。
これを解決するには、「改行」の意味を表す、\nを文字列の部分に入れます。
printf("a=%d",a);
printf("\nb=%d",b);
printf("\nc=%d",c);
printf("\nd=%c",d);
\nも%dなどと同じように、実行結果には\nなどと表示されたりはしません。
また、これにも幾つか種類があります。

種類効果
\n改行
\tタブ
\r同じ行の先頭に戻る
\\\を表示


■小数を使った変数

<サンプルプログラム3>

#include <stdio.h>
void main(){
  float a=16,b=3;
						int c;
						float d;
      
      c = a/b;
  d = a/b;
      
      printf("c=%d",c);
      printf("\nd=%f",d);
      
      
}



では、ソースコード3を解説します。今回はやけに長いなぁ。

2、4行目に注目して下さい。float型って何でしょう?
いままでは整数しか扱ってこなかったけど、この型を使えば、
小数も扱うことが出来ます。
float型以外にも小数を扱える型があります。(下の表を見て下さい。)

さて実行結果は...
c=5、d=5.333333
cはint型なので、小数でも整数に直されます。
float型の変数を表示するには、%fを使います。
型名使える範囲桁数
float3.40282*1038 〜 3.40282*10387桁
double省略14桁

はい。今回はここまで。
このページを見るだけでなく、サンプルプログラムをいじってみてください。
新たな発見があるはずです。
変数について書きたいことはまだまだあるのですが、それは次回に。


■今回のまとめ


型名 変数名; で変数の宣言。
○変数の種類は、char,short,int,long,float,doiuble 等で、それぞれ代入できる数が異なる。
変数名 = 数; で変数に値を代入できる。
" "内に%d等の記号を入れ、" "外にカンマで区切って変数名を入れると、変数の値を表示できる。
○a=a+2 は、a+=2に書き換えられる。しかもこの方が楽。
○a=a+1 はa++、a=a-1はa--で表記できる。それぞれ、インクリメント、デクリメントと呼ぶ。

3.変数の使い方その2

さて今回は、インクリメント、デクリメントの補足説明、

scanfなど、細かいことを書きます。


■前置演算、後置演算

//サンプルプログラム1

#include <stdio.h&rt;
int main(){
  int a=1;
						int b=2;
      b = a++;

      printf("a=%d",a);
      printf("\nb=%d",b);
      
      return 0;
}

//サンプルプログラム2

#include <stdio.h&rt;
int main(){
  int a=1;
						int b=2;
      b = ++a;
      printf("a=%d",a);
      printf("\nb=%d",b);

      return 0;
}

まず、始めが今までと違いますね。void mainがint mainになってます。
ANSI Cの文法には int main( void ) か int main( int argc, char* argv[] )にしか定義されていないようです。
というわけでこのC言語プログラミング講座はint mainで通すことにしました。
(別にどちらでもいいそうですが)
(だいちさんがこの情報を提供してくれました。 thanks!!)

さて、メインはここからなんです。
先に実行結果を書いてみます。
サンプルプログラム1では、
a=2
b=1
でした。
でもサンプルプログラム2では、
a=2
b=2
でした。

実はサンプルプログラム1のb = a++のインクリメントの使い方、後置演算と呼んで、
先に代入をしてからインクリメントの処理をします。
つまり、先にbにaの値1が代入されてからaが1増えるのです。

これに対してサンプルプログラム2のb = ++aのインクリメントの使い方を前置演算と呼んで、
先にインクリメントの処理をしてから代入します。
先にaが1増えてからbに代入されるので、bがaの値と同じ2になります。

では次のステップに行きませう


■scanfで値を入力

<サンプルプログラム3>
#include <stdio.h&rt;
int main(){
  int a;
      printf("aの値を入力して下さい");
      scanf("%d",&a);
						printf("\na=%d",a);

      return 0;
}

aの値を入力させ、表示させるプログラムです。
scanf("書式指定文字列",アドレス)
書式指定文字列とは、printfにでてきた、%cとか、%dとかいうやつです。
ここでもう一回かきます。
型指定文字意味使われるデータ型
%c「1文字」として入力するchar型
%d10進数で入力するint型
%x16進数で入力する
%o8進数で入力する
%ldlong型変数を 10進数で入力するlong型
%ffloat型変数に実数を入力するfloat型
%lfdouble型変数に実数を入力するdouble型
%s文字列を入力するchar型配列

配列については、あとでやるので、御心配なく。

次に、変数のアドレスですが、これについてはあとでやりますm(--)m
とりあえず、変数の名前の前に&をつければいいということだけ覚えておいて下さい。

文字も取り出すことが出来ます。
#include <stdio.h&rt;
int main(){
	     char a;

	     printf("aの値を入力して下さい");
	     scanf("%c",&a);
	     printf("\na=%c",a);
	     return 0;
}

%cで、char型を指定するので文字も入力できます。
ただ注意したいのは、『1』文字しか入力出来ないということです。
文字『列』を扱うには、配列というテクニックを使うのですが、それはまたあとで。
また、途中でスペースを入れると、入力がそこまででなぜかとまってしまいます。

こんかいはここまで。
次回は、HyperTalkでいうrepeatのfor文と、判定で使われるif文とswitch文を解説します。


■今回のまとめです。


a=++bは、bの値を+1をしてからaに代入(前置演算)
a=b++は、aにbの値を代入してからbの値を+1(後置演算)
scanf("書式指定アドレス",&変数名)


4.制御文の数々

今回は予告通りfor文,while文とif文の解説です。


■for文でループ

<サンプルプログラム>
#include <stdio.h>
int main(){
	     int a;
      for(a=1;a<=5;a++){
            printf("\n%d",a);
      }

	     return 0;
}

ソースコードの解説です。
4行目の for(a=1;a<=5;a++){ ですが、
書式はこうです。 for(最初の代入文;条件;実行文){
まず3行目で宣言した変数aに1が代入されます。
そして中かっこの中の文に移動し、aの値を表示させたあと、
さっきのfor文に戻ります。
for文の3番目の実行文でaの値を1プラスし、
そしてfor文の2番目の条件と比べます。
ここで、aは2なので、条件にあっています。
それなら printf("\n%d",a); をまた実行して
またのfor文に戻ります。
この繰り返し。
最後にfor文の2番目の条件にあっていなかったら、ループはそこで終了。

まとめると、


for(A;B;C){
     D
}

A → D → C → B → D → C → B → D → C → B → D → .....の順に文を実行していきます。

また、for文の中のDが1行なら、


for(a=1;a<=5;a++)  printf("\n%d",a);


このように「{}」を省略できます。

for文の3つめの実行文、実は+1だけじゃなくてもいいです。
for(a=1;a<=5;a+=2) (a+=2 → a=a+2です。覚えてますか?)
こう書けば、奇数の数だけを表示できますし、
for(a=1;a<=16;a=*2) こう書けば、aが1,2,4,8,16と2倍2倍になっていきます。

まあこのようにfor文は汎用性が高いです。


■while文でループ

次にwhile文。

<サンプルプログラム2>
#include <stdio.h>
int main(){
	     int a;
      while(a<=5){
            printf("\n%d",a);
            a++;
      }
    
	     return 0;
}

while文は、for文の簡易版です。
()の中の条件式が正しければ、{}で囲まれた文を実行します。
要は、for文の3番目の実行文がループ内に入ったって感じ。
forよりも使いやすいので、個人的にはこちらがお勧めです。

また、こんなことも出来ます。


while(1){
      printf("無限ループ\n");
}

whileの()内に1を入れると、それだけで無限ループします。
実は、C言語において、条件式が正しければ「1」、
違うなら「0」という意味になるんです。

(後のif文で詳しくやります)

ループ文の基本的な使い方は終わり。分かりました?

次はif文!あ〜急がし


■if文で条件判断

<サンプルプログラム3>

#include <stdio.h>
int main(){
	     int a,b;

      for(a=1;a<=5;a++){
            b=a*5
            printf("\n%d",a);
            if (a==3) {
                printf("\n%d",b);
            }
      }

	     return 0;
}

この部分、重要です。
今回は変数が2つ出てきます。
ループ文の中で、b=a*5とあるので、
5,10,15...と増えているのでしょう。
ここからが本題。
if (条件式) {実行文}
もし条件式が1(つまり正しい)なら{}内の文を実行する。
つまりここではaが3なら、bの値を表示させています。

BASIC、HyperCardなどを使い慣れている人には、
「あれ、なんでイコールが2つなの?(==)」
って思うかも知れません。(僕もそうでした)
でも『=』だと、C言語では「代入」を表すわけです。
区別するために、イコールを2つつけています。

では、改めて条件式をまとめてみます。

条件式意味実例←の意味
==等しいa==3aは3に等しい
<=〜以下a<=4aは4以下である
>=〜以上a>=17aは17以上である
<=〜より小さいa<4aは4より小さい
>=〜より大きいa>17aは17より大きい
!=〜でないa!=10aは10でない

最後の「!=」がC言語独特です。

<サンプルプログラム3>
#include <stdio.h>
int main(){
	     int a,b,c=0;

      for(a=1;a<=5;a++){
            b=a*5
            c++;
            printf("\n%d",a);
    printf("\n%d",b);
            if (a!=3) {
                c++;
            }

      }
  printf("\n%d",c);
	     return 0;
}

forとifを使った応用編です。
Aは1,2,3,4,5 と増えるので、
Bは5倍して5,10,15,20,25 と増えていきます。

では、Cの値は?
『Aが3でない』時にCは2つ増えるので、
1,2,4,5でCは8。
Aが3の時はCは一つしか増えないのでCは9。


■練習問題1


for文を駆使して@(アットマーク)で10段のピラミッドを作りなさい。
       @
      @@@
     @@@@@
・・・・・・・


こんな感じのやつです。正解は次回発表します。

■今回のまとめ


for(最初の代入文;条件;実行文) 条件が正しい間ループ
while(条件) 条件が正しい間ループ
while(1) 無限ループ
if(条件) 条件が正しければ、次の{}内の文を実行
} else 前のif文の条件が正しくなかった時、次の{}内の文を実行


5.配列


■練習問題の答


まず、ピラミッドはどのような構成か考えてみます。
___@
__@@@
_@@@@@

このように、空白とアットマークから成っています。
次に、現在書いている段を使って空白、アットマ−クの数を表してみます。
よく観察していると、次のようなことが分かります。

○空白の数   ・・・最大段数(ここでは10)−現在段数
○@の数   ・・・現在段数×2−1
@の数と空白の数

for文を入れ子にして使って表示させます。
//変数宣言
int dan,blank,a

//第1ループ
for (dan=1;dan<=10;dan++){

       //空白描画
       for (blank=1;blank<=10-dan;blank++){
              printf(" ");
       }

       //アットマーク描画
       for (a=1;a<=2*dan-1;a++){
              printf("@");
       }

       //改行
       printf("\n");
}   

blank<=10-dan や a<=2*dan-1 のところがミソです。


■配列

プログラミングで最も重要な要素の1つである『配列』について解説します。

配列って何かというと、変数の説明で箱を使ったけど、それが1列に並んだような感じです。
//配列変数宣言
int a[5];

上ので、『aという名前の配列を6つ用意せよ』、という意味。
//配列変数宣言
a[5]={1,3,-5,10,-4};


上ので、 a[0],a[1],a[2],a[3],a[4] に数を代入しています。
a[5]には代入されてません。むしろ、a[5]は配列の中で使いません。

配列を宣言した時に、a[5]にはすでに『終わり』を表す文字 『\0』(ヌル文字)がすでに入っています。
だから結局、配列を用意したい時は、a[n]に配列にデータを入れたい数分だけ、nの値をきめることになります。

また以上2つのは一行でまとめて出来ます。
//配列変数宣言
int a[]={1,3,-5,10,-4};

int a[] にはコンピューターが勝手に適当な数を代入してくれるので、楽です。
//配列変数宣言
int a[]={1,3,-5,10,-4};
int n,total;
for (n=0;n<=4;n++){
      total+=a[n]
}

配列は普通の変数と同じように計算できます。
これは配列変数に入ってる数の合計を計算させるプログラムです。
これをa1,a2,a3,a4,a5..といちいち変数を5つ決めて、代入させて...とやってると日が暮れてしまいます。


■2次配列

配列は横だけでなく縦にも並べられます。

//配列変数宣言
a[3][5]={{1,3,-5,10,-4},
             {2,0,-9,7,6},
             {-5,8,4,9,1} };

まず一つ一つの{}内に今まで通りに宣言します。
そして一つの{}を一まとまりと考え、それを『,』で区切ります。
区切った幾つかのまとまりの{}をまた{}で入れ子にします。そしてセミコロン。
この時、下の図のように数が代入されています。
2次配列
また、一次元配列では完全に[]の数字を省略できましたが、
2次元配列では2次元目(最初の[])だけ省略できることに気をつけて下さい。
2次配列の宣言

a[2][2]=+a[1][3]

2次元配列は同じように計算できます。
2次元配列も各次元の最後の部屋(3番目と5番目)に変数を入れることが出来ません。

■文字列

配列を使えば文字列を扱えます。
//配列変数宣言
char a[]={"this is a pen."};

文字列はダブルクォーテーションでくくって下さい。
この時、配列の中身はこうなってます。
このうちの一文字、例えば『a』を表示するには、
printf("%c",a[8]);

とすればいいのはもう分かりますね。
この文字列全体を表示するには、文字列をもってこさせる『%s』を使います。
printf("%s",a);

aだけを指定すれば、その配列全体を参照できます。


■2次配列を使った文字列

//配列変数宣言
char a[][15]={{"this is a pen."},
                    {"c language"},
                    {"あいうえお"}};

こんな風に宣言したとします。前と一緒で、ただ前のやつが3列になっただけです。
注意したいことと言えば、1次元目の配列の数字を一番大きな値にそろえることです。
まぁ、当然と言えば当然なのですが....
ではこれを表示させます。1行目全体を参照したい時は、
//配列変数宣言
printf("%s",a[0])

とすればいいし、3行目を表示したい時は、
//配列変数宣言
printf("%s",a[2])

とすればいいですね。

■練習問題2


配列とは関係ないのですが練習問題を。
任意の数1つを、素因数分解するプログラムを作ろう。
ヒント1:for文とifを使います。
ヒント2:2で割れても、もう一回2で割れるかもしれない。

■練習問題3


数の配列の平均と最大値を求めるプログラムを作ろう。
配列は、n[]={-5,12,9,-6,51,-14} を使って下さい。
ヒント1:平均はさっきでてきた配列の合計を求めるプログラムを....
ヒント2:最大値はif文を使います。

■今回のまとめ。


型名 変数名[] で配列の宣言。
○int a[6]={5,3,1,-1,-3,-5};この時、a[0]=5のように 0から始まることに注意
○int a[6]={5,3,1,-1,-3,-5};の時、配列の最後(a[6])は使えないことに注意
型名 変数名[][] で2次元配列。
○int n[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}; の時、 2次元目は省略できるが(○n[][4])、1次元目は省略出来ない(×n[3][]、n[][])
○文字列を扱うにはchar型の配列を使う
○文字列を表示するには%sを使う
○文字列を参照..1次元配列の場合、a とそのまま。(printf("%s",a);)
○文字列を参照..2次元配列の場合、a[n] 何行目かを示す。(printf("%s",a[1]);→2行目)


間違い等ありましたら御指摘をお願いします。