「祝!C言語プログラミング人気ランキング1位(2020年5月)」
TOEBE Softwareが実施している。複数の検索エンジンの検索結果でどのプログラミング言語が最も検索されたかを調査した結果(PCI:TIOBE Programming Community Index)の結果がでていて、今月はC言語が1位になっていました。
ずっと2位が続いていたのに復活です。
C言語といえば、言語の仕組みもシンプルで組込み系などでは使われ続けているので、コロナの影響で医療機器などの需要が増えたとの推測もされていましたが、本当のところはわからないですね。
昔からある言語で、自分もいったいどれだけお世話になったのかわからないほど使い続けてきました。
世界でもっとも検索されたというのは、現在最も使われているプログラミング言語、ということです。
そこで、C言語のランキング1位を記念し何回かに分けて自分なりのC言語講座を記事にしてみます。
プログラミング C言語 【はじめの一歩】
C言語講座、基礎編、第1回です。
C言語のはじめの一歩
Cプログラマのこだわりからはじめます。
やはり、C言語をはじめるとき、最初に書くプログラムは、もう定番のこれです。
#include < stdio.h > main() { /* 文字の出力 */ printf("hello, world!\n"); }
僕は、もう数え切れないくらいこのプログラムを書いているため、hello, world のタイピングだけは、異常に早いです。
新しいマシン、新しい環境のコンパイラの動作確認のたびにhello, worldとタイプしてきたため、完全に指がこのプログラムを記憶しているのです。
さて、C言語のはじめの一歩です。
関数は、{}で囲われ、文字列は””で囲まれる。
(2)コメントは、/* と */でくくって記述する。(行コメントは、//も可能になりました)
(3)文字列の出力(コンソール)は、printfという関数で行える。
(4)文の終わりは、;で区切る。
(5)ヘッダファイルというものがあり、関数を使用する場合、その関数の宣言を
しているヘッダを取り込む必要がある※。その時の命令が、#include であり、
printfは、stdio.h に定義されているため、#include
と書く必要がある。
(6)printf で出力する文字列の中の、\n は、改行を表す。
わからずとも、とりあえず書いてみて、手持ちの環境で動作させてみるのがいいです。
プログラミングは、習うより慣れの方が、はるかに覚えます。
画面に、
> hello, world!
と表示されれば、C言語の第一歩は、クリアです。
プログラミング C言語 【基本の構文】
構造化プログラミングの基本
C言語なので、構造化プログラミングからはじめます。
構造化プログラミングとは、全てのプログラムは、
(2)分岐
(3)繰返し
の3つのパターンで記述できると、いうものです。
条件分岐
main 関数から順に実行されることは、前に書いたので、次は分岐です。
プログラミングで分岐といえば、if文というやつ。C言語では、次のように書きます。
if (条件) { こんなこと; } else { あんなこと; }
本当は、 if (条件) 文 [ else 文 ]
複数の文は、{ } でまとめる(ブロック化)というのが正しいのだけれど、
できれば、if文は、{}で括る癖をつけて欲しいのであえて{}付きで覚えたい。
if (x == 1) printf("x is 1\n"); else printf("x is not 1\n");
これでもいいのだけれど、修正して
if (x == 1) printf("x is 1\n"); else printf("x is not 1\n"); printf("ERROR \n");
実は、最後の ERROR は、プログラムのインデントからすれば、xが1以外の時のみ出力されるのがプログラマの意図するところだったのに、この場合は、xの値にかかわらず出力されてしまいます。
Pythonはインデントがブロックを示しますが、{}とか begin end で明示的にブロックをしめすプログラミング言語の方が、多いですね。
僕は、間違いを避けるためにも、{}は書くようにしています。
なので、C言語、正しく書くと下記になります。
if (x == 1) { printf("x is 1\n"); } else { printf("x is not 1\n"); printf("ERROR \n"); }
まぁ、 printf("x is 1\n"); のほうは、別に{}で括る必要もないのですが、のちのちつまらないバグを引き起こさないようにも、書いておいて損はありません。
実際、業務プログラムの場合は、書くことを心がけています。
連続する分岐の場合、上記 if 文では、
if (条件1) { 処理1; } else if (条件2) { 処理2; } else if (条件3) { 処理3; } else { 処理4; }
という具合です。実は、先のif ~ else が重なっているだけですが、複数条件の分岐の場合は、こういう書き方をしたほうが、やはりわかりやすいです。
さて、複数の分岐の場合、数値(整数、文字定数、定数の式)での振り分けができるものは、以下の構文がよく使用されます。
switch (id) { case 数値1: 処理1; break; case 数値2: 処理2; break; default: 処理3; break; }
switch 文での注意点は、break を忘れると次のcase 文まで実行されてしまうことと、defaultラベルは、タイプミスをしてもgoto 文のラベルとみなされて、エラーにならないということです。
defaultのタイプミスは、過去にデバッグで悩んだことがありました(笑)
個人的に気をつけていることといえば、あえてbreak を使わない場合でもコメントでその旨をことわることと、空でもなんでもdefault文を記述することです。
意図してbreakを書いていないのか、バグやミスの類なのか、他の人では一見してわからないからです。
switch (n) { case 0: printf("case 0\n"); /* no break */ case 1: printf("case 1\n"); break; default: break; }
繰り返し
次は繰返しです。
前で判定するか、後ろで判定するか、カウンターで指定数まわす、パターンが良く使われます。
あわせて、無限ループにして、ループの途中で抜け出すパターンもよく見かけるやり方です。
A) 前判定 while (条件) { } B) 後判定 do { } while (条件); C) for文(指定回数の繰り返し) for (初期処理; 条件; 終処理) { } for 文の一般的パターンは、 for (i = 0; i < n; i++) { ... } D) 中判定(無限ループ) for (;;) { if (条件) break; }
さらには、ループの途中で先頭に戻るcontinue 等というのもあります。
時に、D)の中判定は、構造化プログラミングに反するとか、do ~ while は、わかりにくくなるから避けたほうがよい、とかいう話も以前はよく耳にしましたが、そう硬く考えなくともよいと思います。
むしろ、プログラムをわかりにくくする原因は別にあるような気がするからです。
簡単な構文をひととおり学習してみたところで、Nの階乗計算のプログラムを書いてみました。
これは、関数再帰呼出のよく知られた例もあるのだけれど、まだ関数は使いません。
#include < stdio.h > int main() { int i, n, x; char buf[128]; printf("N : "); gets(buf); if ((n = atoi(buf)) < 0) { printf("Input Error!\n"); return 1; } x = 1; for (i = 1; i < n; i++) { x = x * i; } printf("%d! = %d\n", n, x); return 0; }
実行すると、入力した数字の階乗を計算して表示します。
今回はここまでにします。
C言語の話は、何回かに分けて投稿しますので、興味のある方は引き続きよろしくお願いします。