C言語プログラミング

[| ]  最終更新: 2011/02/10 19:34:58

このページについて

このページでは、「C言語で手順をコンピュータに指示する」ための、考え方に重点を置きます。 C言語の入門書などにありがちな、「言語そのものの解説」は減らし、予め、そこそこできたひな形をいじる形で、プログラムをつくっていきます。

ひな形は、このページからコピーしたりすれば一瞬で手に入りますが、 「あえて手で打ち込むこと」を強く推奨します
小中学校といろいろ覚えるときに、ひたすら繰り返しノートなどに書いて覚えたと思います。 一番最初のひらがなから。
それと同じです。意味がよくわからなくとも、打ち込み続けることで頭だけではなく指も慣れ、最後にはなかば無意識でプログラムが作れるようになると思います。<なった人
また、コピーは一瞬過ぎて、その内容を考える暇がありません。 打ち込む速度で考え、動かしてエラーが出たときにどこがおかしいのかを探し、直すことで、次第に意味が通じるようになります。


プログラム・プログラミング言語

コンピュータの世界で「プログラム」といったら、コンピュータに処理させるための手順を記したものです。
運動会のスケジュールであるプログラムも、番組表を意味するプログラムも、どちらも「順番」であるように、コンピュータのプログラムも順序立てた仕事の記述です。
多くの言語では、書かれた順番に処理を進めます。

プログラムにはいろいろな形式があります。
最終的には、コンピュータが直接理解できる、01なデータの固まり(マシンコードとか、バイナリとか呼ばれます。)として実行されることには違いありませんが、たとえば、
  A=B+C
と書いたり、
  B+C→A
と書いたり、
  BとCの合計をAに入れる
と書いたり、単に合計を求めるにもそれらしくわかる書き方がいくつかあるように、「指示の仕方」が何通りもあります。
指示の仕方の文法を取りそろえたものをプログラミング言語で、膨大な種類があります。
(すでに業界でよく使われるものがあっても、それなりに欠点があるので「俺様言語」を開発する人がたくさんいるので。その中から爆発的に広く使われるようになる言語もたまにあります。)

「プログラムをつくる」ということは

  1. コンピュータにさせたい仕事を明確に手順化する
  2. 使っているプログラミング言語で記述できるところまで、細分化する
  3. プログラムに置き換えていく
ことです。まず、第一に、「手順を明確にできること」これができなければコンピュータを使うことはできません。 どの言語を使うときにも必要で、表計算ソフトを使うときにすら必要です。
次に、細分化と置き換えです。これは言語を知っていないとできません。ほとんどの言語は、基礎的なお約束は共通性があるため(例:四則演算はA+-*/Bで書けるとか、上から順に進むとか)、限界まで細分化すれば、やはり言語ごとの共通性はあります。
しかし、プログラミング言語は「いかに楽に指示を出すか」も考えられています。限界まで細分化しなくても指示できることもあります。 「プログラミング言語」を学ぶということは、「その言語のできることを知り、手順を書く方法を知る」ことです。
しかし「プログラムを作ること」を学ぶのは、いかに手順を明確にするか、単純化するか、適切にするか、それを学ぶことです。 それができていれば、言語は本来あまり問いません。 「一つプログラミング言語を知っていれば、別の言語を学ぶのはたやすい」とよく言われますが、「プログラム」を学ぶ際に大切なのは、言語そのものではなく、「指示の仕方」だからです。

その観点からすると、プログラムの作り方を学ぶにはいろいろな言語が使えますが、ここではC言語を使います。
C言語(およびその改良版?であるC++言語)は幅広く使われています。
その特徴として、比較的「みてわかりやすい」言語でありながら、コンピュータの隅々まで指示できる「汚さ、泥くささ」をもった言語です。 情報系や計算系の立場的には、コンピュータのハードウエアにちょっかいを出すことは想定されていませんが、機械をコンピュータで動かそうというときには、ハードウエア操作も不可欠になります。
C言語の開発由来もそれ系で、いまでは、「組み込み」と呼ばれる機械に近いところで動くプログラムを書くときにはなくてはならない言語になっています。
一方、機械科のコンピュータ系演習科目で使われる頻度が高いFORTRANという言語は、主に計算向きです。機械制御などは想定されていません。 比較的文法などが(コンピュータからみて)単純で、演算の高速化(最適化=勝手に処理順序を入れ替えるなど)がしやすいとされています。 以前はスーパーコンピュータはFORTRANでなければ動かせないといわれてましたが、最近は普通にC言語も使えるようです。


