0
#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|错误:没有匹配函数调用'remove_if(std::basic_string::iterator, std::basic_string::iterator, )'|

4

5 回答 5

4

首先,std::isspace在声明中<cctype>包含它。

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

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

第三,正如詹姆斯所说,这会导致所有不在 ASCII 范围内的字符出现未定义的行为,并且由于您通常不能排除这一点,因此您需要努力确保只有正字符代码被传递给std::isspace

bool char_isspace(char c) {
    return std::isspace(static_cast<unsigned char>(c));
}

…

str.erase(
    remove_if(str.begin(), str.end(), char_isspace),
    str.end());
于 2013-09-03T10:19:06.517 回答
3

如评论中所述,您缺少包含std::isspace,即<cctype>。但即便如此,您也不会成功,因为 isspace 已超载,请参见此处

重载问题的解决方案是将函数指针显式转换为所需的函数签名:

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

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

C++14:

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

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

C ++ 03 with boost:用于boost::bind创建谓词remove_if

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

没有 boost 的 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());
于 2013-09-03T10:19:54.987 回答
1

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

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

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

如果没有强制转换 to unsigned char,则输入 toisspace将失败函数的(未经检查的)先决条件是简单 char的签名。

如果你没有 C++11,或者你在其他地方也需要这种东西(跳过空格等),你可以编写一个单独的谓词函数对象:

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

您可能还需要IsNotSpaceis....<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;
//  ...

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

于 2013-09-03T11:28:31.087 回答
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;
}

If the result size can be predicted (or just taking the original size is good enough), a result.reserve() will improve performance.

于 2013-09-03T11:24:50.837 回答
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;
}
于 2013-09-03T10:53:20.067 回答