У меня проблемы с разбиением строки на вектор - PullRequest
0 голосов
/ 25 сентября 2019

Я пытаюсь написать код, который инициализирует строку в вектор, разбивая ее на каждый пробел.Каким-то образом временный вектор не займет позиции, и он не разделит строку правильно.

#include <iostream>
#include <string>
#include <vector>

std::vector<std::string> splitStr(std::string s, char cut = 32) {
    std::string temp = s;
    int begin = 0;
    std::vector<std::string> v;
    for (int i = 0; i < temp.length() - 1; ++i) {
        if ((int) cut == (int) temp[i]) {
            v.push_back(temp.substr(begin, i));
            begin = i + 1;
        }
    }
    return v;
}


using namespace std;


int main() {

    for (string e : splitStr("Hello this is a test!", ' ')) {
        cout << e << endl;
    }

}

Я думаю, что это неправильно при добавлении к вектору, но я не понимаю, почему это так.Кто-нибудь из вас, ребята, может сказать, что я делаю не так?

Ответы [ 3 ]

0 голосов
/ 25 сентября 2019

Для начала не используйте магические числа, такие как 32.

Во-вторых, символ табуляции также может рассматриваться как пустой разделитель.Первый параметр должен быть константной ссылкой на строку.

Нет необходимости создавать копию параметра внутри функции.

Этот цикл

for (int i = 0; i < temp.length() - 1; ++i) {
    if ((int) cut == (int) temp[i]) {
        v.push_back(temp.substr(begin, i));
        begin = i + 1;
    }
}

не имеет смысла.Например, строка может содержать два последовательных пробела.Во-вторых, второй аргумент вызова substr temp.substr(begin, i) неверен.В нем должна быть указана длина подстроки,

Вместо цикла используйте стандартные функции-члены поиска класса std::string.

Вот демонстрационная программа, которая показывает, как эта функция может быть реализована..

#include <iostream>
#include <string>
#include <vector>

std::vector<std::string> splitStr( const std::string &s, 
                                   const std::string &delim = " \t" )
{
    std::vector<std::string> v;

    for ( std::string::size_type pos = 0, n = 0;
          ( pos = s.find_first_not_of( delim, pos ) ) != std::string::npos; 
          pos += n )
    {
        n = s.find_first_of( delim, pos );

        n = ( n == std::string::npos ? s.size() : n ) - pos;

        v.push_back( s.substr( pos, n ) );
    }

    return v;
}

int main() 
{
    for ( const auto &s : splitStr( "Hello this is a test!" ) )
    {
        std::cout << s << std::endl;
    }

    return 0;
}

Его вывод

Hello
this
is
a
test!
0 голосов
/ 25 сентября 2019

разделение на каждый пробел

Это разделит его на каждый пробел.Я прокомментировал изменения в коде.

#include <iostream>
#include <string>
#include <vector>

// don't use magic numbers like 32 for space. Use a literal space: ' '

// Instead of copying the string (potentially twice), use a reference to
// your input parameter and make it const if you are not going to change it.

std::vector<std::string> splitStr(const std::string& temp, char cut = ' ') {
    // Use types designed for the task to avoid casting, like
    // size_t for most indexing tasks.
    size_t begin = 0;
    std::vector<std::string> v;

    // with temp.length()-1 you won't capture a space at the very end
    for(size_t i = 0; i < temp.length(); ++i) {
        if(cut == temp[i]) {
            // the second argument to substr is the length of the sub string
            v.push_back(temp.substr(begin, i - begin));
            begin = i + 1;
        }
    }
    // add the remaining part of the string
    v.push_back(temp.substr(begin));
    return v;
}

// using namespace std; // don't do this globally

int main() {
    // added double spaces between words and one at the end for effect
    for(const std::string& e : splitStr("Hello  this  is  a  test! ", ' ')) {
        // added > and < around the words to see what you captured
        std::cout << '>' << e << '<' << std::endl;
    }
}

Вывод:

>Hello<
><
>this<
><
>is<
><
>a<
><
>test!<
><
0 голосов
/ 25 сентября 2019

Второй аргумент к substr - это количество символов, которое вы хотите выбрать из исходной строки, и если оно не будет передано, все символы будут приняты до конца строки.Вот ваш код с этими исправлениями:

  std::vector<std::string> splitStr(std::string s, char cut = 32) {
    std::string temp = s;
    int begin = 0;
    // Remove multiple spaces based on logic described here : /6741993/zamenit-neskolko-probelov-odnim-probelom-v-stroke
    std::string::iterator new_end = std::unique(temp.begin(), temp.end(), [](char one,char two) { return (one == two) && (one == ' '); } );
    temp.erase(new_end, temp.end());
    std::vector<std::string> v;
    for (int i = 0; i < temp.length() - 1; ++i) {
        if ((int) cut == (int) temp[i]) {
            v.push_back(temp.substr(begin, i-begin));
            begin = i + 1;
        }
    }
    v.push_back(temp.substr(begin));
    return v;
}
    using namespace std;


    int main() {

        for (string e : splitStr("Hello this is a test!", ' ')) {
            cout << e << endl;
        }

    }
...