我知道有几种方法可以在Java和C中做到这一点很好,但在C ++中,我似乎无法找到一种方法来轻松实现字符串修剪功能。
这就是我目前所拥有的:
string trim(string& str)
{
size_t first = str.find_first_not_of(' ');
size_t last = str.find_last_not_of(' ');
return str.substr(first, (last-first+1));
}
但每当我试着打电话
trim(myString);
我收到编译错误
/tmp/ccZZKSEq.o: In function `song::Read(std::basic_ifstream<char,
std::char_traits<char> >&, std::basic_ifstream<char, std::char_traits<char> >&, char const*, char const*)':
song.cpp:(.text+0x31c): undefined reference to `song::trim(std::string&)'
collect2: error: ld returned 1 exit status
我试图找到一种简单而标准的方法,从字符串中修剪前导和尾随空格,而不占用100行代码,我尝试使用正则表达式,但无法使其工作。
我也不能使用Boost。
答案 0 :(得分:35)
你的代码很好。您所看到的是链接器问题。
如果您将代码放在如下的单个文件中:
#include <iostream>
#include <string>
using namespace std;
string trim(const string& str)
{
size_t first = str.find_first_not_of(' ');
if (string::npos == first)
{
return str;
}
size_t last = str.find_last_not_of(' ');
return str.substr(first, (last - first + 1));
}
int main() {
string s = "abc ";
cout << trim(s);
}
然后执行g++ test.cc
并运行a.out,您将看到它有效。
您应该检查包含trim
函数的文件是否包含在编译过程的链接阶段。
答案 1 :(得分:19)
以下是如何做到这一点:
std::string & trim(std::string & str)
{
return ltrim(rtrim(str));
}
支持功能的实现如下:
std::string & ltrim(std::string & str)
{
auto it2 = std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
str.erase( str.begin() , it2);
return str;
}
std::string & rtrim(std::string & str)
{
auto it1 = std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
str.erase( it1.base() , str.end() );
return str;
}
一旦你完成所有这些,你也可以写下这个:
std::string trim_copy(std::string const & str)
{
auto s = str;
return ltrim(rtrim(s));
}
试试这个
答案 2 :(得分:6)
我认为如果str只包含空格,则substr()会抛出异常。
我会将其修改为以下代码:
string trim(string& str)
{
size_t first = str.find_first_not_of(' ');
if (first == std::string::npos)
return "";
size_t last = str.find_last_not_of(' ');
return str.substr(first, (last-first+1));
}
答案 3 :(得分:1)
使用正则表达式
#include <regex>
#include <string>
string trim(string s) {
regex e("^\\s+|\\s+$"); // remove leading and trailing spaces
return regex_replace(s, e, "");
}
答案 4 :(得分:0)
#include <vector>
#include <numeric>
#include <sstream>
#include <iterator>
void Trim(std::string& inputString)
{
std::istringstream stringStream(inputString);
std::vector<std::string> tokens((std::istream_iterator<std::string>(stringStream)), std::istream_iterator<std::string>());
inputString = std::accumulate(std::next(tokens.begin()), tokens.end(),
tokens[0], // start with first element
[](std::string a, std::string b) { return a + " " + b; });
}
答案 5 :(得分:0)
除了@gjha的答案:
inline std::string ltrim_copy(const std::string& str)
{
auto it = std::find_if(str.cbegin(), str.cend(),
[](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
return std::string(it, str.cend());
}
inline std::string rtrim_copy(const std::string& str)
{
auto it = std::find_if(str.crbegin(), str.crend(),
[](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
return it == str.crend() ? std::string() : std::string(str.cbegin(), ++it.base());
}
inline std::string trim_copy(const std::string& str)
{
auto it1 = std::find_if(str.cbegin(), str.cend(),
[](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
if (it1 == str.cend()) {
return std::string();
}
auto it2 = std::find_if(str.crbegin(), str.crend(),
[](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
return it2 == str.crend() ? std::string(it1, str.cend()) : std::string(it1, ++it2.base());
}