从字符串中删除多余的空格

时间:2019-07-02 14:34:04

标签: c++

我遇到了一个有趣的练习。基本上,我必须从字符串中删除所有多余的空格,而多余的是指字符串开头,字符串结尾处的所有空格,并且连续的空格不应超过两个。

这是我尝试过的

#include <iostream>
#include <string>
using namespace std;

string RemoveSpaces(string s) {
    auto it = s.begin();
    while(*it == ' ') { // removes spaces at the beginning
        if(*it == ' ') s.erase(it);
    }

    auto it2 = s.end(); // removes spaces at the end of a string
    it2--;

    while(*it2 == ' ') it2--;
    it2++;
    while(*it2 == ' ') {
        if(*it2 == ' ') s.erase(it2);
    }

    for(int i = 0; i < s.length() - 1; i++) { // this does NOT work
        if(s.at(i) == ' ' && s.at(i + 1) == ' ') {
            auto it3 = s.at(i);
            s.erase(it3);
        }
    }

    return s;
}

int main() {
    string s;
    getline(cin, s);

    string s1 = RemoveSpaces(s);

    cout << "|" << s << "|" << endl;
    cout << "|" << s1 << "|" << endl;

    return 0;
}


但是,这并没有达到我的预期。我的代码成功删除了字符串开头和结尾的空格,但是我不能再进一步了。有人可以帮忙吗?

EDIT 我已解决此问题。这是代码的一部分,现在该部分删除了单词之间的多余空格,因此只在两个单词之间留了一个空格。

    auto it3= s.begin();

    for(int i = 0; i < s.length() - 1; i++) {
        if(s.at(i) == ' ' && s.at(i + 1) == ' ') {
            s.erase(s.begin()+i);
            i--;
        }

    }

谢谢大家的帮助。

5 个答案:

答案 0 :(得分:3)

您可以利用std::stringstream的功能:

#include <string>
#include <sstream>

std::string RemoveSpaces(const std::string& str) {
    std::string out;                 // the result
    std::string word;                // used to extract words from str 
    std::istringstream ss(str);      // create an istringstream from str
    while(ss >> word) {              // extract a word
        if(!out.empty()) out += ' '; // add a space between words
        out += word;                 // add the extracted word 
    }
    return out;
}

答案 1 :(得分:0)

#include <iostream>

std::string remove_excessive_spaces(const std::string& str)
{
    std::string ret;

    for(std::size_t i = str.find_first_not_of(' '); i < str.size(); i++)
    {
        if(str[i] != ' ' || ret[ret.size() - 1] != ' ')
        {
            ret.push_back(str[i]);
        }
    }

    return ret;
}


int main()
{
    std::string sentence("    some weird  sentence  xd    ");

    std::cout<<sentence<<"\n";
    std::cout<<remove_excessive_spaces(sentence)<<"\n";

    return 0;
}

答案 2 :(得分:0)

当我的模拟从命令行或文本文件读取输入时,我经常使用这一小段代码,以确保数据干净。它通过自定义copy_if()使用STL的predicate。它将所有内部空格减少到一个空格,并删除所有前导和尾随空格。

/* Removes inner whitespace from str_in */
string remove_excess_spaces(string str_in){
    //predicate class to use with copy_if
    //determines if a character should be copied based on if there is
    //a space following a non-space character
    class copy_space{
    public:
        copy_space() : was_last_space(true) {};

        bool operator()(char c) {
            if(!isspace(c)){
                was_last_space = false;
                return true;
            }
            else{
                if(was_last_space) return false;

                was_last_space = true;
                return true;
            }
        }
    private:
        bool was_last_space;
    } pred;

    //copy into single-spaced string
    string str;
    str.resize(str_in.size());
    auto it = std::copy_if(str_in.begin(), str_in.end(), str.begin(), pred);

    //remove trailing empty spots
    str = str.substr(0, it - str.begin());

    //convert all remaining whitespace to ' '. Accounts for tabs, miscelaneous newlines, etc.
    std::replace_if(str.begin(), str.end(), isspace, ' ');

    //remove any trailing whitespace
    if(isspace(str[str.size() - 1]))
        str.erase(str.size() - 1, 1);

    return str;
}

尝试一个可行的示例here

答案 3 :(得分:0)

标准库已经具有搜索范围为search_n的连续元素的功能。使用此功能,您可以找到两个以上空格开始的位置。然后您可以清除此ws并继续,找到更多连续的空格:

public function users()
{
    return $this->hasMany('App\Users', 'iduser');
}

删除前导和尾随空白称为修整。您可以使用std :: find_if从头开始,从头开始一次:

inline auto remove_triple_spaces(std::string str)
{    
    for(auto r = std::search_n(str.begin(), str.end(), 3, ' '); r != str.end(); r = std::search_n(r, str.end(), 3, ' '))
    {
        r = str.erase(r); // returns new iterator pointing to the 2nd ws. the first got erased        
    }   
    return str;
}

您现在可以合并两个功能:

inline auto trim_ws(std::string s)
{
    // erase all trailing ws (start from the end for performance)
    auto one_past_last_non_ws = std::find_if(s.rbegin(), s.rend(), [](char c){ return c != ' '; }).base();
    s.erase(one_past_last_non_ws, s.end());

    //erase all leading ws
    auto first_non_ws = std::find_if(s.begin(), s.end(), [](char c){ return c != ' '; });   
    s.erase(s.begin(), first_non_ws);

    return s;
}

答案 4 :(得分:0)

那么多行代码。 。

这里是使用嵌套std::regex的C ++标准解决方案。这样,我们得到了单线。

请参阅:

#include <iostream>
#include <string>
#include <regex>

int main()
{
    // Test string
    std::string s("   abc de  fg   hi    jk     lm  ");

    // First remove leading and trailing spaces, then remove too many spaces in between
    s = std::regex_replace(std::regex_replace(s, std::regex("^ +| +$|(\S+)"), "$1"), std::regex(" {3,}"), "  ");

    // Show result
    std::cout << s << '\n' << std::string(s.size(), '^') << '\n';

    return 0;
}

这实际上并不复杂:内部正则表达式替换

  • 文本开头,后跟
  • 一个或多个空格

OR

  • 一个或多个空格后跟
  • 文字结尾

带有原始的休息文本。在此新文本中,我们进入第二个正则表达式,在这里我们将3个或更多空格替换为2个空格。

应该可以理解。而且超短。