39

I want to change a C++ string at a particular index like this:

string s = "abc";
s[1] = 'a';

Is the following code valid? Is this an acceptable way to do this?

I didn't find any reference which says it is valid:

http://www.cplusplus.com/reference/string/string/

Which says that through "overloaded [] operator in string" we can perform the write operation.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
David
  • 4,634
  • 7
  • 35
  • 42
  • Yes, no problem at all. If you really want a reference, section 21.4.5/2 of the C++11 standard. – Jerry Coffin Aug 19 '13 at 03:08
  • 7
    Ugh. In C++11 this is actually prohibited due to a defect in the standard, and you *technically* have to use `s.begin()[ 1 ] = 'a';` But it's not worth worrying about. – Potatoswatter Aug 19 '13 at 03:10
  • And you *did* find a reference which says it is valid, although cplusplus.com is generally substandard and often outdated. Considering the link, it's unclear what else you want to know. – Potatoswatter Aug 19 '13 at 03:13
  • @Potato what's that? (Of course people would worry; what the hell were you expecting?) – R. Martinho Fernandes Aug 19 '13 at 03:14
  • @R.MartinhoFernandes It's worrisome aside from being a simple editorial defect. See http://stackoverflow.com/a/18116876/153285 – Potatoswatter Aug 19 '13 at 03:16

4 Answers4

46

Assigning a character to an std::string at an index will produce the correct result, for example:

#include <iostream>
int main() {
    std::string s = "abc";
    s[1] = 'a';
    std::cout << s;
}

For those of you below doubting my IDE/library setup, see jdoodle demo: http://jdoodle.com/ia/ljR, and screenshot: https://i.stack.imgur.com/Adav3.jpg

Which prints aac. The drawback is you risk accidentally writing to un-assigned memory if string s is blankstring or you write too far. C++ will gladly write off the end of the string, and that causes undefined behavior.

A safer way to do this would be to use string::replace: http://cplusplus.com/reference/string/string/replace

For example

#include <iostream> 
int main() { 
    std::string s = "What kind of king do you think you'll be?"; 
    std::string s2 = "A good king?"; 
    //       pos len str_repl 
    s.replace(40, 1, s2); 
    std::cout << s;   
    //prints: What kind of king do you think you'll beA good king?
}

The replace function takes the string s, and at position 40, replaced one character, a questionmark, with the string s2. If the string is blank or you assign something out of bounds, then there's no undefined behavior.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
  • 1
    The safe version would be to use string::replace http://www.cplusplus.com/reference/string/string/replace/ – Chris Aug 19 '13 at 04:55
  • With the first code snippet, I get the error "a value of type "const char *" cannot be assigned to an entity of type "char"" – danielcaballero88 Sep 25 '21 at 14:05
  • @dancab Somehow your IDE or library setup has conflated `std::string` with some kind of `const char *` arrangement. Your IDE/library setup has a problem. See the added demo and screenshot for a neutral 3rd party showing the code is correct. – Eric Leschinski Dec 20 '21 at 14:58
3

Yes. The website you link has a page about it. You can also use at function, which performs bounds checking.

http://www.cplusplus.com/reference/string/string/operator%5B%5D/

Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
  • 1
    @Potatoswatter Why? The point was the programmer could choose to use bounds checking. – Neil Kirk Aug 19 '13 at 03:18
  • @NeilKirk: I imagine it's changing because everyone just *assumed* that bounds checking was being done, and didn't know about `at()`. – cHao Aug 19 '13 at 03:20
  • 2
    @Potatoswatter a check for what? The function is either called with a valid position (accounting for *one* null terminator) or the behaviour is undefined. See Requires clause. – R. Martinho Fernandes Aug 19 '13 at 03:28
  • 2
    -1 for cplusplus.com. Seriously, that site is so shit, it's unbelievable. – Puppy Aug 19 '13 at 03:54
  • @DeadMG I linked that site because it's what the OP was using and couldn't find the page. Thanks for downvoting me. – Neil Kirk Aug 19 '13 at 03:56
  • @DeadMG What are the alternatives? I use cppreference.com, but I don't thing the content is greatly different. – nishantjr Aug 19 '13 at 04:02
  • 3
    @nishantjr I've noticed lately that the C++ community here at so has the classic RTFM responses; where the "manual" is one of the C++ standards. At least those sites _try_ (emphasis on try) and offer library documentation derived from the standards. I'm grateful the community here knows the standards (they have answered a lot of questions for me), but I do wish there was a _little_ leniency for questions/answers/comments that do not always reference the standard. – Kaiged Aug 19 '13 at 05:14
  • @R.MartinhoFernandes Oh, woops I missed that. Thanks! – Potatoswatter Aug 19 '13 at 06:39
  • 1
    @nishantjr cppreference.com is better mainly because it's a Wiki. cplusplus.com is not only closed, they don't respond to error reports and don't seem to have enough authors to stay abreast of standard updates. They also put extra emphasis on scuzzy SEO… all of which has led some of our C++ community to a boycott. – Potatoswatter Aug 19 '13 at 06:57
2

Yes the code you have written is valid. You can also try:

string num;
cin>>num;
num.at(1)='a';
cout<<num;

**Input**:asdf
**Output**:aadf

the std::replace can also be used to replace the charecter. Here is the reference link http://www.cplusplus.com/reference/string/string/replace/

Hope this helps.

Prashant Shubham
  • 456
  • 8
  • 20
0

You could use substring to achieve this

  string s = "abc";
  string new_s = s.substr(0,1) + "a" + s.substr(2);
  cout << new_s;
  //you can now use new_s as the variable to use with "aac"
Nasz Njoka Sr.
  • 1,138
  • 16
  • 27