std::string
現在、私はプログラム内のすべての s を右トリムするために次のコードを使用しています。
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
問題なく動作しますが、失敗する可能性のあるエッジケースがいくつかあるのでしょうか?
もちろん、エレガントな代替案や左トリムの解決策を含む回答も歓迎します。
ベストアンサー1
C++11 の新しい回答
#include <algorithm>
#include <cctype>
#include <locale>
// trim from start (in place)
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)
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());
}
感謝https://stackoverflow.com/a/44973498/524503現代的な解決策を提示してくれたことに感謝します。
便利な機能
// trim from both ends (in place)
inline void trim(std::string &s) {
rtrim(s);
ltrim(s);
}
// trim from start (copying)
inline std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
inline std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
inline std::string trim_copy(std::string s) {
trim(s);
return s;
}
C++03 の回答を更新しました
参照によるパラメータの受け取り、変更、および返却に関するコメントに対処します。同意します。おそらく私が好む実装は、インプレース用とコピー用の 2 セットの関数です。より良い例は次のとおりです。
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>
// trim from start (in place)
inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::not1(std::ptr_fun<int, int>(std::isspace))));
}
// trim from end (in place)
inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
}
// the remaining functions (trim() et al.) are identical to the new C++11 version
std::ptr_fun
ロケールをサポートする 2 番目の定義があるため、曖昧さを解消する必要がありますstd::isspace
。これは、まったく同じキャストでもかまいませんが、私はこれがより気に入っています。
C++03の元の回答
私はこの元の回答を文脈上、また高評価の回答を引き続き利用できるようにするために残しておきます。
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>
// trim from start
inline std::string <rim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
inline std::string &rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// trim from both ends
inline std::string &trim(std::string &s) {
return ltrim(rtrim(s));
}