用一个 space 反转字符串

Reverse string with one space

我需要反转字符串,但要在单词之间只保留一个 space。

示例:

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

代码:

#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;
}

输出:

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

为什么我的字符串反转后多了一些字符?

在你的两个 while 循环中,你都 运行 出界了。变量i最后会是“-1”。

请将 while 循环中的条件从 >= 更改为 >

其他原因可能是一些设计问题。永远不要用其他语句更改循环体内的循环变量(此处i)。

#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;
}

你也可以试试我的代码,我正在使用 reverse 函数,所以我不需要从后面循环字符串

#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;
}

代码将像这样打印到终端

"!!!aadrm aabrv adrb hrv an"
"!!!aadrm aabrv adrb hrv an"

另一个解决方案是使用 C++ 库中可用的内容:

  1. 使用 std::istringstream 无需检查 space 秒。
  2. 使用std::reverse会自动反转字符串。

将这些放在一起产生以下程序:

#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;
}

输出:

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

请注意,没有检查 spaces。手动检查 spaces 是 error-prone,至少大部分时间是在第一次尝试编写此类代码时。那么,如果有东西(在本例中为 std::istringstream)可以为您进行 space 检查,为什么还要浪费时间呢?