2

与えられた文字列が特定の条件に一致するかどうかをチェックし、引数として受け取った 2 つの文字列に基づいて 3 番目の文字列を生成する単純な関数があります。3弦は大丈夫なのですが、戻すといきなり「\n」になってしまいます。

string sReturn = "";
if (sText.size() != sPassword.size()) {
     //Checks to see if the texts match a condition
     return sReturn;
}
for (int foo = 0; foo < sText.size(); foo++) {
    sReturn = "";
    sReturn += (char)sText[foo] ^ (char)sPassword[foo];
}
return sReturn;

forsReturnは問題なく、正しい内容を持っていますが、ループが存在するとすぐに、デバッガーは突然、内容が " \n" であると通知します。私は何を間違っていますか?

4

4 に答える 4

3

なぜあなたはループのsReturn = "" 中にいるのですか?ループの前に初期化するべきではありませんか?

この場合、sReturn文字は1つだけになります。あなたの場合、^操作は最後の反復で\n文字になると思います。

于 2010-08-20T15:50:54.690 に答える
3
  1. 次のように、空の文字配列で文字列を初期化する必要はありません。

    std::string sReturn = "";
    

    デフォルトのコンストラクターは、あなたのためにそれを行うことを意図しており、はるかに効率的です。正しいコード:

    std::string sReturn;
    
  2. ループの各反復で空の文字列を sReturn に割り当てるのは正しくありません。文字列をクリアするには、 std::string::clear ()を呼び出す必要があることは言うまでもありません 。

    sReturn = "";
    

    正しいコード:

    sReturn.clear (); 
    

    しかし、あなたの場合、これはループから完全に削除する必要があります。

  3. operator [] (size_t) の結果は文字であるため、明示的に文字に変換する必要はありません。

    sReturn += (char)sText[foo] ^ (char)sPassword[foo];
    

    正しいコード:

    sReturn += sText[foo] ^ sPassword[foo];
    
  4. for ループでポスト インクリメントを使用する必要はありません。インクリメントごとに「foo」の余分なコピーを作成します。

    for (int foo = 0; foo < sText.size(); foo++)
    

    これはおそらくコンパイラによって最適化されるでしょうが、この悪い習慣を取り除く必要があります。代わりにプレインクリメントを使用 してください。正しいコード:

    for (int foo = 0; foo < sText.size(); ++foo)
    
  5. 文字列のサイズが変わらない場合に反復ごとに std::string::size () を呼び出すのは効率的ではありません。

    for (size_t foo = 0; foo < sText.size(); ++foo)
    

    より良いコード:

    for (size_t foo = 0, end_foo = sText.size(); foo < end_foo; ++foo)
    

    size_t タイプに注意してください。大きな数を格納するのに十分な容量がないため、文字列サイズを 32 ビットの符号付き整数に格納することはできません。正しい型は、std::string::size () メソッドによって返される size_t です。

上記のすべてを考慮すると、正しい関数は次のようになります。

std::string
getMixedString (const std::string & text, const std::string & password)
{
    std::string result;
    if (text.length () != password.length ())
        return result;
    for (size_t pos = 0, npos = text.length (); pos < npos; ++pos)
        result += text[pos] ^ password[pos];
    return result;
}

しかし、最終的な文字列を人間が読めるようにしたい場合は問題があります。2 つのASCII文字で排他的 OR (XOR) 演算子を使用すると、人間が判読できる文字またはASCII文字でさえも得られる場合と得られない場合があります。そのため、改行、判読できない文字、何らかのゴミを含む結果の文字列が得られる可能性があります。

これを解決するには、他の 2 つの文字列に基づいて文字列を生成する、より優れたアルゴリズムを考え出す必要があります。たとえば、両方の文字列のMD5ハッシュを使用するか、base64でエンコードすることができます。

幸運を!

于 2010-08-20T16:20:15.493 に答える
2
string sReturn;
if (sText.size() != sPassword.size()) {
        return sReturn;
}
for (size_t foo = 0, end_foo = sText.size(); foo < end_foo; ++foo) {
        sReturn += sText[foo] ^ sPassword[foo];
}
return sReturn;

皆さんのアドバイスを参考に今書き直しました。ループを実行するたびに文字列をクリアするという、注意の欠如によって引き起こされた間違いをお詫びします。今は大丈夫だと思いますが、何か問題があれば教えてください。迅速な回答をありがとうございました。

于 2010-08-20T16:55:50.180 に答える
2

あなたはすでに問題を説明しました。同様の間違いを引き起こす可能性をほとんど排除すると思われる、まったく異なる方法を提案します。まず、「テキストが条件に一致するかどうかを確認する」部分と「エンコードする」部分を分けます。現在、ほとんど無関係な 2 つの責任があると思われる 1 つの (かなり小さい) コードがあります。

エンコード部分は、次のように書きます。

struct encode_byte { 
    char operator()(char a, char b) { 
        return a ^ b;
    }
};

std::transform(sText.begin(), sText.end(),
               sPassword.begin(), sPassword.end(),
               std::back_inserter(sResult),
               encode_byte());
于 2010-08-20T16:45:58.620 に答える