はじめにで述べたように、コンピュータは演算処理部と、記憶部があります。 プログラムの面から見て、この演算処理部でできることは、大きく二つ。 その過程で、演算に必要なデータ(変数)はメモリとやりとりし、手順であるプログラムもメモリから読み取ってきます。

たとえば、

  1. 変数iに0を入れる。
  2. なにかする
  3. 変数iに1を加える(厳密には、iに1を加えたものをiに入れる)
  4. 変数iは10未満なら2へ、そうでなければおわり
というプログラムを書くと、「2:なにか」を10回「する」ことになります。
(手っ取り早くは3未満、くらいにしていちいち追ってみて3回なら、10でもいっしょ、と考えるのが無難)
ここで、「なにかする」では「するごとに0〜9で変わる数字i」を使うことももちろんできます。
  1. 変数iに0を入れる。変数sにも0を入れる。
  2. sにiを加える
  3. 変数iに1を加える
  4. 変数iは10未満なら2へ、そうでなければおわり
終わったとき、「sに0を加える」「sに1を加える」....「sに9を加える」となり、結果的にsは0+1+..+9=45になるはずです。

「できること二つ」は組み合わせ次第で、いろいろな計算ができます。
ただし、実際にプログラムを作るには、言語ごとに「演算式の書き方」と「判断する対象の書き方」を覚えておく必要があります。


C言語で最低限暗記しておくべきこと

ここでは、C言語でプログラムを作る上で「暗記しておく」=「調べなくても使えるようにしておく」ことをなるべく最低限あげておきます。
各自、参考書などを見るときに参考にしてください。

なお大前提として、プログラムは「半角英数記号」だけで書きます。全角はつかえません。
また、後述しますが、原則として各記述(数式など)の後ろには「;」(セミコロン)をつけます。
また、プログラムの中で 「/*」「*/」 で囲まれた部分(複数行のことあり)、1行のなかで「//」の後ろは「コメント」といって、無視されます。 メモ書きなどに使えますし、日本語もそこなら使えます。

変数

変数=値の入れ物 です。

表計算ソフトのセルにあたるものですが、あれに比べるとずっと制限がきつく、予め「○○の種類を入れる」と決めて、かつ、自分で名前をつけておかなければ使えません。
(種類を決めることで効率はよくなる。何を入れるかわからない容器よりは、わかっているほうが適切な大きさ、また、使うときに気を遣わなくなるため。名前は「自由につけられる」という利点。)

この講義で使うものは

のみです。 C言語の本を見ると、いろいろありますが、実際問題、この2種類だけで各種計算はできます。
いろいろな効率を考えたり、人とやりとりするようなプログラムを作ろうしなければ、この2種でいいです。

整数や小数の変数を用意するときは
  int i,j,k,seisuu;
  double a,b,c,shosu;
と書きます。複数を同時に作りたいときは「,」で区切ります。

以下雑学:
小数に整数が含まれますが、普通はあえて、整数ですむものは整数ですませます。 一つは効率の問題です。1+1を計算したいときに、1.0000000+1.0000000と電卓を打つのは無駄です。
もう一つは、なんでも小数でやると、思わぬ失敗をすることがあるからです。 特に、直接的、間接的に回数を数えるときに小数をつかうと失敗する場合があります。
(有名どころとしては、0.1+0.1+0.1+...という計算で誤差が出る。<0.1は2進数で表現できない数:循環小数)
そこで「整数ですますべきところは整数ですませる」癖をつけておく必要があります。

今回の演習環境ではintは±20億くらい、doubleは有効桁数15桁(で10の±300乗)くらいの範囲が表せます。
使い方にもよりますが、困ることはあまりないかもしれません。
(たとえば、10の5乗に10のマイナス12乗くらいを加えると無意味、という問題が生じる)

