5

私は次のように暗号化していますが、大文字が範囲外にシフトされた場合に他の記号に入るのを防ぐ方法がわかりません。同様に、小文字は小文字の範囲外になります。どうすれば円を描いてオーバーフローを止めることができますか? ありがとう

    int size = strlen(plain_text);
int arrayelement = 0;
for(arrayelement = 0; arrayelement < size; arrayelement++)
{
    if (islower(plain_text[arrayelement]))
    {
        ciphered_text[arrayelement] = (int)(plain_text[arrayelement] + shiftkey);
    }
    else if (isupper(plain_text[arrayelement]))
    {
        ciphered_text[arrayelement] = (int)(plain_text[arrayelement] + shiftkey);
    }
}

ciphered_text[size] = '\0';
printf("%s", ciphered_text);
4

4 に答える 4

1

char のような型を使用していると思いますので、オーバーフローしない簡単な解決策は

int tmp_ciphered = (my_char + shift) % 0xff;
char ciphered = (char)(tmp_ciphered);

それからあなたは回して溢れないで、これはリングです

于 2012-11-15T23:20:03.970 に答える
1

これは、(ほぼ正確に) c++ の単純なシーザー暗号アルゴリズムを複製します。

その投稿で受け入れられた回答に同意しないことに注意してください。基本的に、((c-'a'+shift) % 26) + 'a' のようなものを使用して、文字を範囲に戻す必要があります。ただし、文字が「a」..「z」にあることを前提としています。英語以外のシステムでロケールがどのように機能するかわからないため、 islower の代わりに c >= 'a' && c <= 'z' を使用する方が安全かもしれません。isupper と他の範囲についても同様です。最後に、char がどちらの範囲にもない場合に処理するために、else 句が必要です。

于 2012-11-15T23:20:29.120 に答える
1

これを行うための真に移植可能な唯一の方法は、入力ドメインのルックアップ テーブルを構築し、非線形の仮定に基づいて手動で文字を構築することです。

の制限されたドメインであっても、['a'..'z','A'..'Z']「A」..「Z」が連続していると仮定することは、言語標準によって定義されておらず、常にそうであるとは限りません。そうでないと考える否定論者のために、想定されるシーケンスの真ん中にあるデッドゾーンに細心の注意を払いながら、このリンクのチャート内の文字の順序位置を案内します. 「もう誰も EBCDIC を使用していない」と思われる場合は、AS/400 と OS/390 の両方が正常に機能していることを保証させてください (IRS は IBM の最大の顧客の 1 つであるため、おそらく現在、米国の税金を処理しています)。

実際、C 標準はこれについてかなり明示的です。

C99-5.2.1.3ソースと実行の両方の基本文字セットで、上記の 10 進数のリストで 0 の後の各文字の値は、前の値よりも 1 大きくなければなりません。

文字セットの他の部分で定義された順序付けや暗黙の順序付けについての言及さえどこにもありません。実際に'0'..'9'は、もう 1 つの固有の属性があります。ロケールの変更によって影響を受けないことが保証されている唯一の文字です。

したがって、標準の疑わしい沈黙に鼻を鳴らしながら、キャラクターに線形の継続が存在すると仮定するのではなく、独自のハードマップを定義しましょう. ここでは、通常のようにコードをインライン化しません。あなたがまだ私と一緒にいるなら、あなたは本当に知りたいと思っており、おそらく以下のコードを読んで批評するでしょう. しかし、それがどのように機能するかを要約して説明します。

  1. 2 倍の長さの 2 つのアルファベットを静的に宣言します (A..ZA..Z、a..za..z)。
  2. (1<<CHAR_BIT)エントリを保持するのに十分な大きさの 2 つの配列 (暗号化と復号化) を宣言します。
  3. インデックスに対応する値で両方の配列を完全に初期化します。例: a[0]=0a[1]=1、...
  4. (1) のアルファベットの一部である暗号化配列の各位置に、シフト幅 Ex に対応する適切な値を入力します。a['a'] = 'g'ROT5の場合。
  5. 反対のシフト方向を適用して、アルファベットの末尾から逆方向に作業することにより、(4) をミラーリングします。例: `a['g'] = 'a';

暗号化配列を単純なテーブルとして使用して、入力テキストを暗号化テキストに変換できるようになりました。

enc-char = encrypt[ dec-char ];
dec-char = decrypt[ enc-char ];

ソースレベルのプラットフォームの独立性を確保するだけでも大変な作業のように思えるとしたら、その通りです。しかし、人々が「マルチプラットフォーム」として偽装しようとする#ifdef #endif地獄に驚かれることでしょう。プラットフォームに依存しないコードの主な目標は、共通ソースを定義するだけでなく、動作も定義することです。プラットフォームが何であれ、上記の概念は機能します。(そして、見えない #ifdef ではありません)。

この大失敗を読んでくれてありがとう。一見簡単そうに見える問題...


サンプル main.cpp

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

// global tables for encoding. must call init_tables() before using
static char xlat_enc[1 << CHAR_BIT];
static char xlat_dec[1 << CHAR_BIT];

void init_tables(unsigned shift)
{
    // our rotation alphabets
    static char ucase[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
    static char lcase[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
    int i=0;

    // ensure shift is below our maximum shift
    shift %= 26;

    // prime our table
    for (;i<(1 << CHAR_BIT);i++)
        xlat_enc[i] = xlat_dec[i] = i;

    // apply shift to our xlat tables, both enc and dec.
    for (i=0;i<(sizeof(ucase)+1)/2;i++)
    {
        xlat_enc[ lcase[i] ] = lcase[i+shift];
        xlat_enc[ ucase[i] ] = ucase[i+shift];
        xlat_dec[ lcase[sizeof(lcase) - i - 1] ] = lcase[sizeof(lcase) - i - 1 - shift];
        xlat_dec[ ucase[sizeof(ucase) - i - 1] ] = ucase[sizeof(ucase) - i - 1 - shift];
    }
}


// main entrypoint
int main(int argc, char *argv[])
{
    // using a shift of 13 for our sample
    const int shift = 13;

    // initialize the tables
    init_tables(shift);

    // now  drop the messsage to the console
    char plain[] = "The quick brown fox jumps over the lazy dog.";
    char *p = plain;
    for (;*p; fputc(xlat_enc[*p++], stdout));
    fputc('\n', stdout);

    char cipher[] = "Gur dhvpx oebja sbk whzcf bire gur ynml qbt.";
    p = cipher;
    for (;*p; fputc(xlat_dec[*p++], stdout));
    fputc('\n', stdout);

    return EXIT_SUCCESS;
}

出力

Gur dhvpx oebja sbk whzcf bire gur ynml qbt.
The quick brown fox jumps over the lazy dog.
于 2012-11-16T07:44:25.063 に答える
0

文字通り実装できます:

「それらが範囲外にシフトされた場合」:

if (ciphered_text[arrayelement] > 'z')

「円を描いてオーバーフローを止める」:

ciphered_text[arrayelement] -= 26;

あなたの文脈では:

if (plain_text[arrayelement] >= 'a' && plain_text[arrayelement] <= 'z')
{
    ciphered_text[arrayelement] = (int)(plain_text[arrayelement] + shiftkey);
    if (ciphered_text[arrayelement] > 'z')
        ciphered_text[arrayelement] -= 26;
}

(ACSII エンコーディングで英語のテキストを扱ってshiftkeyおり、その範囲が 1 ~ 25 であると仮定します)

于 2012-11-18T13:48:19.010 に答える