まえがき

このページはCを中心にPerl/CASL2/UNIXシェルについても書いています。

Javaで入れ子になったオブジェクトやコレクションのコピーや設定で思いもかけない結果になって苦しむのは誰もが通る道ですが、そんな人にC言語の学習をすすめる人もいます。

C言語はJavaよりアセンブラに似ていてメモリの確保や解放を自力で行わなくては ならず、メモリ上でデータ(特に構造体の配列)がどう初期化、設定、コピー、参照されるのかを把握しなければなりませんが、一次元領域しか扱えないC言語はメモリ内を賢く細切れに使うJavaよりもシンプルで分かりやすいので学習の価値があるということだと思います。

C言語は標準関数が少ないのでライブラリ製品を買わなければ共通部品を自力で作る必要があるという意味でJavaより難易度が高く、 プロジェクトでの単金が高いという現象も発生しているそうです。

現在のシステムの画面はJavaやVBがほとんどですが、巨大なデータを作成するバッチは C言語がまだ良く使われています。Oracleの(パーティション分割された)巨大なテーブルからマルチスレッドでハッシュ分割数のCSVファイルを作成し、監視プログラムがハッシュ分割数のファイルが揃ったのを監視して、そろったらプロセスをforkしてマージとソートをして1つのファイルを作るバッチということが典型的です。

それにJavaのVMやPHP,Rubyなどの環境はすべてC言語で書かれているように、OSやミドルウエアはほとんどC言語で書かれていますので、システム管理ツール開発もC言語が必須と言えるでしょう。

ここではC言語の学習に必須と思われるサンプルを列挙しています。

また、アセンブラの練習も必要かと思いCASL道場も追加しました。

作者:城風敏彦 http://www5.plala.or.jp/shirokaze/

業務系Cプログラマの条件

開発環境

基本文法

実践編

C言語入門の教科書というとmain関数1つだけで、変数、演算子、配列、標準関数、構造体、ポインタなどと解説していくことが多いですが、これがいけないと思います。最初から機能を関数化して自分の共通関数(部品)を積みあげ、日々改善していくのが最も実り多いやり方です。

main,標準出力

  • main,最小ソース
    • smallest.c 必要最小のC言語ソース雛形。機能はmain.cと全く同じなので、main.cを見てください。このソースは例外的にコメント(処理に関係のない説明)がないのでここで説明します。intはmain関数が返す型=整数(Integer),mainはコンパイルされた実行モジュールがメモリにロードされて最初に起動される関数の名前、()は関数引数を並べるところ、{}は関数の処理を記述するところの約束です。return 0; で整数0を返していますので、最初のintと辻褄が合っています。
  • main,コメント
    • main.c コメント付き必要最小のC言語ソース雛形。機能はsmallest.cと同じ。
      • 例題:main.cのreturn 0をreturn 1に修正して実行し、その後にシェルでecho $? を確認せよ。mainの返す値を受け取るのはmainを起動したシェル(csh,bash等)プロセスであるので、シェルはmainの返した値を判断して再試行したり、続行、中断などを行える。
  • include,printf
    • hello.c 定数文字列"hello world\n"を出力する。
    • hello_func.c
      • 例題:hello_func.cのprintf中の文字列を変更してコンパイル&実行せよ。"\n"が改行であるように"\t"がタブであるのでタブも使ってみること。
  • DEBUGオプション、標準エラー出力
    • debug.c コンパイラのDEBUGオプションがある時のみメッセージを出力する。
      • 例題:debug.cを-DDEBUGオプションなしでコンパイル&実行し、何も出力されないことを確認せよ。
  • コマンド引数→argc,argv
    • argv.c char2次元ポインタ(文字列の配列)**argvの理解
      • 例題:argv.cにトータルで1024バイト(文字),2048バイト、4096バイトと1024の倍数の引数を与えてみる。どこかで異常終了するので、上限を記憶しておく。
    • print_argv.c argv.cの関数化。引数の他の関数への委譲(丸投げ)の例。
    • arith_int.c 整数の四則演算の計算
      • 例題:arith_int.cの除算を分母が0以下の場合に-1を返し、それ以外で引数に商と余をセットして0を返す関数 int integer_divide(int bunsi, int bunbo, int *syo, int *yo) を作って呼び出すように改造せよ。
    • bmi.c 肥満度(BMI指数)の計算。倍制度浮動少数点実数doubleの利用。
      • 例題:bmi.cで%gでBMI指数を表示しているとことを、%2.2fまたは%eで置き換えてdoubleのprintfでの書式について学習せよ。http://www.mm2d.net/c/c-01.shtml 参照。

