◆C言語の基礎◆

既にC言語は習ってきているはずなので、ここでは基礎部分を思い出す程度の概略説明を行う。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

■C言語のプログラミング環境 と実行方法概略

ここでは、Visual Studio(Microsoft)を利用してプログラミングを行う。

Visual Studio (以下VSと呼ぶ)を立ち上げ、プロジェクトを読み込み、main関数のあるソースを表示させる。

プログラムを完成したら、「デバッグ」メニューから「デバッグ開始」を選択する。

ソースが変更されている場合、「ビルドしますか?」と問われるので、「はい」を選択する。

すると、「ソースが保存」され、「ビルド、つまりコンパイル」されて、実行される。

但し、もしプログラムに文法エラーがある場合、「ビルド」の際に次のようなダイアログウィンドウが表示される。

ビルド時のエラーダイアログ

この場合、「いいえ」を選択し、VS下の「出力」欄にエラー等が表示されているので、これらを参考にして正しい文法のプログラムに修正し、再度「デバッグ開始」をする。

プログラミングにおいて、間違いは主に3種類に分けられる。

一つはアルゴリズムのミス。そしてソースコードの文法ミス。最後にプログラミングミスである。

アルゴリズムのミスとは、自分が採用したアルゴリズムそのものに問題があることを指す。たとえば、円の面積を求めるのに、間違って台形を求める方法を利用してしまうことなどである。これはプログラムとは全く無縁な話で、自分でよく考える必要がある。

文法ミスはビルド(コンパイル)をすればある程度どこの辺りがミスしているのか想定が付く。

一番厄介なのはプログラミングのミスである。文法的なミスを伴うこともあるが、文法上問題がなくても、プログラムとしてミス(バグ)がある場合がある。たとえば単純な例としては、変数iを使用するところを間違って変数jを使ってしまうなどである。i=i+1とすべきところを、i=j+1などとしてしまうと、文法的にはミスはないが、思った通りに動かないことになる。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

■ C言語の基礎

C言語によるプログラミングの簡単な例として有名な「Hello World!」プログラムは次のようなコードである。

#include ;
main(){
    int x;
    /* printf( "helohelo\n" ); */
    printf( "Hello World! %d\n", x );
    //xを表示することには全く意味がない
}

C言語には、行という概念が薄い。上記例では4行だが、2〜4行目の3行分を、main(){ printf("Hello World!\n"); }と1行に書くことができる。

main関数(main(){...})は、プログラム実行時にスタートとなる関数で、ここに自分でプログラムを書く。

#include はヘッダーという様々な宣言などをしたファイルを読み込むもので、<stdio.h>や<math.h>などをincludeしておけば、簡単なプログラムではほぼOKなことが多い。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

□コメント

プログラムの中で、メモなどコメントを書きたいことがある。このようにC言語のプログラムではない部分として指定することをコメントアウトと呼ぶ。

コメントとするには、二つの方法がある。

「//」(半角スラッシュを二つ続けて書く)と、これ以降行末までがコメントとして扱われる。

「/*」と「*/」で囲まれた部分(「/*this is comment*/」)が、コメントとして扱われる。

コメントは、メモなど説明のために使われるだけでなく、一時的に特定のプログラムを実行させないようにするのにも使える。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

□printf関数

printf関数は、変数(の中身)や指定した文字などを実行時に結果やコメントなどを表示するための関数。

printf( "XXX" ); のように、""の内の文字列を実行時に表示させることができる。

int型変数yの中身を表示させるには、printf( "XXX %d", y ); とすると、「%d」の部分に変数yの中身が表示される。たとえば今y=123だとすると、「XXX 123」と表示される。

float型の変数を表示させるには、%dではなく「%f」とする。

文字列内の「\n」 は、改行を意味し、ここで改行される。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

□変数の宣言

C言語ではプログラム内で利用する変数について、型と共に宣言しなければならない。

変数には、取り扱うデータの種類によって型がある。整数しか扱うことのできない変数はint型、実数(小数点以下も扱える)を扱うには、float型を利用する。

変数の宣言は、関数の先頭部分で宣言する。たとえば、int型の変数a,b,cとfloat型の変数x,yをプログラム内で利用する場合、例えば次のように宣言をする。

