K&Rを読もう(9) 1.9 文字配列
C言語で凶悪なのが、文字配列。というか、文字列自体あんまり得意じゃない。今回は、配列で行の取得。スクリプト言語に慣れてると固定長配列は凄くキツイ。
テキストファイルについての考察。
行はは文字の連続と改行で表されて、
ファイルは行の連続と、EOFで構成されている。
と、再帰的なんだけど納得がいかない。
K&Rの1.9をちょっとわかりやすくしてみた。一番長い行を表示する。
#include <stdio.h> #include <stdlib.h> #define MAX_LENGTH 1024 int getline(char s[], int limit); void copy(char to[], char from[]); int main(void) { int len; int max = 0; char line[MAX_LENGTH]; char longest[MAX_LENGTH]; while ((len = getline(line, MAX_LENGTH)) > 0) { if (len > max) { max = len; copy(longest, line); } } if (max > 0) printf("%s", longest); exit(EXIT_SUCCESS); } int getline(char s[], int limit) { int i, c; for (i = 0; i < limit - 1; ++i) { c = getchar(); if (c == EOF) break; s[i] = c; if (c == '\n') { ++i; // pushしたのに足されてない。 break; } } s[i] = '\0'; return i; } void copy(char to[], char from[]) { int i; for (i = 0;(to[i] = from[i]) != '\0'; i++) ; }
getlineをもっとシンプルに出来ないのかなぁ・・・と悩んだが、あまり良い案が思い当たらず。
あっ
ちょっと眺めてたら気づいた。
EOFの位置だ。改行の前にEOFがある場合があるので、うまく再帰で表せない。
行はは文字の連続と改行で表されて、
ファイルは行の連続と、EOFで構成されている。
という僕の考察では、全然足りない。どこにEOFが発生してもおかしくない。
つまり、EOFを最初に見る必要があるので、改行の処理が面倒になる。
EOFを先に見るなんて当たり前の事だと思ってたけど、かなり面倒な処理が必要なんだと気づいた。文字列の難しさの一端がわかった気がする。
ファイルの最後には改行を入れようと思った。
修正
おぉ、コレダ。
int getline(char s[], int limit) { int c; int i = 0; for (;;) { c = getchar(); if (c == EOF) break; if (i < limit - 1) s[i++] = c; // push else break; if (c == '\n') break; } s[i] = '\0'; return i; }
インクリメントの位置を直してスッキリした。
ファイルは文字の連続とEOFで表される。
行は文字長に制限がある。
行は文字の連続と改行で表される。
と、解釈を変えた。
これなら改行にCRLFが来ても柔軟に対応出来る。
修正2
もうちょっと修正。
int getline(char s[], int limit) { int c; int i = 0; while ((c = getchar()) != EOF) { if (i < limit - 1) /* push */ s[i++] = c; else break; if (c == '\n') break; } s[i] = '\0'; return i; }
今までと変わらないじゃん!!