C++ 什么';修剪std::string的最佳方法是什么?
我目前正在使用以下代码右键修剪程序中的所有C++ 什么';修剪std::string的最佳方法是什么?,c++,trim,stdstring,C++,Trim,Stdstring,我目前正在使用以下代码右键修剪程序中的所有std::strings: std::string s; s.erase(s.find_last_not_of(" \n\r\t")+1); 它工作得很好,但我想知道是否有一些最终案例可能会失败 当然,欢迎使用优雅的备选答案和左对齐解决方案。对于空字符串,您的代码假设将1添加到string::npos中会得到0string::npos的类型为string::size\u type,未签名。因此,您依赖于加法的溢出行为。使用以下方法最简单: #inclu
std::strings
:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
它工作得很好,但我想知道是否有一些最终案例可能会失败
当然,欢迎使用优雅的备选答案和左对齐解决方案。对于空字符串,您的代码假设将1添加到
string::npos中会得到0string::npos
的类型为string::size\u type
,未签名。因此,您依赖于加法的溢出行为。使用以下方法最简单:
#include <boost/algorithm/string.hpp>
std::string str("hello world! ");
boost::trim_right(str);
#包括
string str(“你好,世界!”);
增压:右微调(str);
str
现在是“你好,世界!”
。还有trim_left
和trim
,可以修剪两侧
如果将\u copy
后缀添加到上述任何函数名称,例如trim\u copy
,该函数将返回字符串的修剪副本,而不是通过引用对其进行修改
如果在上述任何函数名中添加\u If
后缀,例如trim\u copy\u If
,则可以修剪满足自定义谓词的所有字符,而不仅仅是空格。我不确定您的环境是否相同,但在我的环境中,空字符串大小写将导致程序中止。我要么用if(!s.empty())包装那个擦除调用,要么像前面提到的那样使用Boost
这也适用于空情况。:-) 编辑自c++17以来,标准库的某些部分被删除。幸运的是,从c++11开始,我们有了lambdas,这是一个更好的解决方案
#include <algorithm>
#include <cctype>
#include <locale>
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trim_copy(std::string s) {
trim(s);
return s;
}
我保留上面的原始答案是为了上下文和保持高投票率的答案仍然可用。使用以下代码从std::strings
()右键修剪(尾随)空格和制表符:
为了平衡起见,我还将包括左修剪代码():
上面的方法很好,但有时您希望对例程认为是空白的内容使用函数的组合。在这种情况下,使用函子组合操作可能会变得混乱,因此我更喜欢一个简单的循环,我可以为修剪修改它。这里有一个稍微修改过的trim函数,它是从C版本复制过来的。在本例中,我正在修剪非字母数字字符
string trim(char const *str)
{
// Trim leading non-letters
while(!isalnum(*str)) str++;
// Trim trailing non-letters
end = str + strlen(str) - 1;
while(end > str && !isalnum(*end)) end--;
return string(str, end+1);
}
以下是我的想法:
std::stringstream trimmer;
trimmer << str;
trimmer >> str;
std::stringstream修剪器;
trimmer>str;
流提取自动消除空白,因此这就像一个符咒一样有效。
如果我自己这么说的话,那也相当干净优雅 我喜欢tzaman的解决方案,唯一的问题是它没有修剪只包含空格的字符串
要更正该缺陷,请在两条修剪线之间添加str.clear()
std::stringstream trimmer;
trimmer << str;
str.clear();
trimmer >> str;
std::stringstream修剪器;
trimmer>str;
试试这个,它对我有用
inline std::string trim(std::string& str)
{
str.erase(0, str.find_first_not_of(' ')); //prefixing spaces
str.erase(str.find_last_not_of(' ')+1); //surfixing spaces
return str;
}
我的解决方案基于
请注意,如果输入字符串只包含空格,则这些函数将返回空字符串
const std::string StringUtils::WHITESPACE=“\n\r\t”;
std::string字符串utils::Trim(const std::string&s)
{
返回右侧修剪(修剪左侧);
}
std::string字符串utils::trimlevent(const std::string&s)
{
size\u t startpos=s.find\u first\u not\u of(StringUtils::WHITESPACE);
return(startpos==std::string::npos)?“”:s.substr(startpos);
}
std::string字符串utils::TrimRight(const std::string&s)
{
size_t endpos=s.find_last_not_of(StringUtils::WHITESPACE);
返回(endpos==std::string::npos)?“”:s.substr(0,endpos+1);
}
晚会有点晚了,不过没关系。现在C++11在这里,我们有lambda和自动变量。因此,我的版本,也处理所有空白和空字符串,是:
#include <cctype>
#include <string>
#include <algorithm>
inline std::string trim(const std::string &s)
{
auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
auto wsback=std::find_if_not(s.rbegin(),s.rend(),[](int c){return std::isspace(c);}).base();
return (wsback<=wsfront ? std::string() : std::string(wsfront,wsback));
}
C++11还附带了一个模块,当然可以用来修剪前导或尾随空格
也许是这样的:
inline std::string trim(const std::string &s)
{
auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
return std::string(wsfront,std::find_if_not(s.rbegin(),std::string::const_reverse_iterator(wsfront),[](int c){return std::isspace(c);}).base());
}
std::string ltrim(const std::string& s)
{
static const std::regex lws{"^[[:space:]]*", std::regex_constants::extended};
return std::regex_replace(s, lws, "");
}
std::string rtrim(const std::string& s)
{
static const std::regex tws{"[[:space:]]*$", std::regex_constants::extended};
return std::regex_replace(s, tws, "");
}
std::string trim(const std::string& s)
{
return ltrim(rtrim(s));
}
这个怎么样
#include <iostream>
#include <string>
#include <regex>
std::string ltrim( std::string str ) {
return std::regex_replace( str, std::regex("^\\s+"), std::string("") );
}
std::string rtrim( std::string str ) {
return std::regex_replace( str, std::regex("\\s+$"), std::string("") );
}
std::string trim( std::string str ) {
return ltrim( rtrim( str ) );
}
int main() {
std::string str = " \t this is a test string \n ";
std::cout << "-" << trim( str ) << "-\n";
return 0;
}
#包括
#包括
#包括
std::string ltrim(std::string str){
返回std::regex_replace(str,std::regex(“^\\s+”),std::string(“”);
}
std::string rtrim(std::string str){
返回std::regex_replace(str,std::regex(\\s+$),std::string(“”);
}
std::string trim(std::string str){
返回ltrim(rtrim(str));
}
int main(){
std::string str=“\t这是一个测试字符串\n”;
这就是我所用的。只要不断地从前面去掉空间,然后,如果还有什么剩余的,从后面也做同样的事情
void trim(string& s) {
while(s.compare(0,1," ")==0)
s.erase(s.begin()); // remove leading whitespaces
while(s.size()>0 && s.compare(s.size()-1,1," ")==0)
s.erase(s.end()-1); // remove trailing whitespaces
}
我想如果你开始询问修剪字符串的“最佳方法”,我会说一个好的实现应该是:
不分配临时字符串
具有在位修剪和复制修剪的重载
可轻松定制以接受不同的验证序列/逻辑
显然,有太多不同的方法来实现这一点,这完全取决于您实际需要什么。然而,C标准库中仍然有一些非常有用的函数,如memchr。这就是为什么C仍然被视为IO的最佳语言的原因——它的stdlib纯粹是高效的
inline const char* trim_start(const char* str)
{
while (memchr(" \t\n\r", *str, 4)) ++str;
return str;
}
inline const char* trim_end(const char* end)
{
while (memchr(" \t\n\r", end[-1], 4)) --end;
return end;
}
inline std::string trim(const char* buffer, int len) // trim a buffer (input?)
{
return std::string(trim_start(buffer), trim_end(buffer + len));
}
inline void trim_inplace(std::string& str)
{
str.assign(trim_start(str.c_str()),
trim_end(str.c_str() + str.length()));
}
int main()
{
char str [] = "\t \nhello\r \t \n";
string trimmed = trim(str, strlen(str));
cout << "'" << trimmed << "'" << endl;
system("pause");
return 0;
}
inline const char*trim_start(const char*str)
{
而(memchr(“\t\n\r”,*str,4))++str;
返回str;
}
内联常量字符*修剪结束(常量字符*结束)
{
而(memchr(“\t\n\r”,end[-1],4))--end;
返回端;
}
内联std::string trim(const char*buffer,int len)//修剪缓冲区(输入?)
{
返回std::string(trim_start(buffer)、trim_end(buffer+len));
}
内嵌式空心装饰(标准::字符串和str)
{
str.assign(trim_start(str.c_str()),
修剪末端(str.c_str()+str.length());
}
int main()
{
char str[]=“\t\nhello\r\t\n”;
字符串修剪=修剪(str,strlen(str));
cout
将我的解决方案用于噪音。trim
默认情况下创建一个新字符串并返回修改后的字符串,而trim_in_place
修改字符串过程
inline std::string trim(const std::string &s)
{
auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
return std::string(wsfront,std::find_if_not(s.rbegin(),std::string::const_reverse_iterator(wsfront),[](int c){return std::isspace(c);}).base());
}
std::string ltrim(const std::string& s)
{
static const std::regex lws{"^[[:space:]]*", std::regex_constants::extended};
return std::regex_replace(s, lws, "");
}
std::string rtrim(const std::string& s)
{
static const std::regex tws{"[[:space:]]*$", std::regex_constants::extended};
return std::regex_replace(s, tws, "");
}
std::string trim(const std::string& s)
{
return ltrim(rtrim(s));
}
#include <iostream>
#include <string>
#include <regex>
std::string ltrim( std::string str ) {
return std::regex_replace( str, std::regex("^\\s+"), std::string("") );
}
std::string rtrim( std::string str ) {
return std::regex_replace( str, std::regex("\\s+$"), std::string("") );
}
std::string trim( std::string str ) {
return ltrim( rtrim( str ) );
}
int main() {
std::string str = " \t this is a test string \n ";
std::cout << "-" << trim( str ) << "-\n";
return 0;
}
void trim(string& s) {
while(s.compare(0,1," ")==0)
s.erase(s.begin()); // remove leading whitespaces
while(s.size()>0 && s.compare(s.size()-1,1," ")==0)
s.erase(s.end()-1); // remove trailing whitespaces
}
inline const char* trim_start(const char* str)
{
while (memchr(" \t\n\r", *str, 4)) ++str;
return str;
}
inline const char* trim_end(const char* end)
{
while (memchr(" \t\n\r", end[-1], 4)) --end;
return end;
}
inline std::string trim(const char* buffer, int len) // trim a buffer (input?)
{
return std::string(trim_start(buffer), trim_end(buffer + len));
}
inline void trim_inplace(std::string& str)
{
str.assign(trim_start(str.c_str()),
trim_end(str.c_str() + str.length()));
}
int main()
{
char str [] = "\t \nhello\r \t \n";
string trimmed = trim(str, strlen(str));
cout << "'" << trimmed << "'" << endl;
system("pause");
return 0;
}
std::string trim(const std::string &s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && isspace(*it))
it++;
std::string::const_reverse_iterator rit = s.rbegin();
while (rit.base() != it && isspace(*rit))
rit++;
return std::string(it, rit.base());
}
#include <string>
// modifies input string, returns input
std::string& trim_left_in_place(std::string& str) {
size_t i = 0;
while(i < str.size() && isspace(str[i])) { ++i; };
return str.erase(0, i);
}
std::string& trim_right_in_place(std::string& str) {
size_t i = str.size();
while(i > 0 && isspace(str[i - 1])) { --i; };
return str.erase(i, str.size());
}
std::string& trim_in_place(std::string& str) {
return trim_left_in_place(trim_right_in_place(str));
}
// returns newly created strings
std::string trim_right(std::string str) {
return trim_right_in_place(str);
}
std::string trim_left(std::string str) {
return trim_left_in_place(str);
}
std::string trim(std::string str) {
return trim_left_in_place(trim_right_in_place(str));
}
#include <cassert>
int main() {
std::string s1(" \t\r\n ");
std::string s2(" \r\nc");
std::string s3("c \t");
std::string s4(" \rc ");
assert(trim(s1) == "");
assert(trim(s2) == "c");
assert(trim(s3) == "c");
assert(trim(s4) == "c");
assert(s1 == " \t\r\n ");
assert(s2 == " \r\nc");
assert(s3 == "c \t");
assert(s4 == " \rc ");
assert(trim_in_place(s1) == "");
assert(trim_in_place(s2) == "c");
assert(trim_in_place(s3) == "c");
assert(trim_in_place(s4) == "c");
assert(s1 == "");
assert(s2 == "c");
assert(s3 == "c");
assert(s4 == "c");
}
const char* ws = " \t\n\r\f\v";
// trim from end of string (right)
inline std::string& rtrim(std::string& s, const char* t = ws)
{
s.erase(s.find_last_not_of(t) + 1);
return s;
}
// trim from beginning of string (left)
inline std::string& ltrim(std::string& s, const char* t = ws)
{
s.erase(0, s.find_first_not_of(t));
return s;
}
// trim from both ends of string (right then left)
inline std::string& trim(std::string& s, const char* t = ws)
{
return ltrim(rtrim(s, t), t);
}
void TrimString(std::string & str)
{
if(str.empty())
return;
const auto pStr = str.c_str();
size_t front = 0;
while(front < str.length() && std::isspace(int(pStr[front]))) {++front;}
size_t back = str.length();
while(back > front && std::isspace(int(pStr[back-1]))) {--back;}
if(0 == front)
{
if(back < str.length())
{
str.resize(back - front);
}
}
else if(back <= front)
{
str.clear();
}
else
{
str = std::move(std::string(str.begin()+front, str.begin()+back));
}
}
#include <algorithm>
#include <functional>
#include <string>
/**
* @brief Left Trim
*
* Trims whitespace from the left end of the provided std::string
*
* @param[out] s The std::string to trim
*
* @return The modified std::string&
*/
std::string& ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::ptr_fun<int, int>(std::isgraph)));
return s;
}
/**
* @brief Right Trim
*
* Trims whitespace from the right end of the provided std::string
*
* @param[out] s The std::string to trim
*
* @return The modified std::string&
*/
std::string& rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::ptr_fun<int, int>(std::isgraph)).base(), s.end());
return s;
}
/**
* @brief Trim
*
* Trims whitespace from both ends of the provided std::string
*
* @param[out] s The std::string to trim
*
* @return The modified std::string&
*/
std::string& trim(std::string& s) {
return ltrim(rtrim(s));
}
std::string & trim(std::string & str)
{
return ltrim(rtrim(str));
}
std::string & ltrim(std::string & str)
{
auto it = std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
str.erase( str.begin() , it);
return str;
}
std::string & rtrim(std::string & str)
{
auto it = std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
str.erase( it.base() , str.end() );
return str;
}
std::string trim_copy(std::string const & str)
{
auto s = str;
return ltrim(rtrim(s));
}
s.erase(0, s.find_first_not_of(" \n\r\t"));
s.erase(s.find_last_not_of(" \n\r\t")+1);
static void trim(std::string &s) {
s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), [](char c){ return std::isspace(c); }));
s.erase(std::find_if_not(s.rbegin(), s.rend(), [](char c){ return std::isspace(c); }).base(), s.end());
}
while ( !s.empty() && isspace(s.back()) ) s.pop_back();
size_t beg = s.find_first_not_of(" \r\n");
return (beg == string::npos) ? "" : in.substr(beg, s.find_last_not_of(" \r\n") - beg);
#include <string>
#include <cctype> // for isspace
using namespace std;
// Left trim the given string (" hello! " --> "hello! ")
string left_trim(string str) {
int numStartSpaces = 0;
for (int i = 0; i < str.length(); i++) {
if (!isspace(str[i])) break;
numStartSpaces++;
}
return str.substr(numStartSpaces);
}
// Right trim the given string (" hello! " --> " hello!")
string right_trim(string str) {
int numEndSpaces = 0;
for (int i = str.length() - 1; i >= 0; i--) {
if (!isspace(str[i])) break;
numEndSpaces++;
}
return str.substr(0, str.length() - numEndSpaces);
}
// Left and right trim the given string (" hello! " --> "hello!")
string trim(string str) {
return right_trim(left_trim(str));
}
std::string_view trim(std::string_view s)
{
s.remove_prefix(std::min(s.find_first_not_of(" \t\r\v\n"), s.size()));
s.remove_suffix(std::min(s.size() - s.find_last_not_of(" \t\r\v\n") - 1, s.size()));
return s;
}
std::string_view ltrim(std::string_view s)
{
s.remove_prefix(std::distance(s.cbegin(), std::find_if(s.cbegin(), s.cend(),
[](int c) {return !std::isspace(c);})));
return s;
}
std::string_view rtrim(std::string_view s)
{
s.remove_suffix(std::distance(s.crbegin(), std::find_if(s.crbegin(), s.crend(),
[](int c) {return !std::isspace(c);})));
return s;
}
std::string_view trim(std::string_view s)
{
return ltrim(rtrim(s));
}
#include <string>
#include <regex>
string trim(string str){
return regex_replace(str, regex("(^[ ]+)|([ ]+$)"),"");
}
str.erase(0, str.find_first_not_of("\t\n\v\f\r ")); // left trim
str.erase(str.find_last_not_of("\t\n\v\f\r ") + 1); // right trim