質問: 0以上26未満の整数keyを読み込んで、その後読み込んだアルファベットをkey分ずらして表示するプログラムを作成したいのですが、 実行はキーと読み込むアルファベットの条件によっては正しく出来るものの、例えばキーが1で読み込むアルファベットがzのときに 実行結果がおかしくなってしまいます。 私は以下のようにプログラムを作成しました ``` #include int main() { char c; int n; n%=26; printf("キー(0以上26未満)を入力: "); scanf("%d",&n); while((c=getchar())!=EOF){ if((c>='a' && c<='z') || (c>='A' && c<='Z')){ c+=n; } printf("%c",c); } printf("\n"); return 0; } ``` 実行結果 ``` $ ./a.out キー(0以上26未満)を入力: 1 abcd bcde z { ``` 正しい実行結果 ``` $ ./a.out キー(0以上26未満)を入力: 1 abcd bcde z a ``` どうすれば正しい実行結果となりますか。
回答: `z`の次が`a`, `Z`の次が`A`になるとすれば、考え方としては`a`や`A`が`0`, `b`や`B`が`1`, ..., `y`や`Y`が`24`,`z`や`Z`が`25`と相互に変換できる、言わば26進数と見做せば良いわけです。 `z`の(+1した)次の文字が`a`になるのは、10進数で言えば`09`に`01`を足して`10`になり、その1桁目だけ(10で割った余り)を表示すると`0`になるのと同等です。 つまり`z`は明示されてはいないけれども`az`であり、そこに10進数で言えば`01`である`ab`を足すと`ba`になり、それを`ba`で割った余り(1桁目)だけを表示すると`a`になる、という計算を実装することになります。 文字が英大文字なら、数値と対応する文字が`A`~`Z`になるわけです。 細かい条件を考慮した`for`ループの中の手順は以下になります。 (実際のコーディングと1対1にするには少し冗長ですが) 1. 入力された文字が英大文字または英小文字か、それ以外かを判断する 2. 入力された文字が英大文字なら`A`~`Z`を`0`~`25`に変換して作業変数に入れる 3. 入力された文字が英小文字なら`a`~`z`を`0`~`25`に変換して作業変数に入れる 4. 入力された文字が英大文字または英小文字なら作業変数に整数key数を加算した後、`26`で割った余りを代入する 5. 入力された文字が英大文字なら4.の結果の作業変数を`A`~`Z`に変換して入力された文字と置き換える 6. 入力された文字が英小文字なら4.の結果の作業変数を`a`~`z`に変換して入力された文字と置き換える 7. 入力された/または処理されて置き換えられた文字を出力する (あと @metropolis さんコメントに関連する`整数key`変数の取り扱いも注意が必要ですが)