変数、コード

文字列

関数

syslog出力

  • 業務アプリでは、ファイル、DB、通信などの関数で異常が発生したら全てsyslog出力しないと障害解析ができません。単体のデバッグメッセージはfprintf(stderr,..)で、最終的に出力するメッセージはsyslogと思っていると良いでしょう。syslogの出力レベルはsyslogdで制御できるのでデバッグメッセージをsyslogで出すこともできます。

時間取得関数

  • 現在時刻、実行速度計測。単体テスト時から実行速度を計測しておいた方が良いです。実装の選択肢がある時は特に。
  • 現在時刻文字列を取得する関数

文字列操作関数

  • 行数、単語数、文字数カウント

領域確保関数

関数内部で領域を拡張する文字列操作関数

ファイルを込みこんで文字列を加工してDBに挿入したり別のファイルを作るバッチ処理は アセンブラに近くて高速化しやすいC言語が最もよく使われる領域です。
文字列操作を駆使できれば業務プログラマの中級まで来たことになります。
しかしC言語では関数の中で引数の文字列の領域を拡張して返すだけでも、注意しないと 思わぬバグに悩むことになります。 malloc,reallocで確保した領域は利用がすんだらfreeで開放することを忘れないでください。

  • 入力文字列を2倍にして返す関数。関数内での領域拡張の試行。
  • 入力文字列を2倍にして戻り値の文字ポインタにセットして返す関数
  • 入力文字列を2倍にして出力文字列にセットして返す関数

csv分解

関数での構造体のポインタ渡し

  • 1次元構造体参照渡しサンプル 。呼び出す側が領域を確保するなら、関数内で構造体のアドレスを変更する必要がないので、構造体の1次元ポインタで渡せます。
  • 2次元構造体参照渡しサンプル。関数内部で領域拡張するなら、構造体の2次元ポインタで渡す必要があります。1次元だとmalloc,reallocでアドレスが変わると参照できなくなってしまいますので。
  • 2次元構造体void参照渡しサンプル。void **とは関数内部で領域拡張し、受け取った方で適切な構造体にキャストすると目印と思ってください。全てを受けて後で個別にキャストするのはJavaのjava.lang.Objectのような使い方です。

ソート(並べ替え)

CGI(Common Gateway Interface:動的ホームページ作成)

  • FORMデータの漢字をデコードする。連想配列構造体を定義して利用。
    • wordcut_cgi.c 1ファイルで全てを含むファイル。他のファイルから利用できない。
    • seimei_cgi.c wordcut_cgi.cと全く同じ動作をするが、 別ファイルassosiative_array.cの関数を利用している。分割コンパイル&リンクの例。
  • 例題:姓名判断CGI seimei_cgi.cseimei.c(沢渡香澄氏作)を合体させて、姓名判断を行うCGIを作成する。
    • seimei.cのmain()のをseimei(char *n1, char *n2)に変更して、seimei_cgi.cのmain()から呼び出す。
    • コンパイルは cc -o seimei_cgi assosiative_array.o seimei.o seimei_cgi.c になる。
    • UNIXでCGI実行させるには、モジュールの名前をseimei_cgi.cgiにして、フォームのactionもそれに合わせる必要あり。
  • BMI指数計算CGI。bmi.cのCGI化。

データベース

番外-UNIX FAQ

番外-bshサンプル

番外-CASL道場

SQL-Translatorインストール?


Link

Counter: 7297, today: 24, yesterday: 0

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-11-15 (火) 10:38:41 (183d)