Удаление начальных и конечных пробелов из строки
Как удалить пробелы из строкового объекта в С++.
Например, как удалить ведущие и конечные пробелы из ниже строкового объекта.
//Original string: " This is a sample string "
//Desired string: "This is a sample string"
Строковый класс, насколько мне известно, не предоставляет никаких методов для удаления ведущих и конечных пробелов.
Чтобы добавить к проблеме, как расширить это форматирование для обработки лишних пробелов между словами строки. Например,
// Original string: " This is a sample string "
// Desired string: "This is a sample string"
Используя методы строк, упомянутые в решении, я могу подумать о выполнении этих операций в два этапа.
- Удалите передние и конечные пробелы.
- Используйте find_first_of, find_last_of, find_first_not_of, find_last_not_of и substr, повторно на границах слов, чтобы получить желаемое форматирование.
Ответы
Ответ 1
Это называется тримминг. Если вы можете использовать Boost, я бы порекомендовал это.
В противном случае используйте find_first_not_of
для получения индекса первого find_last_not_of
символа, затем find_last_not_of
для получения индекса с конца, который не является пробелом. С их помощью используйте substr
чтобы получить подстроку без окружающих пробелов.
В ответ на ваше редактирование я не знаю термин, но я бы предположил что-то вроде "уменьшить", так что я назвал это. :) (Обратите внимание, я изменил пробел, чтобы быть параметром, для гибкости)
#include <iostream>
#include <string>
std::string trim(const std::string& str,
const std::string& whitespace = " \t")
{
const auto strBegin = str.find_first_not_of(whitespace);
if (strBegin == std::string::npos)
return ""; // no content
const auto strEnd = str.find_last_not_of(whitespace);
const auto strRange = strEnd - strBegin + 1;
return str.substr(strBegin, strRange);
}
std::string reduce(const std::string& str,
const std::string& fill = " ",
const std::string& whitespace = " \t")
{
// trim first
auto result = trim(str, whitespace);
// replace sub ranges
auto beginSpace = result.find_first_of(whitespace);
while (beginSpace != std::string::npos)
{
const auto endSpace = result.find_first_not_of(whitespace, beginSpace);
const auto range = endSpace - beginSpace;
result.replace(beginSpace, range, fill);
const auto newStart = beginSpace + fill.length();
beginSpace = result.find_first_of(whitespace, newStart);
}
return result;
}
int main(void)
{
const std::string foo = " too much\t \tspace\t\t\t ";
const std::string bar = "one\ntwo";
std::cout << "[" << trim(foo) << "]" << std::endl;
std::cout << "[" << reduce(foo) << "]" << std::endl;
std::cout << "[" << reduce(foo, "-") << "]" << std::endl;
std::cout << "[" << trim(bar) << "]" << std::endl;
}
Результат:
[too much space]
[too much space]
[too-much-space]
[one
two]
Ответ 2
Простое удаление ведущих, конечных и дополнительных пробелов из std::string в одной строке
value = std::regex_replace(value, std::regex("^ +| +$|( ) +"), "$1");
удаление только ведущих пробелов
value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::bind1st(std::not_equal_to<char>(), ' ')));
или
value = std::regex_replace(value, std::regex("^ +"), "");
удаление только конечных пробелов
value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), value.end());
или
value = std::regex_replace(value, std::regex(" +$"), "");
удаление только лишних пробелов
value = regex_replace(value, std::regex(" +"), " ");
Ответ 3
В настоящее время я использую следующие функции:
// trim from left
inline std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v")
{
s.erase(0, s.find_first_not_of(t));
return s;
}
// trim from right
inline std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v")
{
s.erase(s.find_last_not_of(t) + 1);
return s;
}
// trim from left & right
inline std::string& trim(std::string& s, const char* t = " \t\n\r\f\v")
{
return ltrim(rtrim(s, t), t);
}
// copying versions
inline std::string ltrim_copy(std::string s, const char* t = " \t\n\r\f\v")
{
return ltrim(s, t);
}
inline std::string rtrim_copy(std::string s, const char* t = " \t\n\r\f\v")
{
return rtrim(s, t);
}
inline std::string trim_copy(std::string s, const char* t = " \t\n\r\f\v")
{
return trim(s, t);
}
Ответ 4
Алгоритм повышения строки
#include <boost/algorithm/string/trim.hpp>
[...]
std::string msg = " some text with spaces ";
boost::algorithm::trim(msg);
Ответ 5
Вот как вы можете это сделать:
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));
}
Попробуйте это
Ответ 6
Это мое решение для удаления верхнего и конечного пробелов...
std::string stripString = " Plamen ";
while(!stripString.empty() && std::isspace(*stripString.begin()))
stripString.erase(stripString.begin());
while(!stripString.empty() && std::isspace(*stripString.rbegin()))
stripString.erase(stripString.length()-1);
В результате получается "Plamen"
Ответ 7
Пример для верхнего и конечного пробелов триммера после предложения jon-hanson для использования boost (удаляет только закрывающие и отложенные пробелы):
#include <boost/algorithm/string/trim.hpp>
std::string str = " t e s t ";
boost::algorithm::trim ( str );
Результаты в "t e s t"
Существует также
-
trim_left
приводит к "t e s t "
-
trim_right
приводит к " t e s t"
Ответ 8
/// strip a string, remove leading and trailing spaces
void strip(const string& in, string& out)
{
string::const_iterator b = in.begin(), e = in.end();
// skipping leading spaces
while (isSpace(*b)){
++b;
}
if (b != e){
// skipping trailing spaces
while (isSpace(*(e-1))){
--e;
}
}
out.assign(b, e);
}
В приведенном выше коде функция isSpace() является логической функцией, которая указывает, является ли символ пробелом, вы можете реализовать эту функцию, чтобы отразить ваши потребности, или просто вызвать isspace() из "ctype.h" если вы хотите.
Ответ 9
Использование стандартной библиотеки имеет много преимуществ, но нужно знать некоторые особые случаи, которые вызывают исключения. Например, ни один из ответов не охватывал случай, когда строка С++ имеет некоторые символы Unicode. В этом случае, если вы используете функцию isspace, будет выбрано исключение.
Я использую следующий код для обрезки строк и некоторых других операций, которые могут оказаться полезными. Основные преимущества этого кода: он очень быстрый (быстрее, чем любой код, который я когда-либо тестировал), он использует только стандартную библиотеку и никогда не вызывает исключения:
#include <string>
#include <algorithm>
#include <functional>
#include <locale>
#include <iostream>
typedef unsigned char BYTE;
std::string strTrim(std::string s, char option = 0)
{
// convert all whitespace characters to a standard space
std::replace_if(s.begin(), s.end(), (std::function<int(BYTE)>)::isspace, ' ');
// remove leading and trailing spaces
size_t f = s.find_first_not_of(' ');
if (f == std::string::npos) return "";
s = s.substr(f, s.find_last_not_of(' ') - f + 1);
// remove consecutive spaces
s = std::string(s.begin(), std::unique(s.begin(), s.end(),
[](BYTE l, BYTE r){ return l == ' ' && r == ' '; }));
switch (option)
{
case 'l': // convert to lowercase
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
return s;
case 'U': // convert to uppercase
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
return s;
case 'n': // remove all spaces
s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
return s;
default: // just trim
return s;
}
}
Ответ 10
Пример для обрезки ведущих и конечных пробелов
std::string aString(" This is a string to be trimmed ");
auto start = aString.find_first_not_of(' ');
auto end = aString.find_last_not_of(' ');
std::string trimmedString;
trimmedString = aString.substr(start, (end - start) + 1);
ИЛИ
trimmedSring = aString.substr(aString.find_first_not_of(' '), (aString.find_last_not_of(' ') - aString.find_first_not_of(' ')) + 1);
Ответ 11
Я тестировал это, все работает. Таким образом, этот метод processInput просто попросит пользователя ввести что-то. Он вернет строку, в которой нет лишних пробелов внутри, или дополнительных пробелов в начале или в конце. Надеюсь это поможет. (также кладет кучу комментариев, чтобы сделать ее простой для понимания).
вы можете увидеть, как реализовать его в main() внизу
#include <string>
#include <iostream>
string processInput() {
char inputChar[256];
string output = "";
int outputLength = 0;
bool space = false;
// user inputs a string.. well a char array
cin.getline(inputChar,256);
output = inputChar;
string outputToLower = "";
// put characters to lower and reduce spaces
for(int i = 0; i < output.length(); i++){
// if it caps put it to lowercase
output[i] = tolower(output[i]);
// make sure we do not include tabs or line returns or weird symbol for null entry array thingy
if (output[i] != '\t' && output[i] != '\n' && output[i] != 'Ì') {
if (space) {
// if the previous space was a space but this one is not, then space now is false and add char
if (output[i] != ' ') {
space = false;
// add the char
outputToLower+=output[i];
}
} else {
// if space is false, make it true if the char is a space
if (output[i] == ' ') {
space = true;
}
// add the char
outputToLower+=output[i];
}
}
}
// trim leading and tailing space
string trimmedOutput = "";
for(int i = 0; i < outputToLower.length(); i++){
// if it the last character and it not a space, then add it
// if it the first character and it not a space, then add it
// if it not the first or the last then add it
if (i == outputToLower.length() - 1 && outputToLower[i] != ' ' ||
i == 0 && outputToLower[i] != ' ' ||
i > 0 && i < outputToLower.length() - 1) {
trimmedOutput += outputToLower[i];
}
}
// return
output = trimmedOutput;
return output;
}
int main() {
cout << "Username: ";
string userName = processInput();
cout << "\nModified Input = " << userName << endl;
}
Ответ 12
Это может быть самым простым из всех.
Вы можете использовать string::find
и string::rfind
чтобы найти пробелы с обеих сторон и уменьшить строку.
void TrimWord(std::string& word)
{
if (word.empty()) return;
// Trim spaces from left side
while (word.find(" ") == 0)
{
word.erase(0, 1);
}
// Trim spaces from right side
size_t len = word.size();
while (word.rfind(" ") == --len)
{
word.erase(len, len + 1);
}
}
Ответ 13
Зачем усложнять?
std::string removeSpaces(std::string x){
if(x[0] == ' '){ x.erase(0, 1); }
if(x[x.length()-1] == ' '){ x.erase(x.length()-1, x.length()); }
return x;
}
Это работает, даже если повышение не удалось, ни регулярное выражение, ни странные вещи, ни библиотеки.
Ответ 14
char *str = (char*) malloc(50 * sizeof(char));
strcpy(str, " some random string (<50 chars) ");
while(*str == ' ' || *str == '\t' || *str == '\n')
str++;
int len = strlen(str);
while(len >= 0 &&
(str[len - 1] == ' ' || str[len - 1] == '\t' || *str == '\n')
{
*(str + len - 1) = '\0';
len--;
}
printf(":%s:\n", str);
Ответ 15
void removeSpaces(string& str)
{
/* remove multiple spaces */
int k=0;
for (int j=0; j<str.size(); ++j)
{
if ( (str[j] != ' ') || (str[j] == ' ' && str[j+1] != ' ' ))
{
str [k] = str [j];
++k;
}
}
str.resize(k);
/* remove space at the end */
if (str [k-1] == ' ')
str.erase(str.end()-1);
/* remove space at the begin */
if (str [0] == ' ')
str.erase(str.begin());
}
Ответ 16
string trim(const string & sStr)
{
int nSize = sStr.size();
int nSPos = 0, nEPos = 1, i;
for(i = 0; i< nSize; ++i) {
if( !isspace( sStr[i] ) ) {
nSPos = i ;
break;
}
}
for(i = nSize -1 ; i >= 0 ; --i) {
if( !isspace( sStr[i] ) ) {
nEPos = i;
break;
}
}
return string(sStr, nSPos, nEPos - nSPos + 1);
}
Ответ 17
Для начального и конечного пробелов, как насчет:
string string_trim(const string& in) {
stringstream ss;
string out;
ss << in;
ss >> out;
return out;
}
Или для предложения:
string trim_words(const string& sentence) {
stringstream ss;
ss << sentence;
string s;
string out;
while(ss >> s) {
out+=(s+' ');
}
return out.substr(0, out.length()-1);
}
Ответ 18
с иголочки
void trimLeftTrailingSpaces(string &input) {
input.erase(input.begin(), find_if(input.begin(), input.end(), [](int ch) {
return !isspace(ch);
}));
}
void trimRightTrailingSpaces(string &input) {
input.erase(find_if(input.rbegin(), input.rend(), [](int ch) {
return !isspace(ch);
}).base(), input.end());
}
Ответ 19
Нет boost
, нет regex
, только библиотека string
. Это так просто.
string trim(const string s) { // removes whitespace characters from beginnig and end of string s
string x = s;
for(uint i=0; i<(uint)s.length(); i++) {
const int l = (int)x.length()-1;
if(x[l]==' '||x[l]=='\t'||x[l]=='\n'||x[l]=='\v'||x[l]=='\f'||x[l]=='\r'||x[l]=='\0') x.erase(l, 1);
if(x[0]==' '||x[0]=='\t'||x[0]=='\n'||x[0]=='\v'||x[0]=='\f'||x[0]=='\r'||x[0]=='\0') x.erase(0, 1);
}
return x;
}
Ответ 20
Как насчет стирать-удалить идиому?
std::string s("...");
s.erase( std::remove(s.begin(), s.end(), ' '), s.end() );
К сожалению. Я слишком поздно заметил, что вы не хотите удалять все пробелы.
Ответ 21
Мое решение этой проблемы, не использующее какие-либо методы STL, но только собственные методы С++ string:
void processString(string &s) {
if ( s.empty() ) return;
//delete leading and trailing spaces of the input string
int notSpaceStartPos = 0, notSpaceEndPos = s.length() - 1;
while ( s[notSpaceStartPos] == ' ' ) ++notSpaceStartPos;
while ( s[notSpaceEndPos] == ' ' ) --notSpaceEndPos;
if ( notSpaceStartPos > notSpaceEndPos ) { s = ""; return; }
s = s.substr(notSpaceStartPos, notSpaceEndPos - notSpaceStartPos + 1);
//reduce multiple spaces between two words to a single space
string temp;
for ( int i = 0; i < s.length(); i++ ) {
if ( i > 0 && s[i] == ' ' && s[i-1] == ' ' ) continue;
temp.push_back(s[i]);
}
s = temp;
}
Я использовал этот метод для передачи проблемы LeetCode Обратные слова в строке
Ответ 22
void TrimWhitespaces(std::wstring& str)
{
if (str.empty())
return;
const std::wstring& whitespace = L" \t";
std::wstring::size_type strBegin = str.find_first_not_of(whitespace);
std::wstring::size_type strEnd = str.find_last_not_of(whitespace);
if (strBegin != std::wstring::npos || strEnd != std::wstring::npos)
{
strBegin == std::wstring::npos ? 0 : strBegin;
strEnd == std::wstring::npos ? str.size() : 0;
const auto strRange = strEnd - strBegin + 1;
str.substr(strBegin, strRange).swap(str);
}
else if (str[0] == ' ' || str[0] == '\t') // handles non-empty spaces-only or tabs-only
{
str = L"";
}
}
void TrimWhitespacesTest()
{
std::wstring EmptyStr = L"";
std::wstring SpacesOnlyStr = L" ";
std::wstring TabsOnlyStr = L" ";
std::wstring RightSpacesStr = L"12345 ";
std::wstring LeftSpacesStr = L" 12345";
std::wstring NoSpacesStr = L"12345";
TrimWhitespaces(EmptyStr);
TrimWhitespaces(SpacesOnlyStr);
TrimWhitespaces(TabsOnlyStr);
TrimWhitespaces(RightSpacesStr);
TrimWhitespaces(LeftSpacesStr);
TrimWhitespaces(NoSpacesStr);
assert(EmptyStr == L"");
assert(SpacesOnlyStr == L"");
assert(TabsOnlyStr == L"");
assert(RightSpacesStr == L"12345");
assert(LeftSpacesStr == L"12345");
assert(NoSpacesStr == L"12345");
}