Cによるプログラミング入門2
プログラムの基本構造
今回は、前回見たプログラムの説明をします。
前回は、以下のように、プログラムhello.cを書いて、実行してみました。(ここで、文字はすべて半角英字であることに注意してください。\(円記号)は、もともとバックスラッシュですが、日本の多くの環境では、\(円記号)を使うのでそうします。)
#include <stdio.h>
int main(void)
{
printf("hello, world\n");
return 0;
}
まず、1行目は「stdio.hというファイルの内容をここに持って来い」という意味です。stdio.hは、どこかに置いてあるファイルで、そこには、「標準的な入出力に必要な情報」(あとで使うprintfなどの情報)が入っているのです。このようなものを、インクルード文などといいます。一般に、「標準的な入出力」をするプログラムでは、はじめに、このインクルード文を書くのです。
2行目は何も書いていない行です。これは、プログラムを見やすくするために入れたもので、あってもなくてもかまいません。Cのプログラムでは、(基本的には)改行はあってもなくても同じなのです。
3行目、4行目、それと最後の行は連動しています。というのは、
Cでは、プログラムの中心部分を int main(void) などと書くことになっているのです。(実は、先頭のintは省略できます。また、丸カッコの中のvoidを省略することもあります。) |
この形の詳しい意味は、入門がもう少し進んでから説明します。とりあえず、プログラムの中心は、このように書くということを理解しておいてください。
すると、このプログラムで本当に意味のある部分は、
printf("hello, world\n");
だけということになります。これさえわかればよいのです。
さて、一般に、Cでは、何かしてくれるものを関数といいます。数学でいう関数と同じ名前ですが、別物です。そして、hello.cに登場したprintfは、データを画面に出力する関数なのです。たとえば、文字列を画面に出力したい場合は、
printf("文字列");
とするのです。
hello.cのprintfの丸カッコの中身は、
"hello, world\n"
ですね。文字列を扱うときは、「"」で囲むことになっています。つまり、「hello,
world\n」という文字列が「"」で囲まれているわけです。したがって、「printf("hello, world\n");」は、「hello,
world\n」の出力ということなのです。
この文字列の中に、「\n」という不思議なものが見えますね。実は、これは「改行」という意味です。そのため、「hello,
world」という文字列を出力したあとに改行されることになるのです。なっとくがいかない人は、hello.cで「\n」だけ削除して実行してみてください。最後の改行がなくなるはずです。
ところで、printfのある行の最後には「;」とあります。これはprintfの一部ではありません。これは、「この行(命令)はここで終わり」というほどの意味なのです。今の例の「printf("hello,
world\n");」は、「printf("hello, world\n")」を実行して、この命令は終わりということなのです。
整理すると、「hello.cは、大部分がルールにしたがって書かれていて、その実質的な内容はprintf("hello, world\n");だけ」ということになります。そして、それは、「hello, world」と出力して改行せよ、ということなのです。
多少しっくりいかないところもあると思いますが、だいたいの仕組みをつかみ、「どういうコードを書けば、何が起こる」という形で理解していってください。ここで、コードとは、「プログラム全体またはその一部」を意味する言葉として使います。最初からすべてを理解することはできませんが、コードを書いていると、だんだんにいろいろわかってくるのです。
今回の話がわかったかどうかは、次の問題ができるかどうかでわかります。
問題:「こんにちは」と画面に出力してから改行し、さらに「お元気ですか?」と
出力してからまた改行し、終了するプログラムを書いてください
さあ、どうでしょう。
プログラムの基本形は説明してあります。また、「文字列の出力」はprintfでできるといいました。すると答は、次のようになるのではないでしょうか。
#include <stdio.h>
int main(void)
{
printf("こんにちは\n");
printf("お元気ですか?\n");
return 0;
}
このプログラムはhello2.cという名前にします。コンパイルして実行してみると次のようになります。
Fig.1 hello2.exeの実行画面
どうやら、うまくいったようです。これが正解(のひとつ)なのです。
上のプログラムを見て、何が何をしているかわかりますか?大部分は、基本的なルールにしたがって書いたコードで、実質的に意味があるのは、mainの中の2行のprintfだけですね。printfを2回使うことで、2行出力しているのです。もう一度、よく考えてみてください。
しかし、実は、同じ仕事をするプログラムを、次のように書くこともできます。
#include <stdio.h>
int main(void)
{
printf("こんにちは\nお元気ですか?\n");
return 0;
}
「\n」は出力における改行を表わすのでした。したがって、上のように文字列を1行で書いても、出力は「\n」のところで改行されるのです。これでも、実行すれば、hello2.cのときと同様になるので、これも正解です。
次に進む前に、いくつかコメントをしておきます。
まず、Cでは、意味のあるものの途中でなければ、空白を入れても入れなくてもよいことになっています。(ただし、日本語の空白、つまり全角の空白は、「空白」ではなく「文字」として扱われます。)たとえば、printfの前の空白は、インデント(字下げ)などとよばれるもので、コンピュータへの命令としては意味はありません。これは、見やすくするために入れたものなのです。プログラムの実行に関しては、あってもなくても同じです。
また、Cでは、改行も空白の一種と考えられるので、改行も自由に入れたり、あるいは取ったりすることもできるのです。つまり、たとえば、上のプログラムを
#include <stdio.h>
int main(void){ printf("こんにちは\nお元気ですか?\n");
}
と書いても、
#include <stdio.h>
int main(void)
{
printf("こんにちは\nお元気ですか?\n"
);
return 0;}
と書いてもよいのです。特に、下の方の形で、
printf("こんにちは\nお元気ですか?\n"
);
は、わざといやらしい書き方をしました。このようなことをしてもよいのです。
しかし、むやみに改行を入れたものや、極端に空白の少ないものは、読みづらいと思います。そこで、一般には、インデントをうまく使い、見やすいプログラムを書くことが推奨されるのです。
もちろん、改行を含む空白を、意味のあるかたまりの中に入れることはできません。たとえば、printfはひとつの関数の名前ですから、空白を使って、途中で切ってしまうことはできないのです。つまり、たとえば、
pri ntf("こんにちは\nお元気ですか?\n");
とすれば、エラーになります。
また、「"」で囲まれた文字列を文字列リテラルなどというのですが、文字列リテラルの途中で改行を入れることはできません。そういうものなのです。しかし、空白(改行も空白です。くどいですね)で分けられた文字列リテラルは、自動的につなげられるということになっています。この性質を利用すると、hello2.cを
#include <stdio.h>
int main(void)
{
printf("こんにちは\n"
"お元気ですか?\n");
return 0;
}
のように書き直してもよいのです。printfの丸カッコの中には、「"こんにちは\n"」という文字列リテラルと「 "お元気ですか?\n"」という文字列リテラルがあります。これらの間には、空白しかありませんが、空白は無視され、2つの文字列リテラルは1つに結び付けられるのでした。その結果、「こんにちは\nお元気ですか?\n」を出力するのと同じことになるのです。
今回はこの辺にしましょう。