プログラミング言語 C
・ 特定の文字列(パターン)を含む行(ライン)を捜し出してプリントするプログラムを組み立ててみよう。
・ このプログラムの基本的な構造は 次の3つの部分に分けることができる。
1. while (ラインが存在している)
2. if (パターンを含んでいる)
3. (プリントする)・ これらすべてを 関数 main() の中で記述することもできるが、各々の部分を それぞれ別の関数にすることによって うまく(プログラムを)組み立てるのが よりよい方法である。
・ 関数をじょうずに使えば、他の部分に関係しない操作の評価を隠すことができるし、また 全体を明確化して プログラムの変更を 容易に行うことができる。
・ それに こうして工夫した関数は それ自体、他のプログラムへ転用することも可能である。
・ (ラインが存在している)には 以前 使った関数 get_line() が使用できる。*1 また(プリントする)では 関数 printf() が すでに用意されている。
・ したがって 残っているのは、そのラインが ある特定のパターンを含んでいるかどうかを捜し出すルーティンをつくることである。
・ それは 文字列 str の中で 文字列 target の始まる位置、つまり インデックスを返し、str が target を含まないときには -1 を返す 関数 str_index() を用意することによって解決できる。
・ C の配列は 0 から始まるので このインデックスは 0 または 正の整数である。 したがって -1 のような負の(返り)値は (target が)見つからなかったことを表すのに適している。
・ また 後で複雑なパターン照合が必要になったときには、この関数 str_index() だけを書き換えれば よいことになる。(p82-84)
それぞれの関数を 別々にコンパイルして、後で pattern という実行ファイルを作成してみる。
まず ヘッダーファイル、
- /* file : header1.h */
- #define MAX_LINE 1000
- int get_line(char line[], int max);
- int str_index(char source, char search_for);
- extern char pattern[] = "char";
- /* ↑ target の文字列を "char" にしてみた */
次に 関数 get_line() と str_index()、
- /* file : part1.c */
- #include
- /*
- * 今回は while文を使って
- */
- int_get_line(char str[], int lim)
- {
- int c, i;
- i = 0;
- while (--lim > 0 && (c = getchar()) != EOF && c != '\n') {
- str[i++] = c;
- }
- if (c == '\n') {
- str[i++] = c;
- }
- str[i] = '\0';
- return i;
- }
- /* file : part2.c */
- #include
- /*
- * 各ラインで パターンとマッチしたら
- * そのインデックスを返す
- * 見つからないときは -1 を返す
- */
- int str_index(char str, char target)
- {
- int i, k, j;
- for (i = 0; str[i] != '\0'; i++) {
- for (j = i, k = 0; target[k] != '\0' && str[j] == target[k]; j++, k++) {
- ;
- }
- */ ↑ パターンにマッチしないラインは飛ばす */
- if (k > 0 && target[k] == '\0') {
- return i;
- }
- }
- return -1;
- }
最後は 関数 main()、
- /* file : part3.c */
- #include
- #include "header1.h"
- /*
- * 順次 各ラインを照合していって
- * 関数 str_index() の返り値が -1 でなければ
- * そのパターンにマッチしたラインをプリントする
- */
- main()
- {
- char line[MAX_LINE];
- extern char pattern[];
- int found;
- found = 0;
- while (get_line(line, MAX_LINE) > 0) {
- if (str_index(line, pattern) >= 0) {
- printf("%s", line);
- found++;
- }
- }
- return found;
- }
3つのファイルを それぞれコンパイルして、次に 実行ファイル pattern を作成。
$cc -c part1.c
$cc -c part2.c
$cc -c part3.c
$ls
header1.h part1.o part2.o part3.o . . .
$cc -o pattern part1.o part2.o part3.o
$./pattern < part1.c として確認。
(注意)
$cc -c part3.c のとき、警告(warning)の表示がでても オブジェクトファイルは作成されますので . . .
*1:←ちょっと改造するけど