執筆者:mznh今回はそこそこ難しい概念である関数と配列を学びます。わからなくなったら即質問してください。関数とはプログラミングというのは何かと数学で聞いたことのある単語が出てきます。この関数もそうですね、f(x)とかg(x)とかいうアレです。数学ではf(x)=ax2+bx+cとおく。みたいな感じで使われていました。これはax2+bx+cという計算の手続きをf(x)とまとめて表記していると考えることが出来ます。(これをf(x)を定義するとも言ったりしますね)これをプログラミングの話に置き換えてみましょう。プログラムの至るところで「指定された変数を2乗して100足して2で割った数」が使われているとします。指定された変数を仮にaとすると、(a*a+100)/2というのをたくさん書くわけです。すごい面倒くさいですね。それに何回も書いているうちにミスをするかもしれません。そこでこれをfという名前の関数に置き換えてあげれば、f(a)これだけで済むわけです。しておけば後々この処理を「aを2乗して200を足して2で割ってそれに最後に10を足す処理」に変更したいなと思った時でも関数fの内容を書き換えるだけで済みます。実際にC言語における関数の作り方を学んでいきましょう。関数を作ることを関数を定義するといいます。返り値の値;}という風に書きます。実は今まで必ず書いてきたmain関数もこれに沿って宣言していました。0;}なお引数を持たない関数の場合は上記のように引数を省略することが出来ます。定義の仕方とこのmain関数を見比べてみれば「このmain関数は引数をとらず返り値にはint型の0を返している」ということがわかると思います。これから今出てきた関数の各用語について説明していきます。引数とは関数に与える値のことです。簡単にいえば機械に突っ込む材料といったところでしょうか。ハンバーグを作る機械があったとしたら。ひき肉やタマネギやつなぎの卵とかが引数です。hamburg;}といったところでしょうか。(当然ですが中の変数の型とか関数名はデタラメです)またこのhamburg_maker関数のように複数の引数を与えることが出来ます。引数の仮の名前,・・・){}といった形で書きます。a,b,c;という風に書けましたが関数の引数の場合はそれが出来ない点です。して与えられた引数はそのまま関数の中で変数として使うことが出来ます。この変数のスコープはこの関数の中だけです。ans;}返り値これは簡単に言えばf(x)の値です。数学でy=f(x)という式があったとしてf(x)の値が5だとすると上記の式は展開されてy=5となります。これをC言語では「f(x)が5を返した」と表現します。基本的にプログラミングにおいて関数はひとつの値しか返すことが出来ません。引数をとらない関数は引数を省略できると言いましたがより明示的に引数が無いことをvoidという型を使って示すことができます。0;}同様にして返り値が無い関数も宣言することができます。hogehoge;}さてここまでのまとめして実際に関数を宣言してそれを使っているコードを見てみましょう。#include<stdio.h>//int型の引数を2つ取りint型を返す//add_numという名前の関数を定義しています。0;}自作した関数を自作した関数の中で使う。自分で定義した関数は最初からあるprintf関数等と同じように別の自分で定義した関数の中でも使うことが出来ます。関数を使う場合は使う行よりも前に定義しなければなりません。ans=add10(x)/2.0;//↑で定義したadd10関数を使っています。宣言だけを最初にまとめて書いておいてmain関数の後に本体を書く。なんてことができるようになります。//!!最後の;を忘れないように!!を書いた後にmain関数の後に。書けば普通に関数を定義したときと同じように自作した関数を使うことが出来ます。再帰関数これはかなり発展的な内容です。わからなくても全く構いません。再帰関数という概念があるよとだけ記憶の片隅にとどめておいてください。関数を定義する際にその関数自体を定義の中に含めることが出来ます。}}こういった関数を再帰関数と呼びます。実はこれ階乗を計算する関数なんですが数学の定義をそのまま記述しているだけなんです。:(otherwise)このように再帰を使うと一部の処理がとても簡潔に書けることがあります。文字とコンピュータ配列や文字列の前にまず文字について学びます。皆さんご存知かと思いますがコンピュータは0と1しか扱えません。これを2進数と言い工夫すれば我々の使う10進数も表現することができます。数値だけではABC..のようなアルファベットを表現することが出来ません。そこで昔の偉い人たちは'A'には65、'B'には66、と言った感じで文字と数字を対応付けることを考えつきました。これがASCIIコードと呼ばれるもので現在でも使われています。(なお残念ですがASCIIコードに含まれている文字はa-zA-Z0-9などの英数字と;.,などの記号だけです。いわゆる全角文字は含まれていません。)なお今後文字という場合にはASCIIコードで定義されている文字だけを指します。charというのはcharacter(意:文字)の略なのでほとんど文字のために用意された型と言っていいでしょう。char型は整数値でいうと-128~127までしか記録できません。「'」(シングルクォーテーション)で囲むとそれはASCIIコードでその文字を表す数値を意味します。'A';printf("%d",mozi);このようにするとprintf関数は「65」を出力します。'A';printf("%c",mozi);このprintf関数は「A」を出力します。ASCIIコードで65という数値は'A'と対応しているわけです。65;printf("%c",mozi);このように直接65という数値を入れてもこのprintf関数は「A」を出力します。1;printf("%c",mozi);このようにするとprintf関数は「B」を出力します。配列と文字列さてC言語においてわりと難しい概念である配列に入ります。学生の成績のデータがあったとします。ヤマダさんは50点、タナカさんは60点、スズキさんは70点だとします。70;こうしてもいいんですがこれだと学生の数が増えたときに面倒ですね。この変数達をまとめて扱えるようにしたい、そこで配列というものが必要になってきます。配列は同じ型のデータをひとまとめにしてそれぞれに番号を付けたものです。具体的には以下のようになっています。|・・・|_____|_____|_____|_____|_____|_____|変数をデータを保存する箱のようなものと以前説明しましたがこれは箱がならんでくっついているイメージです。その箱のそれぞれに番号が付けられています。注意してほしいのは番号付けが0から始まっている点です。配列の宣言は通常の変数の宣言とほとんど同じですが名前のところが少し違います。配列の場合は名前を配列の名前[宣言したい配列の長さ]にします。配列の長さとは上の例でいう箱の個数のことです。array[10];と宣言します。]の中の数字に変数を使うことは出来ません。先ほど例で宣言したarray配列の3番目の箱に10という値を代入したい場合はarray[3]=10;というように書きます。配列の箱の番号は0から始まるので3番目の箱の番号は2です。よって配列の3番目の箱に10という値を代入したい場合はarray[2]=10;というように書くのが正解です。配列の宣言をした直後だけは以下のような特殊な代入方法が使えます。{0,1,2,3,4,5,6,7,8,9};これで配列には順番に0,1,2,...,8,9と値が代入されます。このように変数の宣言と同時に値を代入する行為を初期化と呼びます。array[10];と宣言したこの配列は10個の箱でできています。箱の番号は0から始まるのでこの配列の箱の番号は9までです。何番目の箱かを表す数字(array[5]でいう5)を添字(そえじ)とそれぞれ呼びます。配列に関して一つ注意すべき大事なことがあります。C言語の配列はそれだけではその配列がどれだけの長さか分からない点です。先ほど例で宣言した配列はarray[9]までしかありませんがarray[100]=10;とプログラム中で書いてもコンパイラは何もエラーを吐きません。(賢いコンパイラだったら何か言ってくれるかも)またこれは定数を添字に使っているのでまだ判別可能ですが添字に変数を使ってアクセスしようとした場合実行されるまでどうなるかわかりません。これは次回やる範囲の知識が必要になるので今は聞き流す程度でいいですが配列の名前(例だとarray)は配列の最初の要素(array[0])のポインタを指します。第一回の講習でちらっと話したのですがC言語において文字と文字列は違うものです。文字を'(シングルクォーテーション)で囲むのに対して文字列は「"」(ダブルクォーテーション)で囲んで表します。正確に言うと文字列は配列の最後に'\0'(NULL文字)という特殊な文字がついてます。この'\0'が文字列の終わりを示しています。具体的な例を示しましょう、例えば”Hello”という文字列が格納されているstringという名前の配列があるとすると以下のようになっています。fuga"のような文字列も上記のような形で展開されていました。今まで説明してきた配列、文字列はどれも1次元の配列でした。実は2次元、3次元、n次元の配列も宣言することが出来ます。2次元配列を例にとって説明しましょう。matrix[4][5];というふうに宣言します。これは正確に言うとint型の要素数5の配列を格納する要素数4の配列を宣言しているのですが、それは追々理解してもらえればいいです。2次元配列を使う通常の配列と同じように扱うことが出来ます。配列とfor配列を扱う際は前回学習したfor文を使うと便利です。10;//配列の要素数を記録しておく。",array[i]);}上のプログラムは配列の中身最初から順番に出力してくれます。書き足すと文字列を扱う便利な関数が使えるようになります。ここではその一部を紹介します。strcpyこれはある文字列の内容を別の文字列にコピーしてくれる関数です。from,toという名前の2つの文字列が宣言されていてfrom文字列の中身をto文字列の中身にコピーしたいとしたら以下のようにします。strcpy(to,from);strcatこれは2つの文字列を連結してくれる関数です。beforeとafter2つの文字列が宣言されていてbeforeの後にafterの中身をくっつけたいときは以下のようにします。strcat(before,after);strlenこれは文字列の長さを返す関数です。messageという文字列が宣言されていてその長さを知りたいときは以下のようにします。strlen(messaage);//lengthの中にmessageの長さが格納されます。putsこれは#include<string.h>を追記しなくても使える関数なのですが今まで説明してなかったので紹介しておきます。この関数は低機能はprintf関数で固定の文字列しか出力してくれません。最後に勝手に改行を入れてくれます。puts("Hello");上記のようにするとHelloとHelloが表示された後に改行が入ります。この他にも様々な関数がたくさんあるので各自調べてみてください。何も引数をとらない"Hello"と出力するだけの関数を作成せよ。表記してもこれはxの3乗を意味しません。最初に整数nを入力しその後n個の整数の入力を受け取った後にそれを最初から順に出力するプログラムを作成せよ。スペースや改行を含まない文字列の入力を一つ受け取りそれをそのまま出力するプログラムを作成せよ。スペースや改行を含まない文字列の入力を一つ受け取りそれを逆にして出力するプログラムを作成せよ。"abcd"と入力されたら"dcba"と出力)以下は前回の範囲の発展的な演習です。ライセンスの下に提供されています。