蛇足ですが、いろいろな習わしの関係で、変数で「i,j,k,l,m,n」は普通は整数にします。 Σなどでもよく出てきますが。
習わしは文法でもないので、ある意味無視してもかまわないのですが、業界標準の習わしを無視すると、だれかに見せたりするときに誤解を招くことがあるので、普通は従っておきます。
習わしの重要な例で「赤と黒の電線があったらプラスは赤にする」というものもあります。 その慣例を無視して逆につなぐと、別の人が先入観で電源をつないで回路から煙があがることになります。
(俗に、iはinteger:整数のi, nはnumber of:個数のnでその周囲が使われているとか。 一般に、i,j,kは数を順番に数えるため、l,m,nは全体の個数を表したりするときによく使われます)

演算と式

C言語では普通に数式を書くに書けます。ただし、×を省略しては書きません。

  1. 「変数=式;」と書くと、プログラムの手順が進んでその式にきたときに、「式」の値が計算されて、「変数」に代入される。
    「=」の左辺は必ず変数でなければならない。
    また、この式まで手順が進んだとき初めて計算されるので、常時この関係があるわけでもない。
    ※表計算では、つねにその関係が成り立つように見張っていて値の書き換えがあると自動的に計算するようになっている。
  2. 四則演算+−×÷→ "+,-,*,/"
    「()」で演算順序を優先できる。例:e=(a+b)*(c-d);
    "%"は整数の計算で使われ、「割り算のあまり」となる。案外使い道がある。
  3. 「変数++;」と書くと、変数に1を加える。例:a++; は a=a+1; 相当
    同じく、「変数−−;」は1減らします。
    ※頻繁に使うので、専用の演算がある。コンピュータ固有の命令にもあることは多い。
  4. 一つの演算をするときに、一方が小数なら小数の計算をし、結果を小数とする。両方とも整数なら整数として計算し、結果も整数。
    例:1/5→0(1を5で整数の割り算すると0あまり1)、1/5.0→0.2、1.0/5→0.2
    例:int i,j; i/jは整数演算、int i; double d; i/dは小数演算。
    気をつけていないと、案外失敗の原因になる。連続するはずの数字がとびとびにでてきたり、比率を求めようとして常に結果がゼロにしかならないといったことを引き起こす。
  5. 「a==b」「a!=b」「a<b」「a>b」は判断のための条件式。
    一致が「==」と「=」を2回続けて書くことに注意。
    「a!=b」は「等しくない」
    それぞれ「成立していないとき」=「偽のとき」、「0」の値を持ち、「成立した=真」のときはゼロ以外の値になる。
    これは、判断をする場合に「ゼロ以外は真、ゼロなら偽と見なす」というルールのため。
    なお、代入の=ではないので、左辺が変数でなくとも(数値や式)だいじょうぶ。
  6. 「(条件式1)&&(条件式2)」は両方の条件とも満たされる場合に「真」扱い、 「(条件式1)||(条件式2)」はどちらか満たされる場合に「真」扱いとなる。
    それぞれの条件式は「()」でくくっておいたほうが間違いがない。
    例:(a==b)&&(b==c) は「a=b=cのとき」を表す。「a==b==c」とは書けない(期待する結果にはならない)点に注意。
    「!(条件式)」は真偽を反転させる。
他にもC言語の本をみると、「演算子」という項目にいろいろありますが、とりあえず、これだけ把握しておけば、この科目はOKです。たぶん。

プログラムの構造

C言語のプログラムは式の計算などを一つ一つを手順を順番に書くことで構成されます。
おのおのの手順は、以下の2通りで書かれます。

  1. 「手順;」
    と「;」で終わる一文。
    数式が長くなって、複数の行に渡って書いても「;」までを一つと見なし、逆に一つの行に「;」で区切られて複数の式が書いてある場合もある。
    ただ、原則として、一つの手順は1行で書く。
  2. 「{ 手順; 手順; 手順;... }」(最後にセミコロン無し)
    手順をひとまとめにしたもの。中括弧「{}」でくくる。中は空でも、1つでもかまわない。
    これで一つの手順を同じ扱いになる。
    いくつか{}でくくることによる利点はあるけど、主に、次の条件判断による実行時に大きな意味がある。

