Обрезать пробелы из строки

Я знаю, что есть несколько способов сделать это в 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.

Ответ 1

Ваш код в порядке. То, что вы видите, является проблемой компоновщика.

Если вы поместите свой код в один файл следующим образом:

#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 в этап ссылки вашего процесса компиляции.

Ответ 2

Вот как вы можете это сделать:

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));
}

Попробуй это

Ответ 3

Я думаю, что substr() выдает исключение, если str содержит только пробелы.

Я бы изменил его на следующий код:

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));
}

Ответ 4

#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; });
}