You have not resized your altered line to fit the length of the original line before the loop, so your code shows undefined behavior:
altered[i] = original[i] + 5; // UB - altered is empty
To fix this, resize altered before the loop:
altered.resize(original.size());
Or use std::string::operator+= or similar to adding to altered :
altered += original[i] + 5;
Thus, it may be empty before the loop, it will automatically resize to contain the added characters.
Explanation
The way UB happens here is that you can write data to a static array that std::string uses to optimize short strings ( std::string::operator[] does not check if you access this array by std::string::size() ), but std::string::size() remains 0 , and also std::string::begin() == std::string::end() .
To do this, you can access the data separately (again, using UB):
cout << altered[0] << " " << altered[1] << " " << altered[2] << endl;
but cout << aligned does not print anything, since the definition of a simplified operator<< for std::string looks functionally as follows:
std::ostream &operator<<(std::ostream &os, std::string const& str) { for(auto it = str.begin(); it != str.end(); ++it)
In one sentence, std::string does not know what you did with its base array, and what you meant that the string should increase in length.
In conclusion, the <algoritm> way to do this conversion is:
std::transform(original.begin(), original.end(), std::back_inserter(altered), // or altered.begin() if altered was resized to original length [](char c) { return c + 5; }
(required headers: <algorithm> , <iterator> )