Содержимое строки изменяется при выходе из цикла - PullRequest
2 голосов
/ 20 августа 2010

У меня есть простая функция, которая проверяет, соответствуют ли данные строки определенному условию, а затем генерирует 3-ю строку на основе 2-х, полученных в качестве аргументов. 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;

В for sReturn все в порядке и имеет правильное содержимое, но как только он существует в цикле, отладчик неожиданно сообщает мне, что его содержимое "\n". Что я делаю не так?

Ответы [ 4 ]

3 голосов
/ 20 августа 2010
  1. Вам не нужно инициализировать строку с пустым массивом символов, например:

    std::string sReturn = "";
    

    Конструктор по умолчанию предназначен для этого для вас и гораздо эффективнее. Правильный код:

    std::string sReturn;
    
  2. Назначение пустой строки для sReturn на каждой итерации в вашем цикле неверен. Не говоря уже о том, чтобы очистить строку, которую вы должны позвонить std :: string :: clear () :

    sReturn = "";
    

    Правильный код:

    sReturn.clear (); 
    

    Но это должно быть удалено из петля вообще в вашем случае.

  3. Нет необходимости явно преобразовать результат оператора [] (size_t) в символ, потому что это это персонаж:

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

    Правильный код:

    sReturn += sText[foo] ^ sPassword[foo];
    
  4. Использование постинкремент в течение петля не нужна. Это делает дополнительная копия "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-разрядном целом числе со знаком поскольку у него недостаточно возможностей для хранить большое количество. Правильный тип size_t, который возвращается Метод std :: string :: size ().

Учитывая все вышесказанное, правильная функция должна выглядеть примерно так:

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;
}

Но есть проблема, если вы хотите, чтобы последняя строка была удобочитаемой. Использование оператора eXclusive OR (XOR) для двух символов ASCII может дать, а может и не дать вам читаемый символ или даже символ ASCII . Таким образом, вы можете получить результирующую строку, содержащую символы новой строки, нечитаемые символы, некоторые мусор .

Чтобы решить эту проблему, вы должны придумать лучший алгоритм для генерации строки на основе двух других строк. Например, вы можете использовать MD5 хэш обеих строк или кодировать их в base64 .

Удачи!

3 голосов
/ 20 августа 2010

Почему у вас sReturn = "" внутри петли. Разве это не должно быть инициализировано перед циклом?

В данном случае sReturn будет иметь только один символ. В вашем случае я бы предположил, что операция ^ приводит к символу \ n на последней итерации.

2 голосов
/ 20 августа 2010
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;

Я переписал его сейчас, используя все советы. Я прошу прощения за ошибку, вызванную нехваткой внимания - очистка строки каждый раз, когда я пробегаю цикл. Я надеюсь, что теперь все в порядке, пожалуйста, скажите мне, если что-то не так с этим. Спасибо всем за оперативные ответы.

2 голосов
/ 20 августа 2010

Вам уже объяснили проблему.Я предложу совершенно другой способ сделать то, что, как мне кажется, исключает большую вероятность появления аналогичной ошибки.Во-первых, я бы отделил часть «проверка соответствия текстов условию» от части «кодирование».Прямо сейчас у вас есть один (довольно маленький) код, который, кажется, имеет две, в основном несвязанные, обязанности.

Кодирующая часть, я бы написал что-то вроде этого:

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());
...