按索引更改字符串 [英] Change string by index
问题描述
我是C ++的初学者,目前正在使用字符串.
I am a beginner in C++ and I am currently working with strings.
我的问题是为什么在编译我在下面提供的代码时,使用索引符号时可以获取字符串的字符,但不能使用 cout
来获取字符串本身?
My question is why when compiling the code I'm providing below, I can get the string's characters when I use index notation, but cannot get the string itself using 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;
}
当我运行此命令时,字符串 altered
中的字符在此行中正确显示:
When I run this, the characters in the string altered
are displayed correctly with this line:
cout << altered[0] << " " << altered[1] << " " << altered[2] << endl;
但是字符串本身不显示以下行:
But the string itself is not displayed with this line:
cout << "altered : " << altered << endl;
我想知道为什么会这样.
I would like to know why this happens.
推荐答案
在循环之前,您尚未调整更改的
字符串的大小以适应原始
字符串的长度,因此您的代码表现出未定义的行为:
You have not resized your altered
string to fit the length of the original
string before the loop, thus your code exhibits undefined behavior:
altered[i] = original[i] + 5; // UB - altered is empty
要解决此问题,请在循环前调整更改的
的大小:
To fix this, resize altered
before the loop:
altered.resize(original.size());
或使用 std :: string :: operator + =
或类似的内容附加到更改的
:
Or use std::string::operator+=
or similar to append to altered
:
altered += original[i] + 5;
这样,它可以在循环之前为空,它将自动调整其大小以包含附加字符.
This way, it can be empty before the loop, it will automatically resize itself to contain appended characters.
UB在这里发生的方式是,您已成功将数据写入静态数组中, std :: string
用于短字符串优化( std :: string:: operator []
不会检查您是否在 std :: string :: size()
)之后访问此数组,但是会检查 std :: string :: size()
保留为 0
,以及 std :: string :: begin()== std :: string :: end()
.
The way UB is happening here, is that you're succeeding in writing the data in the static array, which std::string
uses for short string optimization (std::string::operator[]
does no checks if you're accessing this array past the std::string::size()
), but std::string::size()
remains 0
, as well as std::string::begin() == std::string::end()
.
这就是为什么您可以单独访问数据(再次使用UB)的原因:
That's why you can access the data individually (again, with UB):
cout << altered[0] << " " << altered[1] << " " << altered[2] << endl;
但 cout<<考虑到 std :: string
的简化 operator<
定义在功能上 ,不会显示任何内容像这样:
but cout << aligned
does not print anything, considering simplified operator<<
definition for std::string
looks functionally like this:
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;
}
在一句话中, std :: string
并不知道您对其基础数组所做的事情,而是要使字符串的长度增加.
In one sentence, std::string
is not aware of what you did to its underlying array and that you meant the string to grow in length.
最后,使用< algoritm>
进行此转换的方法:
To conclude, <algoritm>
way of doing this transformation:
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;
}
(必需的标头:< algorithm>
,< iterator>
)
这篇关于按索引更改字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!