72520


0以上26未満の整数keyを読み込んで、その後読み込んだアルファベットをkey分ずらして表示するプログラムを作成したいのですが、  
実行はキーと読み込むアルファベットの条件によっては正しく出来るものの、例えばキーが1で読み込むアルファベットがzのときに  
実行結果がおかしくなってしまいます。

私は以下のようにプログラムを作成しました

[code]

    #include<stdio.h>
    
    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;
    }
    
[/code]

実行結果

[code]

    $ ./a.out
    キー(0以上26未満)を入力: 1
    
    abcd
    bcde
    z
    {
    
[/code]

正しい実行結果

[code]

    $ ./a.out
    キー(0以上26未満)を入力: 1
    
    abcd
    bcde
    z
    a
    
[/code]

どうすれば正しい実行結果となりますか。


CC BY-SA 4.0
2020-12-07T05:44:23.310
72470
2020-12-09T17:01:15.723
2020-12-09T17:01:15.723
29826
41837
question
c
アルファベットをkey文字分ずらして表示するプログラム


回答ではありません。あしからず。  
ASCIIのキャラクタコードを見ると'z'は0x7Aです。  
これに1を足すと0x7Bになり、この値のキャラクタは'{'なので、実行結果は正しいと考えられます。  
'z'+1=0x7Bの結果を文字の'a'、すなわち0x61にしたいのなら、その仕様(ないし演算)を考える必要があると思われます。


CC BY-SA 4.0
2020-12-07T07:29:28.687
72476
2020-12-07T07:29:28.687
3793
72470
answer


`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`変数の取り扱いも注意が必要ですが)


CC BY-SA 4.0
2020-12-07T09:08:56.340
72479
2020-12-07T09:08:56.340
26370
72470
answer


質問者氏から仕様が出てこないので勝手に決めるの心  
\- シングルバイトの `A-Z` と `a-z` をカエサル暗号処理する -- ここは設問にて提示されている  
\- それ以外の文字が現れたら無変換 -- 設問にないので勝手に決めた  
\- `Z` の次は `A` (`z` と `a` も同様) -- 設問にないので勝手に決めた  
\- `A` の前は `Z` (`a` と `z` も同様) -- 設問にないので勝手に決めた

普通はプログラムを書く前にこういう「仕様」を定めないと何を書いていいかわからないはず。「仕様」は設問にあるところより、設問に書かれていないところに関して決めなきゃならないあたりが難しいんだろう。っていうかたぶん質問者氏は「自分が何をしたいか」「何をしないといけないのか」を整理する前にコードを書いているのだと思われる。そのままだとゴールが無いのに走り出しているようなもので、どこで終わらせて良いのかわからない＝永遠に終わらないってことっス。それでは楽しくないと思うぞ。案件分析→仕様策定なしにコードを書かないほうがいい。コード書いている最中に「これはどうすればいいんだろう」と疑問に思うことがあったら、それは仕様が不足しているってこと。

あと [c](/questions/tagged/c "'c' のタグが付いた質問を表示")
では「代入」はそこを通過するときにその時の値で計算をするという意味で、事前に恒等式を定義しているという意味ではないっス。

オイラのサンプル提供してみる。今回も EBCDIK
対応の厳密規格合致を狙ってみた。あえて出題通りの実装としない、かつコメント０としておくっス。各処理が何を意図しているのかを読み取って、設問にばっちり合致するプログラムを解説コメント付きでアップしてくれるとうれしい。

[code]

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int rotate(const char* suite, char letter, int difference) {
        const char* p=strchr(suite, letter);
        if (p==0) return EOF;
        ptrdiff_t offset=p-suite;
        offset+=difference;
        offset%=26;
        return suite[offset];
    }
    
    void caesar(char* plain, int difference) {
        for (char letter; letter=*plain; ++plain) {
            int cipher;
            cipher=rotate("ABCDEFGHIJKLMNOPQRSTUVWXYZ", letter, difference);
            if (cipher!=EOF) { *plain=cipher; continue; }
            cipher=rotate("abcdefghijklmnopqrstuvwxyz", letter, difference);
            if (cipher!=EOF) { *plain=cipher; continue; }
        }
    }
    
    int main(int argc, char* argv[]) {
        if (argc<2) return 0;
        ++argv;
        int difference=strtol(*argv, 0, 0)%26;
        if (difference<0) difference=26+difference;
        for (++argv; *argv; ++argv) {
            caesar(*argv, difference);
            puts(*argv);
        }
        return 0;
    }
    
[/code]

んで実行結果も提供してみる。暗号化と復号が同一のプログラムでできていることがわかる。

[code]

    $ ./caesar 3 z9m9z
    c9p9c
    $ ./caesar -3 c9p9c
    z9m9z
    $
    
[/code]


CC BY-SA 4.0
2020-12-09T04:56:21.920
72520
2020-12-09T04:56:21.920
8589
72470
answer