按索引更改字符串

the*_*dor 5 c++ string

我是C++的初学者,目前我正在使用字符串.

我的问题是为什么在编译我在下面提供的代码时,我可以在使用索引表示法时获取字符串的字符,但是无法使用字符串本身cout

这是代码:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string original; // original message
    string altered; // message with letter-shift

    original = "abc";
    cout << "Original : " << original << endl; // display the original message

    for(int i = 0; i<original.size(); i++)
        altered[i] = original[i] + 5;

    // display altered message
    cout << altered[0] << " " << altered[1] << " " << altered[2] << endl;
    cout << "altered : " << altered << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我运行它时,字符串altered中的字符使用以下行正确显示:

cout << altered[0] << " " << altered[1] << " " << altered[2] << endl;
Run Code Online (Sandbox Code Playgroud)

但字符串本身不会显示此行:

cout << "altered : " << altered << endl;
Run Code Online (Sandbox Code Playgroud)

我想知道为什么会这样.

Log*_*uff 5

您没有调整altered字符串的大小以适应original循环之前字符串的长度,因此您的代码显示未定义的行为:

altered[i] = original[i] + 5; // UB -  altered is empty
Run Code Online (Sandbox Code Playgroud)

要解决此问题,请altered在循环之前调整大小:

altered.resize(original.size());
Run Code Online (Sandbox Code Playgroud)

或使用std::string::operator+=或类似附加到altered:

altered += original[i] + 5;
Run Code Online (Sandbox Code Playgroud)

这样,它在循环之前可以为空,它会自动调整自身大小以包含附加字符.


说明

UB这里发生的一切的办法,就是你在静态数组,在写入数据成功std::string为短字符串优化使用(std::string::operator[]不进行任何检查,如果你访问这个数组过去std::string::size()),但std::string::size()0,以及std::string::begin() == std::string::end().

这就是你可以单独访问数据的原因(同样,使用UB):

cout << altered[0] << " " << altered[1] << " " << altered[2] << endl;
Run Code Online (Sandbox Code Playgroud)

cout << aligned不打印任何东西,考虑到功能上简化 operator<<std::string外观定义如下:

std::ostream &operator<<(std::ostream &os, std::string const& str)
{
    for(auto it = str.begin(); it != str.end(); ++it) // this loop does not run
        os << *it;

    return os;
}
Run Code Online (Sandbox Code Playgroud)

在一个句子中,std::string不知道你对它的底层数组做了什么,并且你的意思是字符串长度增长.


总而言之,<algoritm>这种转变的方式:

std::transform(original.begin(), original.end(),
    std::back_inserter(altered), // or altered.begin() if altered was resized to original's length
    [](char c)
    {
        return c + 5;
    }
Run Code Online (Sandbox Code Playgroud)

(必填标题:<algorithm>,<iterator>)