• ベストアンサー

シーザー暗号(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

  • c言語の文字列の逆順のプログラムがわかりません

    文字列を逆順して出力するプログラミングがわかりません。 #include <stdio.h> #include <string.h> void reverse(char *moji, char *gyaku); int main(void) { char x[30]; char y[30]; puts("文字を入力してください。\n"); scanf("%s", x); reverse(x, y); printf("逆順すると%sです。\n", y); return (0); } void reverse(char *moji, char *gyaku) { int i, len; len = strlen(moji); gyaku = moji + len - 1; for(i = 0; i < len; i ++){ putchar((int)*gyaku); gyaku--; } } 理想とする実行結果は 文字を入力してください。 abcdefg 逆順するとgfedcbaです。 なんですが、 上記のソースを実行すると 文字を入力してください。 abcdefg gfedcba逆順すると(謎の漢字)です。 となります。 どこがおかしいんでしょうか? よろしくおねがいします。

  • C言語でscanfを用いた入力

    C言語でscanfの動作を確かめる為に、次のプログラムを作成して実行してみました。 #include <stdio.h> int main(void){ int i; printf("Input1:"); scanf("%d",&i); printf("Input2:"); scanf("%d",&i); printf("Output:%d",i); return 0; } このプログラムは1回目と2回目に数値を入力すると正常に出力します。 例 1回目の入力に10、2回目の入力に20を入力した時の出力結果 Input1:10 Input2:20 Output:20 今度は1回目で数値、2回目で文字を入力してみました。 そしたら2回目の入力が無視されました。 例 1回目の入力に10、2回目の入力にAを入力した時の出力結果 Input1:10 Input2:A Output:10 今度は1回目で文字を入力してみました。 そしたら2回目の入力は要求せず、いきなりよく分からない数値が出力されました。 例 1回目でAを入力した時の出力結果 Input1:A Input2:Output:-858993460 どうして文字を入力したら正常に出力しなくなるのでしょうか?

  • C言語 文字列の操作

    文字Cが含まれる個数を求めたいです #include <stdio.h> int str_chnum(const char str[],int c) { int i; int count=0; for(i=0;str[i]!="\0";i++) if (str[i]==c) count++; return(count); } int main(void) { char st[100]; printf("検索文字列を入力してください:"); scanf("%s",st) ; printf("検索文字列数は%uです。\n",st,int str_chnum(const str[],int c)); return(0); } コンパイルできません。なぜですか?printfの行がたぶん間違っていると思うんですが。。。

  • C言語文字数4つカウント

    こんにちは。大学の課題で「キーボードから入力した文字数に含まれる'h''o''g''e'の4つの文字数をカウントする関数を含むプログラムを完成させよ」という課題がありました。なかなかできず現段階では以下のようになっています。どうすれば問題文のように実行できますか? #include <stdio.h> char str_chnum(const char str[], int ch) { int count = 0; int i; for(i = 0; str[i] != '\0'; i++) { if(str[i] == ch) count++; } return(count); } int main(void) { char str[128]; int ch; printf("文字列を入力してください:"); scanf("%s", str); printf("検索する文字を入力してください:"); scanf(" %c", &ch); printf("%cは%d個ありました。\n", ch, str_chnum(str, ch)); return(0); }

  • C言語のことについて教えてください

    C言語のことで教えてください。お願いします #include <stdio.h> #include <time.h> #include <stdlib.h> #include <string.h> #include <windows.h> int main(int argc, char* argv[]) { char *data[] = {"おひつじ","おうし","ふたご","かに","しし","おとめ","てんびん", "さそり","いて","やぎ","みずがめ","うお"}; int data_len = 12; //データの数 char input[10]; //プレイヤーの入力値 int i,p,start; int win = 1; int mawari = 1; //内回りの場合は1 int p_turn = 0; //プレイヤーのターン if ((argc > 1) && (strcmp(argv[1], "-soto") == 0)) { mawari = 0; } srand(time(NULL)); start = rand()%data_len; printf("古今東西山手線ゲ~ム!\n"); printf("お題:星座の名前\n"); for(p = start,i = 1; i<= data_len; i++,p_turn = !p_turn ) { sleep(500); if(p_turn == 0) {printf("コンピューター");} else if (p_turn == 1) {printf("プレイヤー");} sleep(500); printf("ちゃん! >"); if(p_turn == 0) { printf("%s\n",*(data+p)); } else { scanf("%s", input); while (getchar() != '\n') { } if(strcmp(*(data+p),input) != 0) { win = 0; break; } } if(mawari == 1) { p++; } else {p--;} if((mawari ==1) && (p == data_len)) { p = 0;} if((mawari ==0) && (p == -1)) {p = data_len-1;} } if(win == 1) {printf("あなたの勝ち");} else {printf("あなたの負け");} return 0; } なんですが、どうしても } if(mawari == 1) { p++; } else {p--;} if((mawari ==1) && (p == data_len)) { p = 0;} if((mawari ==0) && (p == -1)) {p = data_len-1;} } 変数Pに今は乱数1-12がはいっているのに、なぜこの処理を行うかがわかりません。どうしてなんですか?教えてください。

  • C言語の文字列について

    abcdefghという文字列を入力した時に以下のように表示させたいのですがわかりません。(入力した文字を逆から表示させて、且つ文字数を4分割させて改行させる) hg fe dc ba 自分で考えたソースは以下のようです。(これではhgfedcbaと表示するだけなのです)どうしてもわからないので教えてください。宜しくお願いします。 #include <stdio.h> #include <string.h> int main(void) { char input[20]; size_t len,h,k,j; size_t i; gets( input); len=strlen(input); h=len/5; k=h; for(j=1; j<=5;++j) { for(h=k*(j-1); h<k*j; ++h) { printf( "%c", input[len - h - 1]); } } scanf( "%20s", input); return 0; }

  • C++

    文字を入力して、それを1つ右にずらして出力する問題。 例  aret → tare 関数内でポインタを使用するのが条件です。 ズラしているつもりが、入力した文字がそのまま出力されてしまいます。 自分の方針としては、 関数内で入力された文字の長さを確認。 文字列の最後の文字をtmpに保存して ドンドン右にずらして保存していく。 最後にtmpに保存したものを、文字列の最初に入れる。 というものです。 わかるかた、ご指導お願いします。 #include<stdio.h> #include<string.h> void kaiten(char *t) { int len =0; int i; char tmp; while (*t++){ len++; } tmp = *(t+(len-1)); for(i=len-1;i>0;i--) *(t+i)=*(t+i-1); *t = tmp; } int main() { char s[100]; printf("文字列を入力:"); scanf("%s",s); kaiten(s); printf("一文字ずらすと:%s\n",s); }

  • C言語のfor文について

    閲覧有難うございます。さて本題ですが、以下のプログラム #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <Windows.h> #define S 500 int main(void) { unsigned char x, input; int i; for (i = 0; i < 20; i++) { x = 0x01; scanf("%#x", &input); Sleep(S); printf("%#x\n", x); } return 0; } を実行したら、一度だけキー入力をした後はキー入力の処理は飛ばされ、 最初に入力した値がi < 20までループが続くのですが・・・ 正常な動作としては キー入力  ↓ スリープ  ↓ 入力値を出力  ↓ 再びキー入力 となるはずですよね?しかし何故か2回目以降のscanf()が省略されるのは何故でしょうか? 環境はVisual C++ 2010です。

  • C言語

    文字列を逆順にするプログラムを考えているのですが分かりません。(例)qwerならrewqです。入力終了は、EOFです。考えたのですが、分かりません。(コンパイルエラーです。)教えてください。宜しくお願いします。#include <stdio.h> unsigned str_length(const char str[]) { unsigned len=0; while (str[len]) len++; return (len); } void put_rstring(const char str[]) { unsigned i = str_length(str): while (i-- >0) putchar(str[i]); } int main(void) { char str[30]; int ch; printf("文字列を入力\n"); /* ----この文字列を入力したあとに、Ctrl+Zを押すと、逆から表示               で反対から、文字列が表示----*/ while (1) { ch=getchar(); if (ch==EOF) break; } printf("逆から表示"); put_rstring(str); puts("です。"); return(0); }

  • C言語で、文字の出現頻度を求める問題がわかりません

    #include <stdio.h> int main(void) { char ss[80],ascii[128]; int len,i; for(i=0;i<128;i++){ ascii[i]=0; } printf("Input the string : "); scanf("%s",ss); len=strlen(ss); for(i=0;i<len;i++){ ???//その文字のアスキーコードがi番であればascii[i]の値をインクリメント; } for(i=0;i<128;i++){ if(ascii[i]>0){ printf("%c : %5.2f % \n",i,???);//???には出現割合の計算式 } } return 0; } 結果例 入力 aaaa000bbT 出力 a : 40.00% 0 : 30.00% b : 20.00% T : 10.00% ???の部分がわかりません・・・ テストにでるとのことなので焦ってます;;

このQ&Aのポイント
  • 今年Windows 11に買い換え、プリンターも新しく購入しましたが、プリンターが認識されません。
  • Canonに連絡し、対策を講じたものの、認識されないため、PCの方に相談するよう指示されました。
  • プリンター接続のトラブルの原因としては、接続ケーブルの不良やドライバの問題が考えられます。
回答を見る

専門家に質問してみよう