Инициализировать вектор с вектором? - PullRequest
0 голосов
/ 24 марта 2020

можем ли мы инициализировать вектор в c ++ с функцией возврата вектора типа.

#include <sstream>
#include <vector>
#include <iostream>
using namespace std;

vector<int> parseInts(string str) {
    // Complete this function
}

int main() {
    string str;
    cin >> str;
    vector<int> integers = parseInts(str); /** here is the problem **/
    for(int i = 0; i < integers.size(); i++) {
        cout << integers[i] << "\n";
    }

    return 0;
}

Ответы [ 3 ]

0 голосов
/ 24 марта 2020
#include <sstream>
#include <vector>
#include <iostream>
using namespace std;

vector<int> parseInts(string str) {
    vector <int> hello;
    int n,ele;
    stringstream geek(str);              // object from the class stringstream 
    geek>>n;               //converts to int
    for(int i=0;i<n;i++)
    {
        cin>>ele;
        hello.push_back(ele);
    }
    return hello;
}

int main() {
    string str;
    cin >> str;
    vector<int> integers = parseInts(str); /** here is the problem **/
    for(int i = 0; i < integers.size(); i++) {
        cout << integers[i] << "\n";
    }
    system("pause");
    return 0;
}
0 голосов
/ 25 марта 2020

Да, можно вернуть std::vector из функции. И с этим мы можем, как сказано в ваших словах, «Инициализировать вектор с вектором». В C ++ мы можем использовать RVO, оптимизацию возвращаемого значения. Вы можете прочитать здесь о копировании elision и RVO. В основном это говорит о том, что у вас не будет проблем с копированием байтов при возврате контейнеров из функции по значению. Теперь это даже рекомендуемый способ сделать это.

Итак, вы можете (и должны) вернуть std::vector из функции. Компилятор позаботится о том, чтобы это работало оптимизированным образом.

Но сначала посмотрите на приведенный ниже пример:

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>

std::vector<int> parseInts(std::string str) {

    // Put the string into a stream
    std::istringstream iss{ str };

    // Return the vector of ints 
    return { std::istream_iterator<int>(iss), {} };
}

int main() {
    // Test data
    std::string test{ "1 2 3 4 5 6 7 8 9 10" };

    // Get the vector with the ints
    std::vector ints = parseInts(test);

    // Show output
    for (const int i : ints) 
        std::cout << i << "\n";
    return 0;
}

У нас есть функция с именем parseInts, состоящая всего из 2 строк. кода.

Сначала мы помещаем строку в поток istring. При этом можно будет извлечь int из нового потока, как в

std::istringstream iss{ str };
int i1, i2;
iss >> i1 >> i2;

Оператор экстрактора >> будет «извлекать» целочисленные значения, разделенные пробелом, из потока (строки).

Но, если мы посмотрим на это, мы увидим, что тогда нам нужно знать количество целых чисел в строке, а затем многократно писать «>>». Для повторного выполнения одного и того же количества элементов, например целых чисел, у нас есть итераторы в C ++. С помощью итераторов вы можете перебирать похожие элементы в контейнере. Если вы предполагаете, что строка является контейнером, вы, конечно, можете перебирать целые числа в ней. Есть доступные итераторы, которые делают это для нас.

В случае потока у нас есть std :: istream_iterator . Эта вещь будет перебирать все разделенные пробелами элементы определенного типа во входном потоке и возвращать значения.

Многие значения, которые возвращает этот итератор, лучше всего хранить в std::vector, потому что это динамически растущий контейнер. Идеально для нас, потому что мы заранее не знаем количество целых чисел в потоке.

Если мы посмотрим на std::vector, мы обнаружим, что у него есть так называемый конструктор диапазона. Пожалуйста, смотрите здесь: конструктор диапазона (число 5) .

С помощью конструктора диапазона мы определяем переменную типа std::vector и инициализируем ее с помощью итератора «начало» и «конец» , Значения в этом диапазоне будут помещены в вектор.

Если мы определим переменную типа std::vector в нашем примере, мы могли бы написать:

std::vector<int> intv{ std::istream_iterator<int>(iss), std::istream_iterator<int>() };

или

std::vector<int> intv( (std::istream_iterator<int>(iss)), std::istream_iterator<int>() );

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

Но мы все равно не будем его использовать. Потому что с равномерной инициализацией и {} -initializer в качестве инициализатора по умолчанию. Мы можем использовать по умолчанию 2-й параметр. Теперь мы можем написать:

std::vector<int> intv(std::istream_iterator<int>(iss), {});

Итак, далее мы можем использовать CTAD, Вычет аргумента шаблона класса . По сути, компилятор знает из параметров конструктора, какой тип контейнера он будет создавать. Так что нет необходимости писать это.

Теперь:

std::vector intv(std::istream_iterator<int>(iss), {});

Это выглядит уже очень хорошо, и теперь вы можете вернуть переменную intv.

Но это еще не все. Компилятор знает тип функции и что она должна возвращать. Таким образом, вы можете использовать инициализированный скобками и возвращать это, и компилятор знает, что вы хотите вернуть std::vector<int>

Итак, последнее утверждение:

return { std::istream_iterator<int>(iss), {} };

Надеюсь, это поможет .

И извините за длинное описание для одной строки кода.

0 голосов
/ 24 марта 2020
#include <sstream>
#include <vector>
#include <iostream>
using namespace std;

vector<int> parseInts(string str) {    //this line tells that function will return an integer vector
    vector <int> hello;
    int n,ele;
    cout<<"Enter An Integer:";
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>ele;
        hello.push_back(ele);
    }
    return hello;           //vector named hello returned to main function
}

int main() {
    string str;
    cin >> str;
    vector<int> integers = parseInts(str); /** here is the problem **/
    for(int i = 0; i < integers.size(); i++) {
        cout << integers[i] << "\n";
    }
    return 0;
}

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...