• ベストアンサー

C言語での質問です。

何か文字を打ち、その後鍵(整数)を入力します。 すると、元の文字が暗号化されて表示。 というプログラムを作っています。 暗号化の具体的な方法は、 (1)、元の文を鍵の整数で分けます。 例:元の文「aiueo」鍵「2」→「ai」「ueo」 (2)、そして、分けた文を混ぜます。 文字数が多い方を先に混ぜていきます。 「ai」「ueo」→「uaeio」 (3)、この混ぜた文を暗号文として出力。 という感じのプログラムを作りたいのですが、上手く混ざらず困っています。 出力された時、上手く混ざってなかったり文字化けしてるような文字が出てきたりなど。 ソースは↓です。 #include<stdio.h> #include<string.h> int main(void) { char word[256]; char angou[256]={0}; char kari[1][256]={0}; int key,i,n,a=0,b,mae,ushiro; printf("単語を入力してください。:\n"); scanf("%s",word); printf("鍵となる整数を入力してください。:\n"); scanf("%d",&key); n=strlen(word); i=0; while(i<=key-1){ kari[0][i]=word[i];/*keyの文字数までの文字を入れる。*/ i++; } while(key-1<=n){ kari[1][a]=word[i];/*keyの文字数から最後までの文字を入れる。*/ a++; i++; } i=0; a=0; mae=strlen(kari[0]); ushiro=strlen(kari[1]); if(mae>=ushiro){/*どちらの方が文字数が多いかを比べる。*/ for(b=0;b<=n;b++){ if(b%2){ angou[b]=kari[1][a];/*奇数の時、文字数が少ない方を入れる。*/ a++; } else{ angou[b]=kari[0][i];/*偶数の時、文字数が多い方を入れる。*/ i++; } } } else if(mae<ushiro){ for(b=0;b<=n;b++){ if(b%2){ angou[b]=kari[0][a]; a++; } else{ angou[b]=kari[1][i]; i++; } } } printf("暗号文は%sです。\n",angou); return(0); } 何がおかしいでしょうか?

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

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

ちょっと見ただけで気づく所は > char kari[1][256]={0}; こう宣言してるなら、 kari[1] は使っちゃだめです。 > while(key-1<=n) keyもnもループ内で変化しないから無限ループします。 aやiがどんどん増えるので最終的に変なところにアクセスして止まっているのだと思います。 あとC言語における文字列は'\0'で終端されている必要がありますが その辺は大丈夫ですか? これができてないとstrlenなどは使えませんよ。 > (1)、元の文を鍵の整数で分けます。 > 例:元の文「aiueo」鍵「2」→「ai」「ueo」 > (2)、そして、分けた文を混ぜます。 > 文字数が多い方を先に混ぜていきます。 > 「ai」「ueo」→「uaeio」 たとえば「aiueokakikukeko」に対して鍵「2」を使ったときには どういう動作を期待していますか? 「uaeiokakikukeko」だとしたら後半はそのままで暗号としてはかなり微妙ですよね。

noname#201739
質問者

お礼

指摘され気付きましたw ありがとうございます!

その他の回答 (3)

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.4

>何がおかしいでしょうか?  「おかしい」部分は、皆さんの指摘どおりです。  質問者様のソースを修正し、関数化してみました。   (BorlandC++5.5.1)  ただし、No.2 さんの「じゃ駄目でしょう」部分は、そのままです。  なお、「文字列コピー」なら、該当箇所は、    strcpy( kari[ 0 ], word );    kari[ 0 ][ key ] = '\0'; 文字列終端「のみ」    strcpy( kari[ 1 ], &word[ key ] );  と3ステップで済みます(ただし、下のソース(★)には不向き)。 +++++++++++++++++++++++++++++++++++++ ☆プログラミングでは、今回の例ですと、    ・kari に格納する部分までができた段階で、正しく格納されたかを printf で確認(◆)する。  ・いろいろな条件で確認してから、次のステップの作成に進む。  ・で、完成したら、全ての確認部分を削除する。  とすると良いかも知れません。  (細かいことですが、n は、len とかの方が・・) #include <stdio.h> #include <string.h> void Mazeru( char angou[], char kariOoi[], char kariSukunai[], int n ) {  int k = 0, i = 0;  while( k < n ){   if( '\0' != kariOoi[ i ] ){ // ★    angou[ k ] = kariOoi[ i ];    k++;   }   if( '\0' != kariSukunai[ i ] ){ // ★    angou[ k ] = kariSukunai[ i ];    k++;   }   i++;   angou[ k ] = '\0'; // 文字列終端  } } void AngouKa( int key, char word[] ) {  char angou[ 256 ];  char kari[ 2 ][ 256 ] = { { 0 }, { 0 } }; // 初期化  int i = 0, n, mae0, usr1;  n = strlen( word );  while( i < key ){ //「 i と key が等しく」なって抜ける   kari[ 0 ][ i ] = word[ i ];   i++;  }  while( i < n ){   kari[ 1 ][ i - key ] = word[ i ];   i++;  }  printf( "CHECK[0] [%s]\n", kari[ 0 ] ); // 確認◆  printf( "CHECK[1] [%s]\n", kari[ 1 ] );  mae0 = strlen( kari[ 0 ] );  usr1 = strlen( kari[ 1 ] );  if( mae0 >= usr1 ) Mazeru( angou, kari[ 0 ], kari[ 1 ], n );  if( mae0 < usr1 ) Mazeru( angou, kari[ 1 ], kari[ 0 ], n );  printf( "原文= %s 暗号文= %s 鍵= %d\n\n", word, angou, key ); } void main() {  AngouKa( 2, "aiueo" );  // 入力部省略  AngouKa( 3, "aiueo" );  AngouKa( 0, "123456789" ); } 注:インデントに全角空白を用いています。コピペ後、タブに一括変換して下さい。

noname#201739
質問者

お礼

まとめて頂ありがとうございます!

回答No.3

他の方も指摘してますが、 ・kariの領域が足りない([1]じゃなくて[2]) ・2個目のwhileが無限ループ(i <= n??) ・文字列の終端を'\0'としてない の部分が大問題です。 さらに、混ぜてると短い方(奇数側)が先に文字が足りなくなるはずですが、なくなった後の処理がないです。

  • t_nojiri
  • ベストアンサー率28% (595/2071)
回答No.2

char kari[1][256]={0}; で定義して、 angou[b]=kari[1][a];/*奇数の時、文字数が少ない方を入れる。*/ は、スタック破壊ですね。 後、文字列コピーするのはstrcpyで kari[0][i]=word[i];/*keyの文字数までの文字を入れる。*/ じゃ駄目でしょう。

noname#201739
質問者

お礼

解答ありがとうございます!

関連するQ&A