按索引更改字符串 [英] Change string by index

查看:58
本文介绍了按索引更改字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