K&Rを読もう(12) 演習 1-19 文字列の逆順表示

今回はcopy関数の応用です。結構めんどい。

演習 1-19

文字列sを逆に並べよ。


ま、コピーの逆をすればいいな。と甘く考えていたけど、よく考えたら、C言語の文字列は、

012345\n\0

となるので、文字列の逆は、

543210\n\0

となる。

つまり、「改行をコピーしてはならない」という制限が付く。


その点を踏まえてコーディング。

#include <stdio.h>
#include <stdlib.h>

#define MAXLINE 1024

void reverse(char to[], char from[], int len);
void copy(char to[], char from[]);
int  getline(char s[], int limit);

int main(void)
{
    int  len;
    int  max = 0;
    char line[MAXLINE];
    char enil[MAXLINE];
    int c;

    while ((len = getline(line, MAXLINE)) > 0) {
        if (len == MAXLINE - 1 && line[len - 1] != '\n') {
            while((c = getchar()) != EOF) {
                len++;
                if (c == '\n')
                    break;
            }
        }
        reverse(enil, line, len);
        printf("%2d : %s", len,enil);
        if (len >= MAXLINE)
            printf("...\n");
    }

    exit(EXIT_SUCCESS);
}

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

    if (len > 0 && from[len - 1] == '\n') { /* 改行のチェック */
        for (i = 0; i < len - 1; i++)
            to[len - 2 - i] = from[i];
        to[len - 1] = '\n';
        to[len] = '\0';
    } else {
        copy(to, from); /* 改行が無い場合はコピーだけ */
    }
}
void copy(char to[], char from[])
{
    int i;
    for (i = 0;(to[i] = from[i]) != '\0'; i++)
        ;
}
  • getlineは略。
  • copyより1個引数を多くしてみた。strlen(3)でもいいと思う。
  • シェルスクリプトのesacの真似て変数名はenilとした。lineの逆順。
  • オーバーフローしたらコピーだけ。

実行結果

% ./ex-1-19 < ex-1-19.c | head
19 : >h.oidts< edulcni#
20 : >h.bildts< edulcni#
 1 :
21 : 4201 ENILXAM enifed#
 1 :
47 : ;)nel tni ,][morf rahc ,][ot rahc(esrever diov
35 : ;)][morf rahc ,][ot rahc(ypoc diov
35 : ;)timil tni ,][s rahc(enilteg  tni
 1 :
15 : )diov(niam tni

か、解読不能です。