C言語で普段使う条件による実行「もし〜なら〜する、さもなければ〜する」の系統は、大きく3種類が使われます。

  1. if (条件式) 手順1; else 手順2;」 もしくは
    if (条件式) { 手順; 手順; ..} else {手順; 手順; ...}」
    すぐ上の、手順ひとつかまとめるかという違いのみで、重要なのはifとelse。
    「もし〜なら〜する」だけでおしまいなら、else以降は省略する。
    なれるまでは、面倒でも後者の形式を使い、「if(){}」を基本パターンとして覚える。
  2. while (条件式) 手順;」
    while (条件式) { 手順; 手順; }」
    まず、条件式をチェックして、真なら、手順を1回(1セット)実行する。 終わったら、また条件式をチェックして、真なら実行する。
    チェックした段階で偽なら、実行をやめて、「手順/{手順}」のあとにすぐ移る。
    (なので最初で外すと1回も実行されない)
  3. for (i=0;i<n;i++) 手順;」
    for (i=0;i<n;i++) { 手順; 手順; }」
    この記述の場合、「i=0からn-1まで数えつつ、手順/{手順..}を繰り返し実行する」という意味。 結果的に、n回実行され。
    バリエーションとして、
    for(i=1;i<=n;i++) {} :i=1からnまで
    for(i=n;i>0;i--) {} :i=nから1まで
    がある。
  4. 「break;」
    while, for のなかで、これに到達すると(if(条件) break; などと使われることが多い)、強制的にwhile, forの中の処理をやめて終わってしまう。
    「continue;」
    while, for のなかで、これに到達すると、条件判断に強制的にもどる。
    どちらも、{手順; 手順;}と複数の手順を並べているときのみ意味がある。
    また、for(){}のなかにforを書くなど、多重になっているばあいは、今実行しているところで一番内側のforやwhileに作用する。
  5. 「for(開始時手順;条件式;繰り返し手順) 手順;/{手順;..}」
    forの本来の姿。
    forに付随する手順を実行する前に「開始手順」を実行、その上で「条件式」を判断して真ならば付随する手順を実行する。その後「繰り返し手順」を実行し、条件判断を再度行う。
    上の項目は「開始時にi=0」「判断はi 例:for(i=1;i<100;i=i+2) =「i=1,3,5,7,9,..99と奇数を数える」

関数

C言語で手順をまとめて、独立した1ブロックにしたものを関数といいます。
関数には入力するもの「引数(ひきすう)」と出力の値「返値(かえりち)」があります。
  b=sin(a);
は普通の数学の関数に見えますが、C言語的には「aという引数をsin()という関数に渡して、その返値をbに代入」と解釈します。
基本的に関数は、
  関数(引数,引数,引数,...)
と「()」が必ずつきます。たまにある、引数のない関数は「関数()」と表記します(例としては「乱数を返す関数」とか)。
また、普通の関数は引数の数は決まっています(sin関数も値をいくつも与えない)。

関数は手順をまとめて使いやすくしたものなので、たまに(わりと)、
  関数();
とだけプログラムに書かれることがあります。 これは本当に手順だけをまとめていて、渡す値もなければ、戻ってくる値も使わないという状態です。 返値があっても、利用する必要はありません。また
  b=sin(a)*cos(a);
のように、式の一部として使うことももちろんあります。

関数を自分で作ることもできますが、とりあえず、使い方だけ把握しておきます。

プログラム全体の構造

一番簡単なプログラムの構成

#include <stdio.h>       // 普通は書く(この // の後ろはコメントで無視される)
#include <math.h>        // 数学関数を使う場合 cos, sin, tan, log, sqrt など

int main(void)           // 必須。ここからプログラムが実行される
{                        // この { も必須
  手順;
    :
  手順おしまい;
  return 0;              // 文句なく終わるおまじない。ないと文句いわれる
}                        // ここまで
プログラムを作る、という場合、まずは勢いでこれだけ書いてしまって、あとから中の手順を書く、というのが初心者にはお勧めです。

Cのプログラムをつくってみる

ここでは、演習室の環境で、実際にプログラムを作って動かしてみます。

環境準備

右クリック→新規作成→フォルダ
右クリック→新規作成→フォルダ
ファイル名を変更
ファイル名を変更
実習環境で用意したcygwinを使います。

