Code023: Cプログラミング 〜C言語は関数の集合体〜

この記事は2002年に書かれたものです。


■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
【 Webプログラミング Code Sample 】                          Since2001/11/23

                 Code023: Cプログラミング 〜C言語は関数の集合体〜

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                                                    Produced by ichikoro.com

           ▼毎週月曜日と金曜日に配信しています。
           ▼等幅フォントでご覧いただくとキレイに見えます。
           ▼登録・解除はこちらから可能です。
               < http://www.ichikoro.com/webp/ >
                  ※バックナンバーへのリンクもあります。
                  ※お友達にもぜひお勧めください(^^)/

─【Contents】───────────────────────────────
    01.Review ................... 前回のおさらい
    02.Guide .................... printf関数:これまでの復習
    03.Guide .................... printf関数:出力書式
    04.Guide .................... printf関数:使用例
    05.Guide .................... 関数ってなに?
    06.Guide .................... C言語は関数の集合体
    07.Question ................. 今週の問題
    08.From Editor .............. 編集後記


                   【 Webプログラミングは毎週2本立て! 】

             ・月曜日版はWebの実際の活用方法などを特集します。
             ・金曜日版はHTMLやCGIなど一つの分野について最初から
              解説する講座になっています。現在はC言語入門です。


こんにちは、編集者の勝部です。

先週の土曜日だから...9日ですね、いつぞや見逃したロード・オブ・ザ・リン
グ見に行って来ました。ヨーロッパはいいですね!大自然の中をロングショット
で。う〜ん、たまりません。確かにCGとか使ってるんですけど、自然が上手い具
合にマッチしていて(映像は)なかなか見ごたえがあります。

