ASCIIコードで遊ぶ

#TIL(Today I Learned)
特に誰に頼まれたわけでもなく、勝手にインターン先の会社でやった勉強会で少し興味を持ったものごとを記述しています。
今日は文字コードの中でもASCIIコードについて。
文字コードとはWikipedia先生によると。
>文字コード（もじコード）とはコンピュータ上で文字（キャラクタ）を利用する目的で各文字に割り当てられるバイト表現。もしくは、バイト表現と文字の対応関係（文字コード体系）のことを指して「文字コード」と呼ぶことも多い。

らしく、ASCIIとはその中でも最もよく使われているものらしいです。ほとんどローマ字を扱うためのもので、日本語は扱えません。

コード表など詳しくはこちらに乗っています。
http://www3.nit.ac.jp/~tamura/ex2/ascii.html

その中で興味を惹かれたのは、👆のページの下方にある、ASCIIコードを使ったトリックの項目です。なんとなく面白いなと思ったのでASCIIコードで遊んでみたいと思いました。
このページではC言語でASCIIコードを扱っていたので、じゃあ自分もCでやってみようとおもったのが苦労の始まりです。当初は__「大学の授業で4時限やった僕なら余裕っしょ！」__と考えていました、馬鹿ですね。
文字コードが整数で扱われるというのは

```C
#include<stdio.h>

int main(void){
  //文字a
  char a;
  a = 'A';
  //整数型でaを表示
  printf("%d\n", a);
  return 0;
}

```
これを実行したとき

```
65
```
AのASCIIコードの65が出力されるということです。
逆に、以下のようなコードを実行したときは

```C
#include<stdio.h>

int main(void){
  //整数a
  int a;
  a = 65;
  //文字列型でaを表示
  printf("%c\n", a);
  return 0;
}

```


```
A
```

が出力されます。何となく僕にはこれが面白かったことが今回この記事を書いている理由です。


#じゃあなにを作ろう
一文字ずつ入力して変換しても面白くないので、文字を入力したらASCIIコードを返してくるようなプログラムを書きたいと思います。しかしこれはすでにやっていた人を検索の過程で見つけましたのでほとんどコピペです。

```C
#include<stdio.h>

int main(void){

  int i = 0;
  //入力された文字を代入する配列
  //よくわからんが多いほうがいいから俺は1000確保するぜ!
  char moji[1000];
  //scanfで読み取り
  scanf("%s", moji);
  //moji配列の分だけ、入力された文字のASCIIコードをスペース区切りで出力します
  while(moji[i]) {
    printf("%d ", moji[i++]);
    printf(" ");
  }
  printf("\n");

  return 0;
}
```

これを実行すると、

```
HELLO
72  69  76  76  79
```
という感じになります

つづいて、
ASCIIコードではアルファベットの大文字に割り当てられた数字に32足すとそれが小文字になります。なので、連続した文字列を小文字にするプログラムを書いてみましたｌ

```C

#include<stdio.h>

int main(void){
  int i=0;
  char moji[1000];
  //小文字にするために32を足す
  int tl = 32;
  scanf("%s", moji);

  while(moji[i]){
    printf("%c", moji[i++]+tl);
  }
  printf("\n");

  return 0;
}

```
このプログラムを実行するとこのようになります

```
>HELLO
>hello
```

例えば```+tl```の部分を```-tl```にかえて小文字を入力すると大文字になります。本当にASCIIでは32を加えると小文字になるのだなあということが実感できました。このtlを例えば42とかにかえるとどうでしょうか。

```
>HELLO
>rovvy
```
ちょったした暗号のように使えそうです。

つぎは、ASCIIコードをスペース区切りで入力したら、対応する文字を出力するプログラムを書きたいと思いました。
__これがむずい__

```C
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void){
  //文字列を代入する配列
  char num[1000];
  //区切り文字
  char sep[] = " ";
  //ぽ...ぽいんた...
  char *tok;
  int ch;
  //入力された文字列の読み取り
  fgets(num, 1000, stdin);
  //文字列numを区切り文字sepで分離する
  tok = strtok( num, sep );
  while( tok != NULL ){
   //文字列数値をintに変換
   ch = atoi(tok);
   printf("%c", ch);
   tok = strtok( NULL, sep );  
  }
  printf("\n");

  return 0;
}


```

正直言ってこれを書くまで、printf,scanfとif,switch,while,forくらいしか知らなかったのでここまでたどり着くのに相当時間がかかったしそもそもこれが正しいということもないと思います。しかしこれを実行すると

```
72  69  76  76  79
HELLO
```
入力した```72  69  76  76  79```に対してちゃんと```HELLO```と返してくれたのでうれしい。
C言語では、文字列を指定した区切り文字で分離する```strtok```を使うには```<string.h>```が必要で、数値文字列をint型に変換してくれる```atoi```を使うには```<stdlib.h>```が必要というのもなんだか普段使っているスクリプト言語本当にありがたいなあと思います。
これらを使ったのも、scanfではできないかなと自分では考えたのですが、その実際はどうなのでしょう。

ポインターという概念も、自分ではうまく理解している気もしないので、今回は説明しません。

#まとめ
文字コードの勉強のために？ほとんどやったことのないC言語でやってみよう！というのがあまり得策ではなかったかもしれませんが、文字コードと言うものの複雑さと面白さに少しだけ触れられたかなと思います。新しいことを知ると自分の知らないことがどんどん浮き彫りになりますね。

#出典
http://www3.nit.ac.jp/~tamura/ex2/ascii.html
https://webkaru.net/clang/convert-string-ascii-code/
https://www.ibm.com/support/knowledgecenter/ja/ssw_ibm_i_72/rtref/fgets.htm
https://bituse.info/c_func/18
https://www.ibm.com/support/knowledgecenter/ja/ssw_ibm_i_73/rtref/itoi.htm
http://pg-kura.hatenablog.com/entry/20120611/1339376977