プログラミング言語 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 という実行ファイルを作成してみる。
まず ヘッダーファイル、

  1. /* file : header1.h */
  2. #define MAX_LINE 1000
  3. int get_line(char line[], int max);
  4. int str_index(char source, char search_for);
  5. extern char pattern[] = "char";
  6. /* ↑ target の文字列を "char" にしてみた */


次に 関数 get_line() と str_index()、

  1. /* file : part1.c */
  2. #include
  3. /*
  4. * 今回は while文を使って
  5. */
  6. int_get_line(char str[], int lim)
  7. {
  8. int c, i;
  9. i = 0;
  10. while (--lim > 0 && (c = getchar()) != EOF && c != '\n') {
  11. str[i++] = c;
  12. }
  13. if (c == '\n') {
  14. str[i++] = c;
  15. }
  16. str[i] = '\0';
  17. return i;
  18. }
  1. /* file : part2.c */
  2. #include
  3. /*
  4. * 各ラインで パターンとマッチしたら
  5. * そのインデックスを返す
  6. * 見つからないときは -1 を返す
  7. */
  8. int str_index(char str, char target)
  9. {
  10. int i, k, j;
  11. for (i = 0; str[i] != '\0'; i++) {
  12. for (j = i, k = 0; target[k] != '\0' && str[j] == target[k]; j++, k++) {
  13. ;
  14. }
  15. */ ↑ パターンにマッチしないラインは飛ばす */
  16. if (k > 0 && target[k] == '\0') {
  17. return i;
  18. }
  19. }
  20. return -1;
  21. }


最後は 関数 main()、

  1. /* file : part3.c */
  2. #include
  3. #include "header1.h"
  4. /*
  5. * 順次 各ラインを照合していって
  6. * 関数 str_index() の返り値が -1 でなければ
  7. * そのパターンにマッチしたラインをプリントする
  8. */
  9. main()
  10. {
  11. char line[MAX_LINE];
  12. extern char pattern[];
  13. int found;
  14. found = 0;
  15. while (get_line(line, MAX_LINE) > 0) {
  16. if (str_index(line, pattern) >= 0) {
  17. printf("%s", line);
  18. found++;
  19. }
  20. }
  21. return found;
  22. }


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:←ちょっと改造するけど