まず、cygwinのフォルダ(マイコンピュータ→Windows(Z:)→cygwin)を開きます。 ここにはすでに、makereportフォルダがあるはずです。
makereportフォルダのほかにprogramフォルダをつくります。
フォルダのウインドウで、「右クリック」→「新規作成」→「フォルダ」。
フォルダができて、「新しいフォルダ」と青く表示されていたらそのまま「program」(enter)と入力します。
青くならずに、ただ「新しいフォルダ」ができたら、フォルダを選んで「右クリック」→「名前の変更」で変更できます。

以後、作業はこのprogramフォルダで行います。

C言語でプログラムを作って動かすには、以下の3手順が必要です。

  1. ソースプログラム(ソースファイル、ソース)の用意
    「プログラムを書く」作業。
  2. コンパイル
    「プログラムを変換する」作業。これによって、文字による文書的なプログラムが、コンピュータが直接実行できる形に変換される。
  3. 実行
    変換されたものを実行する。これはWindows上のソフトを動かすのと「実行」という意味では同じ。
基本的に変換されたプログラムをいじることは困難で、プログラムの修正というとソースの修正です。 なので、修正するたび、「修正→コンパイル→実行」を行います。
たまにソース変更したのに結果変わらない〜と悩むことがありますが、コンパイルで失敗していたり、そもそも変更したソースを保存していなかったりというへまが原因のことも案外あります。


ソースプログラムの用意

右クリック→新規作成→テキスト
右クリック→新規作成→テキスト
ファイル名を強制的に '○○.c'に変更
ファイル名を強制的に '○○.c'に変更
フォルダオプション
フォルダオプション
ソースを用意するには、適当なエディタ(編集ソフト)で、ただ、普通にかきます。
演習室のコンピュータで手頃なのは、TeraPad、メモ帳、VisualStudioです。
VisualStudioは本来は、この上でC言語などのプログラムの編集から実行までできるソフトですが、使い方を学ぶだけでかなりの手間がかかるので、本講義ではつかっていません。 が、一番簡単に起動するので、以下ではそれを前提にします。

まず、先ほど作ったprogramフォルダを開きます(最初は空のはずですが)。 ここで「右クリック」→「新規作成」→「テキストドキュメント」を選びます。
すると、"新規テキストドキュメント.txt"とか、ファイル名が勝手についたファイルができるので、これを「prog1.c」に変えます。
(上のフォルダ名を変えるのと同じ操作)
変えようとすると「拡張子を変えていいんですか」的な確認を求められますが、そのままOKします。
すると、「C」と書かれたアイコンのファイルに変わります。
(中身は空のファイル、ただ、".c"をつけたことで、Windows的にはC言語用のファイルと思うことにした)

この際、もしも、"新規テキストドキュメント"に".txt"がついていない場合(右2枚目の青○の中:この例ではついている)、フォルダのウインドウのメニュー→「ツール」→「フォルダオプション」を開き(右図3枚目)、「表示」タブの「詳細設定」の下の方の「登録されている拡張子は表示しない」に「チェックが入っていたら」外してください(→適用ボタン)。もし、チェックがついていないのに表示されない場合は、相談してください。


VisualStudioの画面
VisualStudioの画面
ソースを入力する
ソースを入力する
C言語ヘルプ
C言語ヘルプ
このprog1.cファイルをダブルクリックすると(わりと時間はかかります)、VisualStudioが起動して、ファイルが編集できるようになります。 とりあえず、使い方の詳細は省きますが、Windowsの他のソフト同様、ファイルメニューで開いたり保存したりできます。 Ctrl-Sでも保存できます。
このファイルをTeraPadにドラッグアンドドロップすればTeraPadで開くこともできます。

開いたら(空ですが)、以下のプログラムを入力してください。

#include <stdio.h>
#include <math.h>

int main(void)
{
  int i,j;

  j=0;
  for(i=0;i<10;i++)
    {
      j=j+i;
      printf("%d %d\n",i,j);
    }
  return 0;
}
※プログラムの各行の先頭の空白は、プログラムとしては「どうでもいい空白」でなくともかまわないものです。 ただ、対になる{と}を明白にするため、また{}で囲まれた部分は一つの手順のまとまりなので、その構造を明確にするため、空白をいれて右に段々にします。
※よってこの段々の隙間は「何文字」ということに気を遣う必要はありません。C言語対応のエディタの多くは、ある程度自動的に入れてくれます。VisualStudioでも、改行すると自動的にそれっぽい位置まで「TAB(タブ)」という空白の一種をいれてくれます。ので、それに任せるのが楽です。

