【最大10000ポイント】当たる!!質問投稿キャンペーン!

プログラミング シーザー暗号 複合化 Linux C言語

シーザー暗号を複合化するプログラムを教えてください!

大文字と小文字が混合の文字列で3つずらして複合化したいです

文字数が28字などでは収まらないくらいあります

それをふまえたプログラムを教えてください

よろしくお願いします

このQ&Aに関連する最新のQ&A

A 回答 (2件)

シーザー暗号はコンピュータがまだ無い時代のもので、非常に単純な暗号と言えます。


しかし、こんな単純なものでも、いざプログラムでやろうとすると、色々なやり方があります。
Wikipediaでシーザー暗号を見ると、必ずしも3つずらすのが決まりではないようです。
ですから、もし汎用性を考えれば、3を変数に代入してNo.1さんのような方法が適切と思いますが、あえて究極のやり方を考えるならば、次のような方法があります。

unsigned char decipher_tbl[256] =
"****************"
"****************"
"****************"
"****************"
"*xyzABCDEFGHIJKL"
"MNOPQRSTUVW*****"
"*XYZabcdefghijkl"
"mnopqrstuvw*****"
"****************"
"****************"
"****************"
"****************"
"****************"
"****************"
"****************"
"****************";

plaintext = decipher_tbl[decipher_text];

decipher_textが1文字の暗号文字となります。
1文字の復号ならば、これだけで完成です。
この方式の最大の利点は、このテーブルが正しければ、絶対に間違いがないこと。
つまり、動作確認テストが楽なことです。
そして、たとえば数字も変換することにした場合も、このテーブルを仕様に合わせて変更するだけで済みます。
(もし、外部ファイルにすれば、リコンパイルの必要さえ無くなります)
そして、今は面倒なので対象文字(つまり英字)以外は"*"にしましたが、対象文字以外をそのまま出力するか、あるいはすべてを3つずらすかなども、このテーブルを変更すれば自由自在です。
但し、対象文字以外は削除するなど(暗号化時に)文字を減らしたりする場合には、暗号化前にそれなりのロジックが必要となります。
また、最初に記述したようにずらすのは、3(でなくともいいのですが)の固定となります。

そして、この方法がシーザー暗号の最速の方法です。

http://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%BC% …

もし、ASCIIコード(英字)がわからなければ、こちらをご覧ください。
http://e-words.jp/p/r-ascii.html
    • good
    • 0

どう「複合」するのでしょうか?


混ぜ合わせるモノが判らなければちょっと答えられません

と云うネタはこのあたりにしておいて「復号」するのですよね
・まず元の文字列をchar配列にでもする
・文字コード的には単純に数を引いたり足したりすれば出たりする
  例えば「char c = 'z' - 3」という計算をすれば'w'が得られるはずです
  但し'a' - 3 など、範囲外となる場合にはそれなりの対応をする必要があります
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q暗号化・復号化のアルゴリズムにはどんなものがありますか?

Cでプログラミングを勉強しており、20文字ほどの文字列を暗号化・復号化するプログラムを考えていますが、ネットを検索しても暗号化アルゴリズムでなかなかいいものが見つかりません。

私のリクエストとしては

・暗号化対象は半角英数字、半角記号のみ。
・単に文字コードを1つずつずらしたような簡単な暗号ではなく、複雑なアルゴリズムを使用したい。
・アルゴリズムは複雑でもプログラムは簡潔にできるものがいい。(長くても数百行程度)。
・アルゴリズム自体の仕様が公開されている。
・アルゴリズムは数学式で表せるものがいい。
・スーパーコンピュータを使わなければ解けないほど時間がかかる暗号化アルゴリズムでなくてもいい。
・暗号化のライブラリファイルは使わず、自前で全部コードを書きたい。
・公開鍵や秘密鍵を使わなくてもいい。

上記の条件を満たす暗号化アルゴリズムでいいものがありましたら、教えてください。

以上、よろしくお願いします。

Aベストアンサー

Blowfishはどうでしょうか。

・暗号化対象は半角英数字、半角記号のみ。
> バイナリデータでしたらなんでも暗号化できます。

