K&Rを読もう(25) atoiとlowerの写経。

K&Rを写経しよう。

今回はatoiとlower。文字列演算が出てきたので、rot13(シーザー暗号)も追加してみた。

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

int atoi_copy(char *s)
{
    int i, n = 0;
    for (i = 0; isdigit(*(s + i)); i++)
        n = 10 * n + (*(s + i) - '0');
    return n;
}

int lower(int c)
{
    if ('A' <= c && c <= 'Z')
        c = c + 'a' - 'A';
    return c;
}

int rot13(int c)
{
    const int rot = 13;
    
    if ('a' <= c && c <= 'z')
        c = (c - 'a' + rot) % ('z' - 'a' + 1) + 'a';
    else if ('A' <= c && c <= 'Z')
        c = (c - 'A' + rot) % ('z' - 'a' + 1) + 'A';
    return c;
}

int main(void)
{
    char *s = "LOWER TEST";
    char *r = "ROT13 TEST -- abc xyz";
    char *p = r;
    printf("%d\n", atoi_copy("1234だけ抽出。")); /* 1234 */
    
    for (;*s != '\0'; s++) {
        putchar(lower((int) *s)); /* lower test */
    }

    puts("");

    /* ROT13 */
    for (;*p != '\0'; p++) {
        putchar(rot13((int) *p));        /* EBG13 GRFG -- nop klm */
    }
    puts("");
    for (p = r ;*p != '\0'; p++) {
        putchar(rot13(rot13((int) *p))); /* ROT13 TEST -- abc xyz */
    }
    puts("");
    
    exit(EXIT_SUCCESS);
}

atoi

  • ポインタとisdigitを使ってみた。
  • 上の桁から見ていくので、n * 10になる。なるほど。

lower

  • ホントの名前はtolowerらしい。引数はintなので注意。

rot13

  • ROT13 - Wikipedia
  • Vimのおまけ機能g?が作りたくなってしまった。
  • ('z' - 'a' + 1)は26です。
  • aを0とした文字コードを作って、13を足します。それを26の余りを取る。'a'を足して元に戻せば、半分ひっくり返ったシーザー暗号が出来ます。
  • rot13(rot13())すると元に戻ります。
  • 暗号としてはとってもチープですが、暗号入門には最適かも。
  • todo:rot47を作る。