いれたら保存してください。

注意 プログラムはこのページからコピー&ペーストすることなく、 手で入力 してください。
文字を鉛筆で書いて覚えたように、プログラムもまた、キーボードから繰り返し打ち込むことで、なれて覚えてきます。
includeとかmainとかprintfとか、毎回出てくるようなキーワードもすぐになれます。

プログラムを作れるようになる、とは、成功や失敗を繰り返すことで、経験値を増やすことです。
コピペですましてしまうと、おそらく、入力ミスなどに起因するエラーに遭遇することもありません。 それではなんのためにもなりません。今はよくても演習課題やレポートのときに、自分でできなくなる確率も上がります。

以上で、ひとまずソースの作成は終了です。

参考:
Visual Studioは本来C言語などの開発環境一式のソフトです。
そのエディタだけをつかっていますが、便利な機能として、適当なキーワード(たとえば、見慣れない printf とか)にカーソルを置いてF1キーを押すと、なんらかの解説がでることがあります。 実際には、あまりに関連する項目が多すぎて、期待するものではないかもしれませんが、使い慣れてくると、プログラムを作るときの辞書代わりに使えます。

コンパイル

次は変換作業を行います。

デスクトップにコピーした「cygwinへのショートカット」を起動します(もしくはマイコン→Y:→cygwin→cygwinへのショートカット)。
(基本的にレポート提出の手順と近い)。

つぎに、$マークが出たら

$ cd program 
($が表示されているところに cd.. 入れてEnter)
と入力します。さっき作ったprogramフォルダで作業するように指示しました。

そこで、

$ gcc -o prog1 prog1.c
と入力します。
(gcc[スペース][マイナス][小文字のオー][スペース]prog1[スペース]prog1.c)
gcc がコンパイルするソフト(コンパイラ)、"-o prog1" は変換結果を "prog1"という名前で保存するように指示、"prog1.c"がコンパイル対象のソースのファイルです。
間違って、"-o prog1.c"とここで".c"をつけると、せっかく入力したソースが壊れる可能性があるので、気をつけてください。

まったく問題がなければ、何事もなかったかのように、また$がでます。
programフォルダをみると(F5を押すと)prog1.exeができています(残念ながらダブルクリックしても動きません)。

そうでない場合は、「error」とか「warning」とか書いてあるエラーが出てきます。英語で。
プログラムを作る以上、これらは避けて通れません。これになれるのも重要ですので、出たら、正面から向き合ってください。
英語ですが、よく見ると単純なことしか、普段はいってません。
必要なら、まずは単語を調べてみましょう。 →gooの辞書、 →英辞郎

ついでに、表示をみると、"line ??"と書いてあります。これはエラーが出た場所が何行目かを表しています。
この手のエラーのやっかいなところは、その行よりも前の間違いでもエラーがでることですが、まずは、指定された行をみてみましょう。
あっさりと「これじゃだめじゃん」な間違いに気づくかもしれません。
典型的なエラーは別にまとめておきます。

エラーは直して、ソースを保存して、またコンパイルです。
その際、cygwinのウインドウで「↑」(上矢印キー)を押すと、直前のコマンドをさかのぼって呼び出せます。覚えておくと便利です。

実行

コンパイル→実行
コンパイル→実行
プログラムが止まらなくなった!
プログラムが止まらなくなった!
Ctrl-Cで止める
Ctrl-Cで止める
ここまできたら、動かせます。

$ prog1
レポートをつくるmakereportも、gccもcygwin上で実行できるようにつくったプログラムなわけで、新たに、自前でprog1というソフトをつくったことになります。

今回のプログラムはすぐに「$」が戻ってくるはずですが、表示が止まらないとか、なにもおこらないという場合は、プログラムが間違っていて暴走している可能性があります。
プログラムの強制停止 はControl-Cです。変だと思ったら、とりあえず押してみましょう。
なお、それでもだめそうなときは、cygwinのウインドウごと消してしまってもかまいません。

期待通りのプログラムなら、