・単に文字コードを1つずつずらしたような簡単な暗号ではなく、複雑なアルゴリズムを使用したい。
> 簡単に解く方法はまだ見つかっていないはずです。

・アルゴリズムは数学式で表せるものがいい。
> どのようなものを数学式として想定されているのかは分かりませんが、
> 数学式で表せない暗号化方式はコードにできないと思いますので
> 数学式でも表せるでしょう。

・暗号化のライブラリファイルは使わず、自前で全部コードを書きたい。
> サンプルコードを見ていただければ分かるのですが、600行ほどのコードで実現できます。自前で全部書けるでしょう。

> 公開鍵や秘密鍵を使わなくてもいい。
共通鍵暗号方式なので公開鍵や秘密鍵は使いません。

参考URL:http://www.schneier.com/blowfish-download.html

Qcharと%c , %s の関係について

char型の変数の扱いで悩んでいます。
具体的には以下の二つのプログラムの差異についてです。

----------------------
char c;

scanf("%c", &c);
printf("%c\n", c);

-----------------------
char c;

scanf("%s", &c);
printf("%s\n", &c);

-----------------------


上のプログラムは正しいと思うのですが、下のプログラムが正しいのかどうか、わかる方に教えていただきたいと思い質問させていただきました。

どちらのプログラムも問題なく動作します。
僕自身は 下のプログラムの printf 関数については間違った使い方なのではないかと思っています。

scanf("%s", &c) は入力された文字のうち、終端文字の手前までの文字を引数のポインタが示すオブジェクトへ順に格納していく関数だと理解しているので、入力された文字が一文字だった場合、&cの示すオブジェクトに文字が代入されると考えたからです。

逆に printf("%s", &c) は、&cの示すオブジェクトから”ヌル文字”の手前までの文字列を順に表示する関数だと理解しているので、問題なく動作しているのは&cで示されるオブジェクトの後ろの領域が偶然'\0'だったからではないかと考えたからです。

何かの本で、未使用の領域は0である確率が高いという記述をみたことがあり、'\0'は0と同じだということなので問題なく動作する率が高いのではないかと思っています。


僕の考え方がどの程度正しくて、正確にはどうなのかを教えて欲しいです。


ちなみに、

-----------------------
char c;
char str[100];

scanf("%s", str);
scanf("%c", &c);
------------------------

と書くと c には改行文字が代入されてしまいます。
scanf("%s", str);
において"aasssdd "と最後に空白を入れると
c には空白文字が代入されます。

しかし、
--------------------------
char str1[100];
char str2[100];

scanf("%s", str1);
scanf("%s", str2);
--------------------------
においては、
scanf("%s", str1);
で "asdfg "と最後に空白を入れても次のstr2が空白で始まることはありません。


この辺りの処理がどのような法則で実行されているのかが分かりづらくて悩んでいます。
おそらく、
scanf("%s", str);
の場合には最初の文字が空白や改行文字でも、その次に有効な文字があればそれらの改行や空白を無視するのではないかと思っています。


分かる方がいましたら回答をよろしくお願いします。

char型の変数の扱いで悩んでいます。
具体的には以下の二つのプログラムの差異についてです。

----------------------
char c;

scanf("%c", &c);
printf("%c\n", c);

-----------------------
char c;

scanf("%s", &c);
printf("%s\n", &c);

-----------------------


上のプログラムは正しいと思うのですが、下のプログラムが正しいのかどうか、わかる方に教えていただきたいと思い質問させていただきました。

どちらのプログラムも問題なく動作します。
僕自身は 下...続きを読む

Aベストアンサー

> char c;
> scanf("%s", &c);
char c では1文字分の領域しか確保されていないので、
1文字以上の文字列を無理矢理格納すると
他のデータが存在しているかもしれない領域を書き換えてしまいます。(メモリ破壊)

なお、'\0'はscanfが(本来書き込んではいけない領域に対してですが)書き込んでいます。


> と書くと c には改行文字が代入されてしまいます。
最初のscanfが改行文字を読み込んでいないからです。
以下のページに書かれている内容と本質的には同じ。
http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-

> 最初の文字が空白や改行文字でも、その次に有効な文字があればそれらの改行や空白を無視するのではないかと思っています。
そう考えて問題ないと思います。

