-1

I need to reverse string but to keep only one space between words.

EXAMPLE:

"  na vrh   brda vrbaa   mrdaa!!!   "
"!!!aadrm aabrv adrb hrv an"

Code:

#include <iostream>
#include <string>

std::string ReverseOneSpace(std::string s) {
  std::string str = s;
  int j = 0;
  for (int i = s.length() - 1; i >= 0; i--) {
    // skip spaces
    while (s[i] == ' ' && i >= 0)
      i--;
    while (s[i] != ' ' && i >= 0) {
      str[j] = s[i];
      j++;
      i--;
    }
    // add only one space
    if (s[i] == ' ') str[j] = ' ';
    j++;
    if (i == 0) break;
  }
  return str;
}
int main() {
  std::string s = "  na vrh   brda vrbaa   mrdaa!!!   ";
  std::string str = ReverseOneSpace(s);
  std::cout << "\"" << str << "\"" << std::endl;
  std::cout << "\"" << "!!!aadrm aabrv adrb hrv an" << "\"";
  return 0;
}

OUTPUT:

"!!!aadrm aabrv adrb hrv an aa!!!   " // my output
"!!!aadrm aabrv adrb hrv an" // correct

Why do I have some extra characters after the string was reversed?

Rocket Procd
  • 103
  • 10
  • `str` will always be the same length as `s`. Maybe you meant to delete some characters from the end? Probably easier though to have `str` as an empty string initially then `push_back` characters, then you don't need `j` – Alan Birtles Apr 30 '22 at 14:27
  • 1
    Have you tried running your code line by line in a debugger while monitoring the values of all variables, in order to determine at which point your program stops behaving as intended? If you did not try this, then you may want to read this: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/12149471) You may also want to read this: [How to debug small programs?](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) – Andreas Wenzel Apr 30 '22 at 14:28
  • 1
    Use four routines that do one thing, rather than one routine that does four things. You can have your swiss-army-routine call the four do-one-thing routines in order. TrimStart, TrimEnd, SqueezeSpace, and `std::reverse`. – Eljay Apr 30 '22 at 14:51
  • [You're doing too much work](http://coliru.stacked-crooked.com/a/1660cbc87a04c849). Using `std::istringstream` and `operator >>`, there is no need to check for spaces. Then the `std::reverse` reverses the string in one call, and it then becomes a simple loop that concatenates the results. – PaulMcKenzie Apr 30 '22 at 15:11

3 Answers3

1

In both of your while loop, you are running out of bounds. Variable i will be "-1" in the end.

Please change your condition in your while loops from >= to >.

Additional cause may be some design issue. You should never change the loop variable (herei) within the loop body with other statements.

#include <iostream>
#include <string>

std::string ReverseOneSpace(std::string s) {
    std::string str = s;
    int j = 0;
    for (int i = s.length() - 1; i >= 0; i--) {
        // skip spaces
        while (s[i] == ' ' && i > 0)   // ************
            i--;
        while (s[i] != ' ' && i > 0) { // ************ 
            str[j] = s[i];
            j++;
            i--;
        }
        // add only one space
        if (s[i] == ' ') str[j] = ' ';
        j++;
        if (i == 0) break;
    }
    return str;
}
int main() {
    std::string s = "  na vrh   brda vrbaa   mrdaa!!!   ";
    std::string str = ReverseOneSpace(s);
    std::cout << "\"" << str << "\"" << std::endl;
    std::cout << "\"" << "!!!aadrm aabrv adrb hrv an" << "\"";
    return 0;
}
A M
  • 14,694
  • 5
  • 19
  • 44
1

You also can try my code, I'm using reverse function so I don't need to loop the string from behind

#include<iostream>
#include<string>

using namespace std;
std::string ReverseOneSpace(std::string s) {
    bool flagSpace = false;
    bool flagWord = false;

    reverse(s.begin(), s.end());
    std::string result = "";
    for(auto c : s) {
        if (c == ' ') {
            if (flagWord) flagSpace = true;
        } else {
            flagWord = true;
        }

        if (c != ' ') {
            if (flagWord && flagSpace) {
                result += ' ';
                flagSpace = false;
                flagWord = false;
            }
            result += c;
        }
    }
    return result;
}

int main() {
    std::string s = "  na vrh   brda vrbaa   mrdaa!!!   ";
    std::string str = ReverseOneSpace(s);
    std::cout << "\"" << str << "\"" << std::endl;
    std::cout << "\"" << "!!!aadrm aabrv adrb hrv an" << "\"" << std::endl;
    return 0;
}

The code will print to the terminal like this

"!!!aadrm aabrv adrb hrv an"
"!!!aadrm aabrv adrb hrv an"
papannn
  • 23
  • 8
0

Another solution is to use what is available in the C++ library:

  1. Usage of std::istringstream removes the need to check for spaces.
  2. Usage of std::reverse will reverse the string automatically.

Putting these together results in the following program:

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>

std::string ReverseOneSpace(std::string s) 
{
    std::istringstream strm(s);
    std::string word;
    std::string ret;

    // Loop for each word found
    while (strm >> word)
    {
        // Reverse the word 
        std::reverse(word.begin(), word.end());

        // Add reversed word to front of the result string
        ret = word + " " + ret;
    }

    // Remove the excess space at the back
    ret.pop_back();

    return ret;
}

int main() {
  std::string s = "  na vrh   brda vrbaa   mrdaa!!!   ";
  std::string str = ReverseOneSpace(s);
  std::cout << "\"" << s << "\"" << std::endl;
  std::cout << "\"" << str << "\"" << std::endl;
  return 0;
}

Output:

"  na vrh   brda vrbaa   mrdaa!!!   "
"!!!aadrm aabrv adrb hrv an"

Note that there is no checking for spaces. Manually checking for spaces is error-prone, at least most of the time on the first attempt of writing such code. So why waste time doing that if there is something (in this case std::istringstream) that does the space checking for you?

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45