$ prog1
0 0
1 1
2 3
3 6
4 10
5 15
6 21
7 28
8 36
9 45
とか表示されると思います。

画面に数値/文字を表示する

プログラムは何らかの結果を出力するために作られます。

出力には様々な方法があります(ある意味、ロボットが動くのも「ロボットを動かすプログラムの出力の結果」)が、一番手っ取り早いのは、そのまま画面に数字等で表示してしまうことです。

ここでは、その代表格であるprintfを簡単に説明します。

printf() ぷりんとえふ

画面に出力する際にもっともよく使われるものに printf()関数があります。
関数といっても返される値には関心はなく、もっぱら「便利な機能をまとめたもの」としての関数です。

本講義でも頻繁に使いますが、世の中でもよく使われています。
それを端的に表す言葉として「printfデバッグ」(デバッグ=誤りによる不具合解消)という言葉があるくらいです。
プログラムは、コンパイルができれば(エラーなどがなければ)完全というわけではありません。 むしろ、たいていはそこがスタートラインで、そこから機能的に望んだものかどうかのチェックと修正という、最重要段階が始まります。
その際、動作が怪しいと思ったところで、とりあえず変数の値をかたっぱしから表示させて動作具合をみる、そもそもそこが実行されているか怪しいときに適当にaaaとか表示させてみる、ということを行います。それを称するのが「printfデバッグ」です。

さて、printfは、以下のような使い方をします。

printf("書式文字列",値1,値2,.....);
たいていの関数は渡される引数(括弧内に並べる変数など)の数が決まっていますが(sinは1個のみなど)、このprintfは最低1個、そのあと必要なだけ並べるという決まりがあります

「"書式文字列"」は「"」でくくった適当な文字列(文字のつらなり)で、画面に表示される文字を決めます。
ただし、一部に特殊な文字を含めることができます。

他にも多数ありますが、とりあえず、これだけは覚えておいてください。 これだけ覚えていれば、ただの計算をさせたりするには困りません。
(%d,%fがなければ、本当にただ文字を表示するだけになります)

ただし、このままだと、表示はきれいにそろいません。整数は必要な桁数を表示するだけ、小数も適当な桁数表示するだけなので、桁数に応じて文字の数が変わったりします。そういうのを気にする場合は、

を覚えておくといいでしょう。

数値は、%dの場合は整数を、%fの場合は小数を、書式文字列内に%d,%fが出てくる順番に与えます。
例:printf("%d %f %d\n",整数,小数,整数);
間違うと、ぐちゃぐちゃな値が表示されます。
(printfに渡されるのは、あくまでゼロイチな組み合わせの値で、%dか%fかでprintfが解釈の仕方を変えるため)。

この数値は、変数そのもの、ただの数値、数式などがつかえます。
例:printf("%d %d %f\n",i,i*i,3.141592);
ただ、数式を書く場合は、整数のみの演算式だと整数に(%dに対応)、一部に小数が入ると小数に(%f)になることに注意が必要で、また、ただの数値も小数点があるかないかで変わります。


ためす

次のプログラム prog2.c をつくって、コンパイル、実行してください。

#include <stdio.h>
#include <math.h>

int main(void)
{
  int i;
  double th;

  for(i=0;i<10;i++)
    {
      th=2*M_PI*i/10.0;
      printf("%d %f %f\n",i,th,sin(th));
    }
  return 0;
}
printfと修正
printfと修正
$ prog2
0 0.000000 0.000000
1 0.628319 0.587785
2 1.256637 0.951057
3 1.884956 0.951057
4 2.513274 0.587785
5 3.141593 0.000000
6 3.769911 -0.587785
7 4.398230 -0.951057
8 5.026548 -0.951057
9 5.654867 -0.587785
のような結果が出るはずです。

次に、printfの行を

printf("%d %f(%fπ) %f\n",i,th,(i/10.0)*2,sin(th));
と修正して、コンパイル、実行(""の中ならば、全角文字(πや漢字など)使っても問題なし)。
さらに、
printf("%2d %4.2f(%3.1fπ) %5.2f\n",i,th,(i/10.0)*2,sin(th));
のように変えてみましょう(書式文字列のみ)。
printfの表示の意味がわかると思います。
その際、もとのprintfも参考のために残しておきたい、という場合は、
  1. その行をコピーする(マウスでorSHIFT押しながらカーソル移動で選択、Ctrl-c、Ctrl-v、Ctrl-vなど)
  2. とっておく方の行の先頭に「//」をいれる。これでこの行はコンパイラが無視する