Q作ったプログラミングC何だけど、評価していただけませんが?不足があれば、教えてください!

文字列「abc」の各アルファベットを1文字ずらすと文字列「bcd
」になり、
文字列「nisidate」の各アルファベットを2文字ずらすと文字
列「pkukfcvg」となる。さらに、
文字列「kibishii」の各アルファベットを2文字ずらすと文字
列「mkdkujkk」となる。
このような、任意の文字列の各要素を任意の文字数ずらすプロ
グラムを作成する、なお、zを1文字ずらしたとき
のアルファベットはaとする。

#include <stdio.h>
#include <string.h>

int main(void)
{
char str[27]="abcdefghijklmnopqrstuvwxyz",str1[50], str2[50];
int x,i,j,len;

printf("文字列を入力---> ");
scanf("%s", str1);

printf("何文字ずらすかを入力---> ");
scanf("%d",&x);

len=strlen(str1);

for(i=0;i<len;i++)
{
for(j=0;j<27;j++)
{
if(str1[i]=='z')
{
str2[i]=str[x-1];
}
if(!(str1[i]=='z'))
{
if(str1[i]==str[j])
{
str2[i]=str[j+x];
}
}
}
}

printf("%d文字ずらした文字列は%sです\n", x, str2);

return 0;

よろしくお願いします!!

文字列「abc」の各アルファベットを1文字ずらすと文字列「bcd
」になり、
文字列「nisidate」の各アルファベットを2文字ずらすと文字
列「pkukfcvg」となる。さらに、
文字列「kibishii」の各アルファベットを2文字ずらすと文字
列「mkdkujkk」となる。
このような、任意の文字列の各要素を任意の文字数ずらすプロ
グラムを作成する、なお、zを1文字ずらしたとき
のアルファベットはaとする。

#include <stdio.h>
#include <string.h>

int main(void)
{
char str[27]="abcdefghijklmnopqrst...続きを読む

Aベストアンサー

#3です。
指摘だけでも、不親切なので。
以下、模範解答。
修正点は以下の通り。
ずらしの文字は、右側だけだが、左側にも対応。(左側の場合、マイナスの値を指定)
ずらじの文字数が、26以上でも対応する。2600のずらし等もOK。
zの文字のみを特殊な扱いにしない。yを2文字ずらして、aになるようにする。
以下ソース。
---------------------------------------------
#include <stdio.h>
#include <string.h>
//shfit_count :ずらし数(26以上を許す)負の数でも良い
//char_in :入力文字(1文字)
//戻り値:ずらした結果の1文字
char shift_char(int shift_count,char char_in)
{
char str[27] = "abcdefghijklmnopqrstuvwxyz";
int i,j;
//入力文字の位置を検索
for (i = 0; i < 26; i++){
if (char_in == str[i]) break;
}
//入力文字がa~z以外ならaとみなす
if (i == 26) i = 0;
//ずらした後の文字の位置を求める。26の余りを求めるのは、26以上のずらしに対応するため
j = (i + shift_count)%26;
//左へのずらしに対応する
if (j < 0) {
j += 26;
}
//これで 0<=j<=25であることが保証されるので、この位置の文字を返す
return str[j];
}
int main(void)
{
char str[27]="abcdefghijklmnopqrstuvwxyz",str1[50], str2[50];
int x,i,j,len;

printf("文字列を入力---> ");
scanf("%s", str1);

printf("何文字ずらすかを入力---> ");
scanf("%d",&x);

len=strlen(str1);

for(i=0;i<len;i++)
{
str2[i] = shift_char(x,str1[i]);
}
//終端にNULLを付加する
str2[i] = '\0';
printf("%d文字ずらした文字列は%sです\n", x, str2);

return 0;
}
--------------------------------------------------------

#3です。
指摘だけでも、不親切なので。
以下、模範解答。
修正点は以下の通り。
ずらしの文字は、右側だけだが、左側にも対応。(左側の場合、マイナスの値を指定)
ずらじの文字数が、26以上でも対応する。2600のずらし等もOK。
zの文字のみを特殊な扱いにしない。yを2文字ずらして、aになるようにする。
以下ソース。
---------------------------------------------
#include <stdio.h>
#include <string.h>
//shfit_count :ずらし数(26以上を許す)負の数でも良い
//char_in :入力文字...続きを読む

Q市松模様

2つの正の整数を入力すると、それぞれ縦横の数とする”*”の市松模様を出力するプログラム

縦はなんとなくわかるのですが
横の定義の仕方がよくわからないので
教えてください

縦5横6の例
_*_*_*
*_*_*_
_*_*_*
*_*_*_
_*_*_*

_はスペースの意

Aベストアンサー

No.1 No.3のarukamunです。

皆さんが書かれているのは関数です。
main等から正しく呼び出せば良いのです。
sample.cとした場合

#include <stdio.h>
#include <stdlib.h>

void ichimatsu(int v,int h)
{
  int i,j ;

  for (i=0 ;i<v ;i++){
    for (j=0 ;j<h ;j++){
      if ( (i+j)%2 ){
        printf("*");
      } else {
        printf(" ");
      }
    }
    printf("\n");
  }
}

main(int argc,char *argv[])
{
  if ( argc < 3 ){
    printf("usage : sample 縦 横");
  } else {
    ichimatsu(atoi(argv[1]),atoi(argv[2]));
  }
}

No.1 No.3のarukamunです。

皆さんが書かれているのは関数です。
main等から正しく呼び出せば良いのです。
sample.cとした場合

#include <stdio.h>
#include <stdlib.h>

void ichimatsu(int v,int h)
{
  int i,j ;

  for (i=0 ;i<v ;i++){
    for (j=0 ;j<h ;j++){
      if ( (i+j)%2 ){
        printf("*");
      } else {
        printf(" ");
      }
    }
    printf("\n");
  }
}

main(int argc,ch...続きを読む

QC言語で、入力された、文字列を逆に並べるプログラム。

タイトルのとおりのプログラムをつくりたいんです。
例えば、abcと入力したら、cbaと返してくれるものです。
条件として、ポインタを使えと言われています。
自分で書いたソースは、

0: #include<stdio.h>
1: char re(char *s);
2: main()
3: {
4:char s[10];
5:gets(s);
6:re(s);
7:printf("%s\n",s);
8: }
9:
10: char re(char *s){
11:char c[10];
12:
13:c[9]=s[0];
14:c[8]=s[1];
15:c[7]=s[2];
16:c[6]=s[3];
17:c[5]=s[4];
18:c[4]=s[5];
19:c[3]=s[6];
20:c[2]=s[7];
21:c[1]=s[8];
22:c[0]=s[9];
23:
24:return c[10];
}

C言語を勉強し始めたばかりで、なかなか思うようにかけないでいます。
文字列を入力するのは、4行目~7行目で大丈夫だと思うんですよ。
文字列を逆に並べる、関数 re(char *s)を作れずにいます。
配列s[10]に入っている、文字を最後から取り出して、c[10]にいれていけば、ひっくり返ると思っているんですが、作れません。
13行~21行目の作業も、whileかforでループさせるべきなのもわかってるんですが、条件をどうしたらいいか分からずに作れずにいます。今のソースのまま実行しても、入力したまま出力してしまいます。
さらに、ポインタも今日はじめて勉強して、うっすらと知ってるくらいなので、アドレスとかが、イメージできないでいます。
ながくなってすいません。アドバイスいただきたいです。よろしくおねがいします。

タイトルのとおりのプログラムをつくりたいんです。
例えば、abcと入力したら、cbaと返してくれるものです。
条件として、ポインタを使えと言われています。
自分で書いたソースは、

0: #include<stdio.h>
1: char re(char *s);
2: main()
3: {
4:char s[10];
5:gets(s);
6:re(s);
7:printf("%s\n",s);
8: }
9:
10: char re(char *s){
11:char c[10];
12:
13:c[9]=s[0];
14:c[8]=s[1];
15:c[7]=s[2];
16:c[6]=s[3];
17:c[5]=s[4];
18:c[4]=s[5];
19:c[3]=s[6];
20:c[2]=s[7];...続きを読む

Aベストアンサー

char re(char *s) → void re(char *s)に変更して。

void re(char *s)
{
 char *p;
 p=s+strlen(s)-1;
 while(s<p){
  c=*s;
  *s=*p;
  *p=c;
  s++;
  p--;
 }
}

これでどうでしょうか? pの初期値は末尾の文字の位置です。
先頭と末尾の文字を順番に入れ替えながら内側に進めます。

Qint型からchar型への変換

タイトル通り、int型からchar型への変換の仕方がわかりません!><
どうしたらいいのでしょうか?

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

no = 10;
sprintf(buf, "%d", no);

Q配列の逆順コピー

for文を使って、配列xの並びを逆順にしたものを配列yにコピーするプログラムを作りたいのですがうまくいきません。どうすればよいでしょうか?
#include<iostream.h>

int main(void){
int i,j;
int x[5]={1,2,3,4,5};
int y[5];
for(i=4;i>=0;i--){
for(j=0;j<5;j++){
x[i]=y[j];
}
}
for(j=0;j<5;j++)
cout<<y[j]<<endl;
return 0;
}

Aベストアンサー

理由
・yは、まだ何も入っていません。
・2重ループで回しているのでx[i]は必ずy[4]になっています。
なので、
for(i=4;i>=0;i--){
 for(j=0;j<5;j++){
  x[i]=y[j];  ←ここ
 }
}
を、
for(i=4;i>=0;i--){
 y[4-i]=x[i];
}
に変更します。

Qpowf を使わずにべき乗を計算

組み込み系で開発しているものです。
どうしても 実数のべき乗 を使わねばならないのですが、
powf があまりに遅くて話になりません。

条件
・sinf, cosf は使ってもよい(高速なライブラリがあるので)
・指数は符号なし整数のみ(0~10000)
・底は 0.0~1.0 のみ
・戻り値も 0.0~1.0 のみ
・精度は 16bit 位で十分
・計算しておいてテーブルから呼んでもよい

自作で powf を作りたいのですが、
3時間いろいろやってみてもうまくいきませんでした。
他のやり方は無いでしょうか?

Aベストアンサー

> 対象ハードは ADSP-BF539 です。

そのプロセッサはFPUがなかったのでは?
そうであれば、主に時間が掛かっているのは浮動小数点演算の部分かと思います(ソフトエミュレーションなので)。

というわけで、#2さんのアルゴリズムで、固定小数点演算を行えばかなり改善するはずです。
固定小数点演算は、加算はそのままで構いませんし、乗算は16ビット×16ビットで計算してから、適当に丸めて16ビット右シフトすればOKです。精度を上げるには、途中の計算を16ビットではなく20ビットにしてもよいでしょう(40ビット整数型が使えるはずなので)。

Qこの言葉遣いは正しいですか?

志望動機を書く際に、
「~だと思ったので志望しました。」という表現は適切ですか?
思った"ので"というところが、少し気になります。
思ったため、とか感じたため、の方が良いのでしょうか。

Aベストアンサー

こんにちは。

採用などで多く志望理由など拝見してきた者に過ぎません。

NO1の回答者の方の通りかとおもいました。

同じように前の部分が分からないので断言できませんが「○○と思い志望しました」や「○○と考え志望しました」など数えあげればキリがない面もあるかと思います。

「○○と思い志望に至った次第です」など書き方も考え出すと入れ替えなどによりいくらでも変えることはできると思います。

しかし、あまりその程度の違いで合否や印象に大きく影響を及ぼすことではないと思いますし、肝心なのは内容かと思います。

字数制限などがあると思いますので「○○と思い志望致しました」など簡潔な方が無難かと思います。

参考程度にでもなれば幸いです。

QC言語 配列の長さの上限

C言語で配列Array[N]の長さNの上限っていくらなんでしょうか?
もし可能なのであれば上限を2147483647にしたいのですが、方法を教えてください。

Aベストアンサー

そもそもWindowsの32bit版はアプリが仮想メモリ空間を2GBしか使えません。2GBを超えるには64bit版が必要です。
たとえ64bit版OSだとしても添え字が2147483647って、単純なintの配列だとしても4x2147483647=8GB必要ですね。実メモリ16GBとかのPCを用意しますか?
そもそも配列で2147483647個必要なアルゴリズムに問題ありだと思います。


人気Q&Aランキング