K&R演習[1-19]

課題

文字列Sを逆に並べる関数reverse(s)を書け。さらに、この関数を使って、入力を一時に1行ずつ逆転するプログラムを書け。

回答

#include <stdio.h>
#include <limits.h>
#include <string.h>

#define MAX_LINE_NUM    1000        /* 入力行数の最大値 */
#define MAX_LENGTH      1000        /* 入力文字列長の最大値 */
const int MIN_COPY_LENGTH = 80;     /* コピーする最低文字列長 */

const char TRUE = 1;
const char FALSE = 0;

typedef unsigned long long u8;

int getline(char line[], u8 maxline);
void copy(char to[], char from[]);
void reverse(char to[], char from[]);           /* 行を逆順にコピーする */



/**
 * @fn      Main
 * @brief
 * @param
 * @return
 * @detail
 */
int main(void)
{
    u8 i, len, num_line = 0;        // 行数
    char line1[MAX_LENGTH];                 // 保存元(読み取った文字列)
    char line2[MAX_LINE_NUM][MAX_LENGTH];   // 保存先
    char flg = TRUE;

    while ((len = getline(line1, MAX_LENGTH)) > 0) {

        if (flg == TRUE) {
            copy(line2[num_line], line1);           // 通常コピー
            flg = FALSE;
        } else {
            reverse(line2[num_line], line1);        // 逆順コピー
            flg = TRUE;
        }
        num_line++;                                 // 有効な行なら次の行へ

        if (num_line >= MAX_LINE_NUM) {     // 保存先の行数を使い切ったら終了
            break;
        }
    }

    printf("\n --- result --- \n");         // タイトル
    for (i = 0; i < num_line; i++) {        // 保存した行数だけ
        printf("%s", line2[i]);             // 保存先から取り出して印字
    }
    return 0;
}

/* getline: sに行を入れる */
int getline(char s[], u8 lim)
{
    int c;
    u8 i;
    char flg = FALSE;

    for (i = 0; (i < lim - 1) && ((c = getchar()) != EOF) && (c != '\n'); ++i) {
        if (c == '.') {     // コロンを発見したら
            flg = TRUE;     // 発見フラグをONする
        }
        if ((flg == FALSE) ||   // コロン発見前または
            (c != ' ') ||   // スペースではない、または
            (c != '\t')) {  // タブでもなければ
            s[i] = c;       // コピーする
        }
    }

    if (c == '\n') {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i;
}

/* 行を逆順にコピーする */
void reverse(char to[], char from[])
{
    u8 i = 0, len = strlen(from) - 1;   // 改行の直前まで
    
    while (1) {
        to[i] = from[len - i - 1];
        if (i == (len - 1)) {
            to[i + 1] = '\n';
            to[i + 1] = '\0';
            break;
        }
        i++;
    }
}

/* 行コピーする */
void copy(char to[], char from[])
{
    int i = 0;
    while ((to[i] = from[i]) != '\0') {
        ++i;
    }
}

実行内容

This is a pen.
This is not a pen.

実行結果

--- result ---
This is a pen.
.nep a ton si sihT