• ベストアンサー

シーザー暗号(C言語)

シーザー暗号というものを作ろうとしていますが、文字のずらし方がわからず詰まっています。 手順は一応考えてあります。 (1)入力された文字を配列input[301]に代入 (2)何文字ずらすかを指定してその数値を変数countに代入 (3)入力された文字の長さを変数lenに代入 (4)inputとcountとlenを、文字をずらしてそれをoutputに返す関数shiftに渡す (5)outputを表示する のような感じですが、肝心の文字のずらし方がわかりません。 JISコードを使ってやるといいと聞いたんですが、そのやり方がわかりません。 ソース↓ #include <stdio.h> #include <string.h> int shift_char(char x[], int y, int z) { int i; for(i = 0; i <= z; i++) { x[i] = x[i] + y; } return x; } int main(int argc, char* argv[]) { char input[301]; char output[301]; int count, len, i; printf("文字を入力してください: "); scanf("%s" ,input); printf("何文字ずらしますか: "); scanf("%d" ,count); len = strlen(input); output = shift_char(input, count, len); for(i = 0; i <= len; i++) { printf("%s" ,output[i]); } return 0; } よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

1つのサンプル 文字をテーブルで持っているので、ある文字を、何文字ずらしたら、どの文字になるかというのは、わかりやすいんじゃないかと思います。 実際は、こんな風にしなくても、文字コードの範囲で処理すればいいかと思いますが、文字コードの並びがマシンに依存しなくなるという効果があるかもしれません。 質問のコードが入力文字列を直接変更しているようなので、 入力を変更するようにしています。 出力用の領域を呼び出し側で準備するのであれば、そのアドレスを処理側に渡してやる必要があると思います。 ---------------------------------------------------------------- #include <stdio.h> #include <string.h> char *shift_char(char x[], int y){ static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; static const int table_len = (sizeof(table)-1) / 2; char *p; y %= table_len; for(p=x;*p;p++) *p = *(strchr(table, *p) + y); return x; } int main(void){ char input[301]; int count; printf("文字を入力してください: "); scanf("%s", input); printf("何文字ずらしますか: "); scanf("%d", &count); printf("%s", shift_char(input, count)); return 0; }

cermet
質問者

お礼

ご回答ありがとうございます。 お礼が遅くなって申し訳ないです。 自分にはこれがどんな動きをしているかまだはっきりわかりませんが、色々調べてはっきりさせます。

その他の回答 (3)

  • nerosuke
  • ベストアンサー率33% (39/115)
回答No.4

他の方に指摘されていますように output = shift_char(input, count, len); は成立しません。 //配列を引数で渡すときは他の変数とは違いアドレスが渡りますので //渡し元の値にも影響がでますので、引数をchar型のポインタにしましょう //とりあえず質問者の関数をそのまま書き直しましたので //暗号の数式もそのままです(ここを直すとずばり答えになってしまいますので・・・) void shift_char(char *in, char *out, int add, int cnt) { int i; for(i = 0; i <= cnt; i++) { out[i] = in[i] + add; } } }

cermet
質問者

お礼

ご回答ありがとうございます。 お礼が遅くなって申し訳ないです。 何とか完成できましたが、なんだかはっきりしない部分もあったので、色々調べてみます。

  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.2

// 文字のずらし方 char pre; char post; int count; // pre を count だけずらして post に入れる // 注意:pre,postはchar型です。char*型ではありません。 post = pre + count; // 以上。 // ただし、postがアルファベットの範囲を超えてしまうことがある // (preが'z'だったりした場合) // その時は'z'+1 = 'a'とすれば……どうすればいいか分かるよな?

cermet
質問者

補足

ご回答ありがとうございます。 >その時は'z'+1 = 'a'とすれば…… 申し訳ないですが、正直わからないです・・・

  • Werner
  • ベストアンサー率53% (395/735)
回答No.1

> output = shift_char(char x[], int y, int z) ずらし方以前の問題が、この部分と関数shift_charにはあります。 ・outputは配列なので左辺値になれない(代入不可)。 ・shift_charの返り値はintなのに、実際にreturnしているのはchar*型。 ・shift_char内でinputを書き換えている。(それを意図しているなら問題ないが) ・(クリティカルな問題ではないが)lenは引数にしなくても関数内で文字列終端は分かる。 特に、1つ目はコンパイルエラーに、2つ目もWarningが出そうなものですが、 エラーは出ませんでしたか? inputに上書きするのではなく、別の文字列に書き出したいのなら、 shift_charは出力先の配列も引数にして > void shift_char(char in[], char out[], int key) のようにします。 ずらしかたはASCII文字を対象にするなら、 制御文字を除く32~126で循環させれば良いのではないでしょうか。 http://e-words.jp/p/r-ascii.html

cermet
質問者

補足

ご回答ありがとうございます。 おっしゃる通り、エラー出ています。 >shift_charは出力先の配列も引数にして これがどういうことかよくわかりません。配列は左辺値になれないので、shift_charの中でprintfをするということでしょうか?

関連するQ&A