2

我有一个简单的函数,它检查给定的字符串是否符合某个条件,然后根据作为参数接收的 2 个字符串生成第三个字符串。第三个字符串很好,但是当我返回它时它突然变成“ \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,只会有一个字符。在您的情况下,我会假设 ^ 操作在最后一次迭代中产生一个 \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 位有符号整数,因为它没有足够的容量来存储大量数字。正确的类型是 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;
}

但是,如果您希望最终的字符串是人类可读的,就会出现问题。在两个ASCII字符上使用异或(XOR) 运算符可能会或可能不会给您人类可读的字符,甚至是ASCII字符。因此,您最终可能会得到包含换行符、不可读字符、一些垃圾的结果字符串。

为了解决这个问题,你必须想出一些更好的算法来根据另外两个字符串生成一个字符串。例如,您可以使用两个字符串的MD5哈希或将它们编码为base64

祝你好运!

于 2010-08-20T16:20:15.493 回答
2

您已经解释了问题。我会建议一种完全不同的做事方式,我认为这种方式可以消除产生类似错误的大部分可能性。首先,我将“检查文本是否符合条件”部分与“编码”部分分开。现在,你有一个(相当少的)代码似乎有两个大部分不相关的职责。

编码部分,我会写这样的东西:

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 回答
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 回答