2016-12-29 28 views
3

ので、配列内の特定の文字です:ループ内replace(str.begin(), str.end(), arrX[1], arrY[1])文字列に別の配列から文字を置き換え

for (int i = 0; i < arraySize; i++) { 
    replace(str.begin(), str.end(), arrX[i], arrY[i]); 
} 

しかし、私のコードで:

#include <iostream> 
#include <algorithm> 
#include <iostream> 
#include <string> 
using namespace std; 

string Caesar(string str) { 
    char alph[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; 
    string caesar = "abcdefghijklmnopqrstuvwxyz"; 
    const int arraySize=sizeof(alph)/sizeof(alph[0]); 
    rotate(caesar.begin(), caesar.begin()+3, caesar.end()); 
    for (int i = 0; i < arraySize; i++) { 
    replace(str.begin(), str.end(), alph[i], caesar[i]); 
    } 
    return str; 
} 
int main() { 
    cout << Caesar("hello"); 
} 

シーザー文字列は3によって回転ALPHです。

シーザーを出力すると、期待される結果が得られます。 (abcdef ...はxyzabcになります)。

私のループは、helloが与えられたときにそれがつぶれているようです。ccaaaを生成します。私は1通の手紙を取り替えてテストしましたが、それはうまくいっていますが、私のループの問題は何かと思われますが、何が間違っているのか分かりません。

UPDATE:私はそれをアルファベットで、その後、彼らまでの文字列に文字に各文字を比較するアルファベットを経由するかどうかを確認するwhileループを使用して、非アルファベット文字をサポートし、それを行う方法を見つけた

一致していない場合は、回転したシーザーアルファベットで置き換えます。一致しない場合は次の文字に移動し、見つかった場合は 'j'を0にリセットします。 charが文字でない場合、新しい文字または文字列の終わりに達するまで、それをスキップするだけの次の文字に 'i'を増加させます。

#include <iostream> 
#include <algorithm> 

using namespace std; 

bool IsInArray(string array, char element) { 
    for(int i = 0; i < array.length(); i++){ 
    if(array[i] == element){ 
     break; 
    } 
    } 
} 
string rot(int n, string str) { 
    transform(str.begin(), str.end(), str.begin(), ::tolower); 
    string alph = "abcdefghijklmnopqrstuvwxyz"; 
    string ciph = alph; 
    rotate(ciph.begin(), ciph.begin() + n, ciph.end()); 

    int i = 0; 
    int j = 0; 
    while (i < str.length()) { 
    if (IsInArray(alph, str[i])) { 
     if (str[i] == alph[j]) { 
     str[i] = ciph[j]; 
     i++; 
     j = 0; 
     } 
     else { 
     j++; 
     } 
    } 
    else { 
     i++; 
    } 
    } 
    return str; 
} 

int main() { 
    cout << rot(2, "This cipher works with more than just alpha chars!"); 
    return 0; 
} 
+1

*私はそれが動作することを確認しました。*これは、私たちが必要とするものとは逆です - [mcve]。また、 'char caesar [arraySize];'これは有効なC++構文ではありません。配列は可変ではなく、コンパイル時の境界が明記されていなければなりません。 'arraySize'を' const int arraySize = ... 'に変更してください。そして、なぜあなたは 'itRemove'関数の代わりに' std :: rotate'を使用するだけで、本当に "動く"と確信しているのですか? – PaulMcKenzie

+3

ループをステップ実行します。 「e」を「h」で置き換えてください。あなたの文字列は「hhllo」になります。しかし、あなたはすべての 'h'を 'k'で置き換えることができます。あなたは手紙が1回だけ置き換えられることを確認する必要があります。 –

+0

@JohnnyMoppああ明らかに、多くのおかげさまですが、これをどうやってやるのですか? – Lamb

答えて

1

ここでは標準機能とラムダ関数使用してそれを行うための一つの方法です:

string Caesar(std::string str) { 
    std::string caesar = "abcdefghijklmnopqrstuvwxyz"; 
    std::rotate(caesar.begin(), caesar.end()-3, caesar.end()); 
    std::transform(str.begin(), str.end(), str.begin(), 
     [caesar](char c) -> char { return caesar[c - 'a']; }); 
    return str; 
} 

注:これは、インデックスを取得するために文字コードを使用していますので、それは何かを処理するために変更しなければなりません"abc ... xyz"以外。

1

最適化:小文字のa-zだけを使用している場合は、2つの配列を使用せずに、関数leftRotatebyOneを使用せずに行うことができます。代わりに、ASCII値を使用します。

std::string Caesar(std::string str){ 
    int delta = 'z' - 'a' + 1; 
    int rotateBy = 3; 
    for(int i = 0; i < str.length(); i++){ 
     char c = str[i] - rotateBy; 
     if(c < 'a') 
      c += delta; 
     str[i] = c; 
    } 
    return str; 
} 
関連する問題