1

I've been doing some C++ challenges to get into coding, and I came across this when I tried to create a function that reversed a string. for some reason assigning result[i] to str[str.length() - i] doesn't work, but assigning str[str.length() - i] to holding and then holding to result[i] does. Can anyone explain this?

//this works
std::string reverse(std::string str){
     std::string result;
     char holding;
     for(uint i = 0; i <= str.length(); i++){
         holding = str[str.length() - i];
         result += holding;
     }
     return result;
}
//this doesn't
std::string reverse(std::string str){
     std::string result;
     for(uint i = 0; i <= str.length(); i++){
         result[i] = str[str.length() - i];
     }
     return result;
}   
  • 1
    The size of `result` is 0. Accessing `result[i]` causes undefined behavior. – Thomas Sablik Jul 30 '20 at 11:24
  • 3
    "Doing some C++ challenges to get into coding" is not the best way to learn C++. The best way to learn C++ [is with a good C++ textbook](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list), which explains these kinds of fundamental rules of C++. The book will, for example, explain why assigning a character to some index of an empty string results in a crash, but the `+` operator overload actually does the right thing, and increases the size of the string. The explanation for this is found only in a C++ textbook, and not a pointless online coding competition site. – Sam Varshavchik Jul 30 '20 at 11:26
  • What does "doesn't work" mean? – nicomp Jul 30 '20 at 11:27
  • Does this answer your question? [why cout is not printing this string?](https://stackoverflow.com/questions/62970070/why-cout-is-not-printing-this-string) – Thomas Sablik Jul 30 '20 at 11:32

5 Answers5

3

result is an empty string. Assigning anything other than result[0] = '\0' will have undefined behaviour.

but assigning str[str.length() - i] to holding and then holding to result[i] does.

You aren't assigning to result[i] in the working example. It works because instead of assigning a non-existing character, you use the compound assignment operator += which performs concatenation into the end of the string.


P.S. There is a function in the standard library for reversal. Or you could just use reverse iterators.

eerorika
  • 232,697
  • 12
  • 197
  • 326
3

The size of result is 0. Accessing result[i] causes undefined behavior in nearly all cases. You can preallocate the needed memory with

std::string reverse(std::string str){
     std::string result(str.length(), '\0');
     for(uint i = 0; i < str.length(); i++){
         result[i] = str[str.length() - i - 1];
     }
     return result;
} 
Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62
0

The lenght of result is 0. please use resize fuction or like this:

std::string reverse(std::string str){
     std::string result = str; // temp value
     for(uint i = 0; i < str.length(); i++){
         result[i] = str[str.length() - i - 1];
     }
     return result;
} 
Albert
  • 29
  • 1
  • 5
  • When `i == str.length()` you'll write to `result[result.length()]`. Undefined behavior. – Ted Lyngmo Aug 13 '20 at 17:41
  • @Ted Lyngmo I fixed it. When `i == 0`, the code generate undefined behavior, Not `i == str.length()`. – Albert Aug 14 '20 at 03:34
  • Good - Now your algorithm is the same as Thomas Sabliks (except that his way of initializing `result` is probably a little more effective). Regarding the UB: No, when `i` was `0` the only thing that happend was that you read from `str[str.length()]` and wrote to `result[0]` none of it is UB. When `i` was `str.length()` you read from `str[0]` (ok) and wrote to `result[result.length()]` which is not ok - unless you write a `\0` which is unlikely. – Ted Lyngmo Aug 14 '20 at 06:15
0

Am assuming you are coming from a language like javascript where you can assign any index of an array and the system will aquire memory for it in the background. C++ is much less free in that regard. You either have to give the string a size (so it reserves memory) to assign data later to each index, or use some method that extends the string (such a method is called when doing += on it). The later case re-aquires fresh memory every time by the way and copies the contained characters over which is not ideal from a performance viewpoint.

AlexGeorg
  • 967
  • 1
  • 7
  • 16
-1

The second snippet of code is not working because the string has just declared and only the default constructor is called on that string, and according to documentation, the default size of the string is 0, due to which, when you are writing this line
result[i] = str[str.length() - i];
(correct line should be result[i] = str[str.length() - i - 1];)
You will receive an out of index error which is obvious because the string size is 0.
see this.
working code->

std::string reverse(std::string str){
     std::string result(str);
     for(uint i = 0; i < str.length(); i++){
         result[i] = str[str.length() - i-1];
     }
     return result;
} 
dukeforever
  • 298
  • 1
  • 7
  • When `i == str.length()` you'll read from `str[-1]` and write at `result[result.length()]` so your function has undefined behavior (twice). – Ted Lyngmo Aug 13 '20 at 17:41