Подтвердить что ты не робот

Удаление начальных и конечных пробелов из строки

Как удалить пробелы из строкового объекта в С++.
Например, как удалить ведущие и конечные пробелы из ниже строкового объекта.

//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, повторно на границах слов, чтобы получить желаемое форматирование.
4b9b3361

Ответ 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);
}

Ответ 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");
}