ただ全体的に小奇麗にまとまってはいるんですが、話自体に奥深さが無いとい
うか、人間ドラマが単調というか(^^; 世界観が上手くストーリーに昇華できて
ないなぁという印象です。暗い感じが終始漂っているので、明るい気持ちにな
りたい人は見に行かない方がよいかと。

あー、もう!心のそこから泣かせるか笑わせてくれる物が見たいぞ!
非常に欲求不満なのです。映画でも演劇でも本でも何でもいいから虜
にされる物求む。っていうかもう自分で作るしかないのか?(^-^;


そんなわけで、今週もそろそろいってみましょう。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  01.Review  「前回のおさらい」
──────────────────────────────────────

前回は、色々なサンプルをご紹介しました。


    /*
     * 消費税を考える
     */
    #include<stdio.h>

    int main(void)
    {
        int   price = 200000;
        float rate1 = 0.03;
        float rate2 = 0.05;

        printf("%d\n", price);
        printf("%10.2f\n", price * rate1);
        printf("%10.2f\n", price * rate2);
        printf("%10.2f\n", price + (price * rate1));
        printf("%10.2f\n", price + (price * rate2));
        printf("%10.2f\n", (price * rate2) - (price * rate1));

        return(0);
    }


今回は、その中でも皆さん気になっていると思われる“printf”を
取り上げたいと思います。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  02.Guide  「printf関数:これまでの復習」
──────────────────────────────────────

printfとは、これまでのサンプルからお分かりの通り“表示”を行う物です。
一番シンプルな例は

    printf("Hello!");

といったように、ダブルコーテーションで囲まれた文字列を表示するという
物です。これはみなさん分かりますよね。
 ※ダブルコーテーションで囲まれたものは“文字列”として扱われます。
    http://ichikoro.com/webp/back_list/index.cgi?cd=00015


次に出てきたのは変数を表示できるという物でした。

    #include<stdio.h>

    int main(void)
    {
        int a = 100;

        printf("a = %d\n", a);

        return(0);
    }

もう何度もサンプルが出てきているので、みなさんピン!と来ていると思いますが、
この %d の部分が変数の値と置き換わるのです。

    「ちょっと待って、これまでに%d以外にもいくつか出てきているよね?」

するどい!
例えば、第1項の中にもありますが、

    #include<stdio.h>

    int main(void)
    {
        float rate = 0.03;

        printf("%10.2f\n", rate);

        return(0);
    }


といった具合に、今度は %10.2f の部分が変数と置き換わっていました。



ずばり答えを言ってしまうと、

 printf("ここに表示する際の書式を記述", 書式で使用する変数もしくは値1,
                                         書式で使用する変数もしくは値2,
                                         書式で使用する変数もしくは値3,
                                         書式で使用する変数もしくは値n);

といったように指定するのです。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  03.Guide  「printf関数:出力書式」
──────────────────────────────────────

では、この書式についてご説明しましょう。
基本的に自由に文字を記入することができます。

    例:
        "こんにちは"
        "ご一緒にポテトはいかがですか?"
        "君がため惜しからざりしいのちさへ 長くもがなと思ひけるかな(藤原義孝)"
        "↑なんて事を、しれっと言ってみたい物ですな"

などといった具合です。


ただ、半角の '%' で始まるものについては、前述した通り特別な意味を持ちます。
結論から言うと

    “変数や演算結果など、指定する何かしらの値と置き換える”

といった物ですが、様々なオプションや値の変換などが可能です。
具体的に言うと、下にあるような書き方ができます。
    ※ % と 変換指示子 以外は省略が可能です。
    ※ よく使うものしか書いていません。


    % [フラグ] [最小フィールド幅] [精度] [変換就職子] 変換指示子


        [フラグ] 
            -     マイナスを指定すると左詰に出来ます
                  指定しない場合は右詰になります

            +     値が正の値の場合、数値の前に + が付加されます。
                  逆に不の値の場合、数値の前に - が付加されます。

            0     ゼロ字詰め(ゼロパディング)されます。

            #     例えば16進数の場合、先頭に 0x(0X) が付加されるなど、
                  どんな値かわかるようになります。

        [最小フィールド幅]
            10進数値    ここで指定された数よりも値が少ない場合は、フィールド幅
                        を満たすまで、空白スペースで埋められます。
                            ※フラグに0が指定されている場合、0で埋められます。

        [精度]
            .10進数値   例えば、“.3”というような指定になります。
                        よく使われるのは、小数点以降の桁数の指定です。

        [変換就職子]
            h、l、L     ※説明割愛。そのうちします。

        [変換指示子]
            d        10進数の整数
            o        8進数
            x        16進数(小文字)
            X        16進数(大文字)
            f        浮動小数点
            e,E      指数
            c        文字
            s        文字列
            p        ポインタ(アドレス)
            %        %を文字列中に書きたい場合、“%%”とします


全部を覚える必要はありません。
主要なものだけ抑えておきましょう。

    「とは言っても、これだけじゃ全然ピンとこないぞ(ーー;)」

むー、確かに。
では使用例を次の項で解説しましょう!


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  04.Guide  「printf関数:使用例」
──────────────────────────────────────

まずはこのプログラムを実行してください。そして、実行結果を見ながらそれぞれが
どういう意味をもっているか考えてみてください。

    #include<stdio.h>

    int main(void)
    {
        int    i_int    = 15;        /* intで扱うのは整数 */
        double b_double = 9.876;    /* doubleで扱うのは浮動小数点 */
        char   c_char   = 'i';        /* charで扱うのは文字 */

        printf(" 1:%d    \n", i_int);
        printf(" 2:%5d   \n", i_int);
        printf(" 3:%05d  \n", i_int);
        printf(" 4:%-5d  \n", i_int);
        printf(" 5:%+5d  \n", i_int);
        printf(" 6:%+5d  \n", i_int*-1);
        printf("\n");

        printf(" 7:%o    \n", i_int);
        printf(" 8:%x    \n", i_int);
        printf(" 9:%X    \n", i_int);
        printf("10:%#o   \n", i_int);
        printf("11:%#x   \n", i_int);
        printf("12:%#X   \n", i_int);
        printf("\n");

        printf("13:%f     \n", b_double);
        printf("14:%1.3f  \n", b_double);
        printf("15:%5.10f \n", b_double);
        printf("\n");

        printf("16:%c     \n", c_char);
        printf("17:%s     \n", "abcdefg");
        printf("\n");

        printf("18:%%     \n");
        printf("\n");

        return(0);
    }


実用的な例だと、こんな使い方がよくされます。

    /*
     *   YYYY/MM/DD hh:mm:ss 形式に変換する
     */
    #include<stdio.h>

    int main(void)
    {
        int yyyy = 2002;    /* 西暦年 */
        int mm   = 3;       /* 月 */
        int dd   = 15;      /* 日 */
        int hou  = 1;       /* 時間 */
        int min  = 2;       /* 分 */
        int sec  = 3;       /* 秒 */

        /* 表示 */
        printf("%4d/%02d/%02d %02d:%02d:%02d \n", yyyy, mm, dd, hou, min, sec);


        return(0);
    }


読んでいればそのうち分かるようになると思いますが、
実際に使う場合はこんな感じです。


    /*
     *   現在時間(ローカル)を表示する
     */
    #include<stdio.h>
    #include<time.h>
    
    int main(void)
    {
        time_t ct;
        struct tm *now;
        int yyyy, mm, dd, hou, min, sec;

        /*-------------------------------------*/
        /*             現在時間取得            */
        /*-------------------------------------*/
        ct  = time(NULL);            /* 暦時間 */
        now = localtime(&ct);        /* ローカル時間 */

        /*-------------------------------------*/
        /*            変数に格納する           */
        /*-------------------------------------*/
        yyyy = now->tm_year + 1900;
        mm   = now->tm_mon  + 1;
        dd   = now->tm_mday;
        hou  = now->tm_hour;
        min  = now->tm_min;
        sec  = now->tm_sec;

        /*-------------------------------------*/
        /*              表  示                 */
        /*-------------------------------------*/
        printf("%4d/%02d/%02d %02d:%02d:%02d \n", yyyy, mm, dd, hou, min, sec);

        return(0);
    }


実行するたびに結果が変わりますよね (^-^)/


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  05.Guide  「関数ってなに?」
──────────────────────────────────────

printfについてはバッチシでしょうか?最初のうちはよく使う関数ですので、ここで
しっかりと抑えておいてください。特にCGIで使う場合、printfは“必須”だったり
します。慣れれば簡単...というか、とっても便利ですよー (^-^)/


さて、これまで“関数”という言葉を使ってきましたが、この関数とは一体どんな
意味なのでしょうか?よく、数学の関数のイメージがつきまとって最初は気持ち悪
いというようなことを聞きます。私みたいに学校の数学をあまり熱心に聞いていな
かった人にはあまり違和感がないと思いますが(^-^;


実際に国語辞典を引いてみると、

>  かんすう くわん— 【関数】 ・ かん— 【函数】  
>
>    〔数〕〔function〕二つの変数 x・y の間に、ある対応関係があって、x の値が
>     定まるとそれに対応して y の値が従属的に定まる時の対応関係。また、y の x
>     に対する称。この時 x は単に変数または独立変数と呼ばれる。y が x の関数で
>     あることを y=f(x)などと表す。ふつう関数といえば、x の値に対して y の
>     値が一つ定まるもの、すなわち一価関数をさす。従属変数。

                                                           出典:大辞林第二版
                   Copyright:(C) Sanseido Co., Ltd. 2002. All Rights Reserved

とあります。
じっくり読まないとよくわからないのですが(^^;

    y = f(x)

とあった場合、

    「関数fの結果がそのままyの値になる関係」

とでも言い換えれるでしょうか。
 ※違ってたら教えてください(^^;


もともとこの“関数”という言葉は、英語(米語か?)の function を日本人が訳した
物のハズです。そこで、今度は function の意味も英和辞典で調べてみましょう。

>  func・tion
>      n. 機能, 働き;
>     【文法】 機能; 任務; 職務; 儀式;  会合, 催し;
>     【数】 関数. 
>        − vi. 作用[機能]する (as). 
>
>     function call
>       【コンピユータ】 ファンクション・コール, 関数呼び出し.
>     function code
>       【コンピユータ】 命令コード.
>     function key
>       【コンピユータ】 ファンクションキー.
>     function library   
>       【コンピユータ】 関数ライブラリ.
>     function procedure   
>       【コンピユータ】 関数手続き.
>     function subprogram   
>       【コンピユータ】 関数副プログラム.

                                                         出典:EXCEED英和辞典
                   Copyright:(C) Sanseido Co., Ltd. 2002. All Rights Reserved


色々とご意見などあると思いますが、以上の引用を参考に考えると、関数とは
下のような意味があると考えられると思います。

    ・関数(function)
        - 関数とは、何らかの“機能(部品)”のことである
        - 関数には、何かしらの値が与えられる
        - 関数は、与えられた値に対して(を元に)、何らかの加工(処理など)を行う
        - 関数は、何かしらの値(結果)を返却する
            ※返却する値がそのまま “関数の値” となる


では、これをprintf関数に置き換えて考えてみましょう。

    ・printf関数
        - printfとは、指定の書式に従い表示を行う“機能(部品)”である
        - printfには、任意の書式(文字列)と、書式で必要な値が与えられる
        - printfは、与えられた値を元に、表示の処理を行う
        - printfは、成功した場合は表示したバイト数を、
                    失敗した場合は負数を返却する。

と言い換えれます。
実際のコードで確認してみましょう。

    #include<stdio.h>

    int main(void)
    {
        int a = 100;

        printf("a = %d", a);

        return(0);
    }


    ・printf関数
        - printfとは、指定の書式に従い表示を行う“機能”である

            上のプログラムを実行すると、a = 100 と表示されます。


        - printfには、任意の書式(文字列)と、書式で必要な値が与えられる

            ここでいう書式とは "a = %d" となります。
            書式で必要な値とはもちろん、変数aのことです。


        - printfは、与えられた値を元に、表示の処理を行う

            上記の書式にしたがって、表示を行います。


        - printfは、成功した場合は表示したバイト数を、
                    失敗した場合は負数を返却する。

            おっと!これはまだ説明していませんでしたね。
            さっそく確認するコードを書いて見ましょう。

                #include<stdio.h>

                int main(void)
                {
                    int  a = 100;
                    long result;

                    /* 普通に表示 */
                    result = printf("a = %d\n", a);        /* printfの実行結果を変数に代入 */

                    /* さっきの実行結果を表示 */
                    printf("result = %d\n", result);

                    return(0);
                }


ここまでで、printfは見事な関数であると証明できたと思います(笑)
そうそう、上記コードで

    /* 普通に表示 */
    result = printf("a = %d\n", a);        /* printfの実行結果を変数に代入 */

この部分、勘のスルドイ方は気がつかれたと思いますが、

    y = f(x)

と、ほぼ一緒ですよね(^-^)


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  06.Guide  「C言語は関数の集合体」
──────────────────────────────────────

C言語はこれら機能(function)の集合体です。
この関数には、大きく2種類に分けることができます。

    ・標準ライブラリ関数
        あらかじめ用意されている関数。
        printfのような物をはじめ、文字列を検索、比較する物があれば、
        ファイルの読み書き、メモリの制御をする関数もあります。
    
    ・ユーザー関数
        あなた自身の手で、関数(機能)を作ることができます。
        もちろんそれを呼び出して使用することも可能です。


当面は標準ライブラリ関数をメインに紹介していきますが、そのうちユーザー関数
の作り方についてもご紹介します。



そうそう、みなさんがプログラムを記述している部分はmain関数と呼ばれています。
というのは最初のころお話しましたよね?

    int main(void)
    {


    }

この関数だけはちょっと特殊で、こいつの役目は、様々な機能(function)を呼び出
し、それを統括することです。色々な関数がファイルの中にあったとしても、コン
パイラはまず、main関数を見つけにいき、main関数にそって実行を行います。逆に
このmain関数がなければ、プログラムは動作しません。というかコンパイル(リン
ク)を通りません(^^;

    C:\>bcc32 test.c
    Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    test.c:
    ↑文法的には正しいため、コンパイルは通ります。

    Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
    Error: 外部シンボル '_main' が未解決(C:\BORLAND\BCC55\LIB\C0X32.OBJ が参照)
    ↑リンク時にmain関数がないため、実行可能ファイルを作成できなかったのです。


だからみなさんはmain関数の中にプログラムを書いているのです。


こういう話が出てくるたびに、色々なところで取り合げられるのが、「世界最小のプロ
グラム」です。コンパイル(リンク)を無事通過し、問題なく実行できる必要最小限の
構成はこんな感じです。

    main(){}

なんと一行、8バイトなんですね。
実際に実行してみましょう。

    C:\>bcc32 test.c
    Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    test.c:
    警告 W8070 test.c 1: 関数は値を返すべき(関数 main )
    Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

    C:\>test

何も処理を記述していないので、もちろん実行したって何も起こりません。
コンパイル中に警告が出ましたが、実行するのに問題は何らありません。
余談でした(^^;


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  07.Question  「今週の問題」
──────────────────────────────────────

    Q. 一回目のprintfから返却される値が、1234(byte) になるように下記のプログ
       ラムを“一箇所”修正しなさい。
           ※必ず一箇所だけの修正に留めること。

            #include<stdio.h>

            int main(void)
            {
                int  a = 100;
                long result;

                /* 普通に表示 */
                result = printf("a = %d\n", a);        /* printfの実行結果を変数に代入 */

                /* さっきの実行結果を表示 */
                printf("result = %d\n", result);

                return(0);
            }


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                           編    集    後    記
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

うーん、今回はかなりこゆかったですねぇ。もちろん目的は“関数”について知って
もらいたかったという所です。実際に自分で関数作るようになればピン!と来るよう
になります。また、今後説明していく様々な関数を使っていくうちに、次第にこうい
うもんなんだと、感じるようになると思います。

キチンと考えながら読んでくださいね(^-^)/
見ているだけでは身につきませんよ〜。


冒頭でロード・オブ・ザ・リングの話をしましたが、
ヨーロッパといえば、「ハリー・ポッターを探しにイギリスへ」という本を今週は
読んでました。原作を三冊ともあっと言う間に読んじゃいまして、手持ち無沙汰な
ところに出会ったのがこの一冊。「ハリー・ポッターの料理・お菓子Cooking Book」
とどっちにしようか結構悩んだんですが(笑)

で、この本、観光本というよりはむしろトラブル日記なのでした。
そこら辺に出回っているハリポタ関連本とは違い、ほのぼのとした雰囲気で笑わ
せてくれる作者のトラブル体験談や、リー君(現地のガイド役)のやさしさにホロ
ッと来たり、なんと行っても最後に訪れる“奇跡”。とってもさわやかな気持ち
になれます。思わず「イギリスに旅に行きたいなぁ」という気になっちゃいまし
た(^-^)

 ・ハリー・ポッターを探しにイギリスへ
    http://www.amazon.co.jp/exec/obidos/ASIN/4102901310/stagefan-22
   ※映画見てから読みませう。

  ・ハリー・ポッターの料理・お菓子Cooking Book
    http://www.amazon.co.jp/exec/obidos/ASIN/4876938059/stagefan-22
    ※立ち読みしてたんですが、イギリスの家庭料理とか載ってるんですよね。
     向こうの人が普段何を食べているのか興味あるじゃないですかぁ。
     原作に事あるごとに出てくるカボチャジュースも興味津々です。
     バタービールも飲んでみたいぞ〜。


そしてこの原稿を書いている最中にDVDを思わず予約。それも金のスニッチバー
ジョンという豪華版!マトリックスのコレクターズボックスに引き続きやってし
まいました。しかしこの内容で通常版の3倍は高いぞ。でも買うけどね、あは(^^;

 ・ハリー・ポッターと賢者の石 DVDスペシャルBOX 金のスニッチバージョン
    http://www.amazon.co.jp/exec/obidos/ASIN/B00005TO3B/stagefan-22


ではでは、次回は9月1日午前11:00、ロンドンのキングズクロス駅 9と4分の3...
じゃない、月曜日にお会いしましょう (^-^)/~~
 ※え、しつこいって?(^^;


■Information 
 「Webプログラミングからのお知らせ」

    【相互広告募集のお知らせ】
      読者数を増やしたいメルマガ発行者さんを募集しています。お互いに一定期間(1〜
      3回程度)広告を掲載し合いませんか?詳細はご相談ください(無料)

         お問い合わせ: mm-webp@ichikoro.com

    【コラム募集のお知らせ】
      Webプログラミングでは、寄稿していただけるコラムやプログラムなどを募集して
      います。たくさんの読者の方にあなたをアピールする場にもなります。ぜひ有意義
      な情報やご意見をお送りください。

         お問い合わせ: mm-webp@ichikoro.com


■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

                   【 Webプログラミング Code Sample 】

                    発  行 : ichikoro.com
                発行責任者 : 勝部 麻季人
                              < mailto:katsube@ichikoro.com >
                  発行部数 : 1787部(前回)
                 Webサイト : < http://www.ichikoro.com/webp/ >
            お問い合わせ先 : < mailto:mm-webp@ichikoro.com >

                            Powerd by まぐまぐ
    All Right Reserved, CopyRight(C) 2001 Webプログラミング Code Sample
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

コメント

コメントを入力. Wiki文法が有効です:
Y D Z I L