从字符串中删除所有空格

时间:2013-09-03 10:08:03

标签: c++ string

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
  string str;
  cin>>str;
  str.erase(remove_if(str.begin(), str.end(), isspace),str.end());
  cout<<str;
  return 0;
}

错误味精:

  

/home/satish/Desktop/CPP/Remove_Spaces/main.cpp|9|error:没有用于调用'remove_if(std :: basic_string :: iterator,std :: basic_string :: iterator,)'的匹配函数

5 个答案:

答案 0 :(得分:4)

首先,在std::isspace中宣布<cctype>,所以请包含该内容。

其次,您需要通过将函数转换为显式类型来消除重载的歧义:

str.erase(
    remove_if(str.begin(), str.end(), static_cast<int(*)(int)>(isspace)),
    str.end());

第三,正如James所说,这会导致所有不在ASCII范围内的字符的未定义行为,并且由于您通常不能排除这种情况,因此您需要努力确保只将正字符代码传递给{ {1}}:

std::isspace

答案 1 :(得分:3)

正如评论中所述,您缺少std::isspace的包含,即<cctype>。但即便如此,你也不会有成功,因为isspace被重载see here

过载问题的解决方案是将函数指针显式地转换为所需的函数sgnature:

str.erase(remove_if(str.begin(), str.end(), static_cast<int(*)(int)>(&std::isspace)),str.end());

但是,正如评论中所指出的那样,此处使用的isspace具有未定义的行为,如果它获得非ASCII字符。在这种情况下,最好使用模板化版本将语言环境作为第二个参数:

<强> C ++ 14:

str.erase(
  remove_if(str.begin(), str.end(), 
    [](auto c){ return isspace(c, cin.getloc());}
  ),
str.end());

C ++ 11:,如上所述,lambda以char c为参数(C ++ 11中没有多态lambda)。

C ++ 03 with boost:使用boost::bindremove_if创建谓词

str.erase(
  remove_if(str.begin(), str.end(), 
    boost::bind(&std::isspace<char>, _1, boost::ref(cin.getloc()))
  ),
str.end());

没有提升的C ++ 03:将手写的仿函数定义为谓词

struct IsSpace {
  bool operator()(char c) {
    return std::isspace(c, cin.getloc());
  }
};

str.erase(
  remove_if(str.begin(), str.end(), 
    IsSpace()
  ),
str.end());

答案 2 :(得分:1)

由于到目前为止所有答案都涉及未定义的行为......

“最简单”的解决方案,如果您使用C ++ 11, 是:

str.erase(
    std::remove_if(
        str.begin(),
        str.end(), 
        []( char ch ) { return isspace( static_cast<unsigned char>( ch ) ); } ),
    str.end() );

如果没有转化为unsigned charisspace的输入就会出现 失败的(未经检查的)函数的前提条件是明确的 char已签名。

如果您没有C ++ 11,或者您将需要这种类型 你在其他地方的东西(跳过空白等) 可以写一个单独的谓词功能对象:

struct IsSpace
{
    bool operator()( char ch ) const
    {
        return isspace( static_cast<unsigned char>( ch ) );
    }
};

您可能还需要IsNotSpace和相应的对象 其余is...函数位于<ctype.h>

或者,您可以使用的语言环境感知版本 <locale>中的函数:

template <std::ctype_base>::mask mask, bool is>
class Is
{
    std::locale m_toEnsureLifetime;
    std::ctype<char> const* m_ctype;
public:
    Is( std::locale const& l = std::locale() )
        : m_toEnsureLifetime( l )
        , m_ctype( &std::use_facet<std::ctype<char>>( m_toEnsureLifetime ) )
    {
    }
    bool operator()( char ch ) const
    {
        return m_ctype->is( mask, ch ) == is;
    }
};
typedef Is<std::ctype_base::space, true> IsSpace;
typedef Is<std::ctype_base::space, false> IsNotSpace;
//  ...

虽然有点复杂,但它完全可以识别语言环境,并且 实际上需要更少的代码(因为掩码可以是一个模板 参数)。

答案 3 :(得分:0)

尝试这种方式:

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

struct SpaceRemover
{
    bool operator( )( char _ch ) { return std::isspace( _ch ); }
};

int main( )
{
    std::string strSource = "   type    ddd     ";
    std::cout << "[main] Source string :\""<< strSource << "\"" << std::endl;

    std::string::iterator itEnd = std::remove_if( strSource.begin(), 
                                                  strSource.end(), 
                                                  SpaceRemover( ) );
    strSource.resize( std::distance( strSource.begin(), itEnd ) );

    std::cout << "[main] Result string :\""<< strSource << "\"" << std::endl;

    return 0;
}

答案 4 :(得分:0)

#include <iostream>

int main() {
    std::string original =  "   type    ddd     ";
    std::string result;
    for(char c: original) {
        if( ! std::isspace(c)) result += c;
    }
    original.swap(result);
    std::cout << "Modified: " << original << std::endl;
    return 0;
}

如果可以预测结果大小(或者仅仅考虑原始大小),result.reserve()将提高性能。

相关问题