97日目 K&R 1.9 文字配列 をふたたび

日本語版p.37、getline()のサンプルプログラムが奇妙に思えてずっと手を出しかねてた。
その違和感を少しだけ解消できたのでメモっとく。


どういうことかっていうと、

for(初期化式;条件式;式1実行後に行う事)
    式1;

これがわかってなかった。
あとs[i]=c; ++i;が二回出てくるのもきもちわるかった。

いきなりcopyとか二つ以上の関数を扱うと思考がついていけないので、行あたりの改行を含めた文字数を表示するプログラムを書いた。それがこれ。

#include <stdio.h>
#define MAXLINE 1000

int getline(char line[], int maxline);

main()
{
    int len;
    char line[MAXLINE];

    while((len = getline(line, MAXLINE)) >0)
        printf("%d\n", len);        // 各行の文字数を表示
}

int getline(char s[], int lim)
{
    int c, i;

    i = 0; // 1000文字目(i==999)か\nかEOFが来る手前まで
    while (i<lim-1 && (c=getchar())!='\n' && c!=EOF) {
        s[i] = c;
        ++i;        // for文の第三引数i+1がs[i]=cの後に評価されることを明示
    }
    if (c == '\n') {    // 改行は改行で新たに格納 (全部読み込んでから区切りたいが…)
        s[i] = c;
        ++i;            // ちなみに一つ上の行でs[i++] = c;とやればこの行はいらない
    }
    s[i] = '\0';

    return i;
}

そんで最終的にはサンプルプログラムはこうなった。好みの問題でしょうが。
でもまだ変えたいところはあって、上のソースのコメントにも書いたように全部読み込んでから改行で区切る方式にしたい。

#include <stdio.h>
#define MAXLINE 1000

int getline(char line[], int maxline);
void copy(char to[], char from[]);

main()
{
    int len;
    int max;

    char line[MAXLINE];
    char longest[MAXLINE];

    max = 0;
    while ((len = getline(line, MAXLINE)) >0)  //getline()で文字数をカウントする
        if (len > max) {
            max = len;
            copy(longest, line);    //copy()でlineをlongestに格納する
        }
    if (max > 0)
        printf("%s", longest);
        printf("%d", max);
    return 0;
}

int getline(char s[], int lim)
{
    int c, i;

    i = 0;
    while (i<lim-1 && (c=getchar())!=EOF && c!='\n')
        s[i++] = c;
    if (c == '\n')
        s[i++] = c;
    s[i] = '\0';

    return i;
}

void copy(char to[], char from[])
{
    int i;

    i = 0;
    while((to[i] = from[i]) != '\0')
        ++i;
}