をします(右図参照、VisualStudioだと、//すると緑表示になる)。
$ prog2
 0 0.00(0.0π)  0.00
 1 0.63(0.2π)  0.59
 2 1.26(0.4π)  0.95
 3 1.88(0.6π)  0.95
 4 2.51(0.8π)  0.59
 5 3.14(1.0π)  0.00
 6 3.77(1.2π) -0.59
 7 4.40(1.4π) -0.95
 8 5.03(1.6π) -0.95
 9 5.65(1.8π) -0.59

やってみる

以下、適宜やってみてください。



2重ループと九九の表

C言語のループ(while, for)は2重3重にいれることができます。また、実際によく使われます。
典型的な例題として、九九の表を作ってみます。
// kuku.c
#include <stdio.h>
#include <math.h>

int main(void)
{
  int i,j;

  for(i=1;i<10;i++)  // i=1...9
    {
      for(j=1;j<10;j++)  // j=1...9
	{
	  printf(" %2d",i*j);
	}
      printf("\n");
    }
  return 0;
}
$ gcc -o kuku kuku.c
$ kuku
  1  2  3  4  5  6  7  8  9 ←i=1
  2  4  6  8 10 12 14 16 18
  3  6  9 12 15 18 21 24 27
  4  8 12 16 20 24 28 32 36
  5 10 15 20 25 30 35 40 45
  6 12 18 24 30 36 42 48 54
  7 14 21 28 35 42 49 56 63
  8 16 24 32 40 48 56 64 72
  9 18 27 36 45 54 63 72 81 ←i=9
よくみれば、とくに不思議なところはないと思います。
ここのprintfの" %2d"の"2"は見栄えという点でとても重要です。 試すまでもありませんが、どうして重要かがわからない、という場合は、あえて"2"をとって実行してみましょう。
同じように"%"のまえの空白一文字もとても重要です。むしろ、"2"より遙かに。

インド式の九九は20×20らしいです。
表示を気にしつつ、つくってみましょう。

挑戦 ここまでの内容が楽勝な人は

$ kuku2
  | 1  2  3  4  5  6  7  8  9
--+---------------------------
 1| 1  2  3  4  5  6  7  8  9
 2| 2  4  6  8 10 12 14 16 18
 3| 3  6  9 12 15 18 21 24 27
 4| 4  8 12 16 20 24 28 32 36
 5| 5 10 15 20 25 30 35 40 45
 6| 6 12 18 24 30 36 42 48 54
 7| 7 14 21 28 35 42 49 56 63
 8| 8 16 24 32 40 48 56 64 72
 9| 9 18 27 36 45 54 63 72 81
をなるべくエレガントにつくってみましょう。
ポイント:

演習課題

11/16 の講義開始まで に以下のプログラム kadai1.c をつくって、コンパイルし、実行できることを確認しておいてください。
それをもとに、16日にC言語な課題の提出方法を確認します。

簡単な結果例:
$ gcc -o kadai1 kadai1.c
$ kadai1
1 1 1    <ここでは何個か 最後の奇数 合計が
2 3 4  <表示されている
3 5 9
 :
125 249 15625
$     <ちゃんと終了するプログラムであること
最低限、こんな感じででるように。

いろいろと小細工を考えてみた例:

$ kadai1
  1個: 1=1
  2個: 1+3=4
  3個: 1+3+5=9
  4個: 1+3+5+7=16
  5個: 1+3+5+7+9=25
  6個: 1+3+5+7+9+11=36
  7個: 1+3+5+...+9+11+13=49
  8個: 1+3+5+...+11+13+15=64
123個: 1+3+5+...+241+243+245=15129
124個: 1+3+5+...+243+245+247=15376
125個: 1+3+5+...+245+247+249=15625
$
※もちろん、ここまでやる必要はありませんが、課題が楽勝で飽きる、という学生さんはこういうのをやってみるのいいかも。 このページ、ここで終了。


熊谷正朗 [→連絡]
東北学院大学 工学部 機械知能工学科 RDE
[| ]