main(){
int a, b;
float x,y;
int c;
・・・

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

□if文

条件によって処理を分岐させる時に利用する。

if( x>y ){
   AAA;
}else{
   BBB;
}

などのように書き、ここでは分岐の条件を「x>y」としたが、様々な論理式を書くことができる。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

□for文

特定の部分を繰り返し実行させる場合に、 利用する。

for( i=0; i<10; i++ ){ ・・・}

などのように下記、{・・・}内を繰り返す。

for( i=0; i<10; i++ ) {
for( j=0; j<3; j++) {
   ・・・
  }
}

は、2重ループで、i=0, j=0→1→2, i=1, j=0→1→2, i=2, j=0→1→2, i=3, j=0・・・と変化しながら10x3回繰り返す。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

□配列

通常変数は、一つの数字などを保存をする箱のようなものである。配列はこのような箱を例えば横に並べて、1番目、5番目などと指定して利用する変数である。
配列変数を宣言する場合、用意する箱の数をしてしなければいけない。箱の数はプログラマーが予め余裕を持って指定する必要があり、指定した数を超えて利用することはできない。たとえば、「int a[10];」などのように宣言する。注意しなければいけないのは、この場合10個の箱が準備されるが、0番目から始まり9番目までである。

一次元配列とは、一列に並んだもので、たとえば配列変数を「a」とした場合、「a[0], a[1], a[2],...」などのように利用する。

二次元配列とは、縦横に並んだもので、たとえば配列変数を「b」とした場合、「int b[10][10];」のように宣言し、「b[0][0], b[0][1], b[0][9], b[9][9]」などのように利用する。

配列が便利なのは、何番目かを指定する数(添え字、indexなどと呼ばれる)に、変数が使える点である。
例えば、for文と組み合わせて、for( i=0; i<10; i++){ x = a[i]; } などのように配列の[]内を数字ではなく、変数を介して指定することができる。

画像データはプログラム内では、二次元配列で扱う。たとえば、20x20画素の画像データで、白を0、黒を1とするとき、配列変数g[20][20]で扱う。
例えばこの画像データにおいて、黒の面積を求めるには、全ての画素の値を足していけばよいので、

  int g[20][20];
  int t = 0;
  for( i=0; i<20; i++ ){
      for( j=0; j<20; j++ ){
          t = t + g[i][j];
      }
  }
  
などのようにすればよい。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

□関数とその引数、及び変数のスコープ

関数は、何度も同じ処理をさせたい場合などに非常に便利なものである。たとえば、画像データを数字ではなく、□と■で表示すると見やすくなるので、このような関数を作ったとする。画像データの二次元配列は、プログラム内でいくつも利用することがあり、たとえばg[20][20]の他に、h[20][20]やe[20][20]などを利用していたとする。その度に表示するプログラムを書くことも不可能ではなく、copy&pasteして修正していけばよいが、若干面倒なことと、この部分を修正するとなると、あちこちを修正しなければならず、ミスをする可能性も増える。

そこで、printMapDot()という関数を一つ作れば、表示が必要な際に、何回でもこの関数を呼び出すようにプログラムするだけでよくなる。

関数を作る・利用する際に重要なのは引数である。
引数とは、関数の( )の中に記載するもので、ここに引き渡すべき情報(数値など)を書く。

例えば、printMapDot()関数では、指定された画像データ(二次元配列)を表示するものなので、少なくとも画像データをこの関数に渡してあげないといけない。
よって、printMapDot( int map[20][20] ) というように、20x20のint型の二次元配列を引き渡すことができるようにする。

この関数を利用する側(つまり呼び出す側)では、たとえば次のようにすればよい。

printMapDot( g );
printMapDot( h );
printMapDot( e );
・・・
printMapDot( g );

なお、ここでは注意すべきは、配列を引数として関数に渡すときに、[]や[][]を付けずに、配列変数の名前だけとする。
きちんとした理由があるが、ここでは省略する。

一方、関数の本体(実体)では、上記のようにmapという変数名で受けるとする。つまり、以下のような関数とする。

printMapDot( int map[20][20] ){
    int i,j;
    for( i=0; i<20; i++ ){
        for( j=0; j<20; j++ ){
            if( map[i][j] == 0 ){
・・・

これは一見正しく動かないように見える。なぜならば、呼んでいる側は、たとえば配列変数gを指定して渡しているのに、関数本体側では、mapという変数名を利用しているからである。しかし、これは問題なく正しく動く。

関数を利用する(呼ぶ)側は、必要な配列変数を指定する。関数の本体側では、どんな配列変数名であろうと、関数内ではすべてmapという変数名で扱うことにしているだけである。
これにより、printMapDot(g)やprintMapDot(h)など自由に配列変数を指定して関数を利用することができる。

なお、ちょっとややこしいが、関数を利用する際には、変数のスコープについても知っておかなければいけない。

例えば、main関数側でも変数i,jなどが宣言、利用されているとする。一方でprintMapDot関数内でも上記のとおり変数i,jが宣言され利用されている。
関数が違えば、同じ変数名であっても、全く別のものであることに注意してほしい。
これは例えば、工場Aと工場Bがあって、工場Aから工場Bに作業の注文をすると考えると分かりやすいかもしれない。工場Aにおけるあるメモ用紙の名前が工場Aでxと呼ばれていたとする。工場Bでもあるメモ用紙をxと名付けることがある。この場合、工場Aのメモ用紙xと工場Bのメモ用紙xは全く違うものである。それぞれの工場内で、独自に(勝手に)名前を付けて利用しているにすぎない。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

□いくつかの数学的関数

数学的な計算(数値演算)をする場合によく利用される関数について簡単に説明する。
なお通常これらの数値演算の関数を利用するためには、プログラムの先頭部分で、「#include <math.h>」を追加しておかなければならない。

※参考; http://www.cppll.jp/cppreference/stdmath.html

・ルート(平方根

例えば√3 は二乗すると3になる数(1.732・・・)のことで、これを平方根(ルート)と呼ぶ。C言語において、平方根を計算するには、sqrt()関数を利用すればよい。

・べき乗

例えば、23は、2の3乗つまり2x2x2を意味する。このようなべき乗の計算をC言語でする場合には、pow()関数を利用する。
但し、2乗の場合は、単に掛算を利用することも多い。例えばx2は、「x*x」とする。
どちらを利用するかはプログラムの自由(好み)でよい。

・合計を求める

関数ではないが、合計を求める方法について簡単に説明する。
通常、for文などを利用して行うが、まず、合計の値を求める変数を一つ用意する(ここでは変数tとする)。
合計値tをまず空にする。つまり「t = 0;」とする。
そして、tに合計したい数の一つを足して、結果をtに代入する。
つまり、次の例のようになる。

t=0;
for( i=0; i<20; i++ ){
    t = t + m[i];
}

このプログラム例は、一次元配列変数mのm[0],m[1],...,m[19]に既に入っている数の合計を求めている。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

□getchar()関数

getchar()関数は、Get Character、つまり1文字を入力するための関数で、通常「c = getchar( );」などのように使う。
但し、もし入力した文字を利用しないのであれば、左側の「c =」は不要。

VSを実行すると、printf()関数で表示した文字などは、別のウィンドウで表示される。しかし、全ての処理が終わると、この表示されていたウィンドウも閉じてします。そこで、getchar()関数を使うと、キーボードから何か入力されるまでgetchar()関数でとまるので、結果として一時処理を止めておくことができる。

なお、ここで入力とは、「エンターキー」が押されて初めて入力となる。なお、単にエンターキーのみを押せば入力したことになる。
一方、「while(getchar() != 'q');」とすると、「q」文字を入力した上で、エンターキーを押すことを意味する。

 


Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ

●参考WEBページへのリンク

自分で所有しているC言語の本をじっくりと参照するとよい。

なお様々なWEBページに、C言語に関する解説・説明等が載っているので、ちょっとしたことであれば、適宜参照するとよい。
以下のリンク先は、比較的初心者を対象にしたものであるので、すっかり忘れてしまった人等は参考してもよいでしょう。

Go[ 先頭 | 実行 | 基礎 | コメント | printf | 宣言 | if | for | 配列 | 関数 | 数学(√・べき乗・合計) | getch | リンク情報 ]へ