该函数返回空字符串

时间:2019-05-01 17:40:12

标签: c++ string

在下面的代码reverse中,

返回一个空字符串。没有编译错误。

什么在这里会引起问题?

#include <iostream>
#include <bits/basic_string.h>
using namespace std;

string reverse(string str) { 
    string r;

    for (int i=str.length()-1; i>=0; i--) {
        r[str.length() - 1 - i] = str[i];  
    }

    return r;
} 

int main() {
    string str = "ABCDefgh";

    cout<<"Reverse string is : "<<reverse(str)<<endl;

    return 0;
}

编辑: r [str.length()-i] = str [i];
r [str.length()-1-i] = str [i];

1 个答案:

答案 0 :(得分:10)

您的函数正在调用未定义的行为,因为在使用r运算符将字符分配给[]之前,您没有为r字符串分配任何内存。 std::string::operator[]不执行任何边界检查,因此实际上您在浪费周围的内存。另外,您也没有正确地索引到r中(索引偏离了1)。

如果您使用std::string::at()方法而不是operator[],则会引发运行时异常,抱怨您无法访问字符。

首先需要对输入str进行拷贝,然后可以反转该拷贝的字符,例如:

std::string reverse(std::string str) { 
    std::string r = str; // <-- COPY HERE

    for (int i = str.length()-1, j = 0; i >= 0; --i, ++j) {
        r[j] = str[i];  
    }

    return r;
} 

或者,您可以使用std::string::resize()方法来预先分配r字符串,然后使用operator[]将是有效的:

std::string reverse(std::string str) { 
    std::string r;
    r.resize(str.length()); // <-- ALLOCATE HERE

    for (int i = str.length()-1, j = 0; i >= 0; --i, ++j) {
        r[j] = str[i];  
    }

    return r;
} 

或者,您可以改用std::string::push_back()方法((可选地与std::string::reserve()方法一起使用,以避免在推送时重新分配):

std::string reverse(std::string str) { 
    std::string r;
    r.reserve(str.length()); // <-- OPTIONAL

    for (int i = str.length()-1; i >= 0; --i) {
        r.push_back(str[i]);  
    }

    return r;
} 

或者,看看用std::reverse_copy()算法代替您的手动循环:

#include <algorithm>

std::string reverse(std::string str) { 
    std::string r;
    r.resize(str.length());
    std::reverse_copy(str.begin(), str.end(), r.begin());
    return r;
} 
#include <algorithm>
#include <iterator>

std::string reverse(std::string str) { 
    std::string r;
    r.reserve(str.length()); // <-- OPTIONAL
    std::reverse_copy(str.begin(), str.end(), std::back_inserter(r));
    return r;
} 

但是,由于输入str是通过值传递 的,因此,它已经是传递给函数的任何字符串的副本,因此实际上完全需要本地r字符串。您可以就地反转输入str的字符,只是要考虑到源字符串和目标字符串是相同的字符串,因此请相应地调整循环:

std::string reverse(std::string str) { 
    int count = str.length() / 2;
    for (int i = 0, j = str.length()-1; i < count; ++i, --j) {
        char ch = str[i];
        str[i] = str[j];
        str[j] = ch;

        // alternatively:
        // std::swap(str[i], str[j]);
    }

    return str;
} 

或者,请改用std::reverse()算法:

#include <algorithm>

std::string reverse(std::string str) { 
    std::reverse(str.begin(), str.end());
    return str;
} 

或者,您可以使用将两个迭代器作为输入的std::string构造函数,因为std::string具有reverse iterators可用:

std::string reverse(std::string str) { 
    return std::string(str.rbegin(), str.rend());
}