Универсальный ">>" для вектора - PullRequest
0 голосов
/ 29 сентября 2019

Я только что узнал об операторах перегрузки и решил перегрузить оператор >> для вектора. Я не уверен, что это правильный способ сделать это, но он работает.

void operator >> (istream &in, vector<int> &_vector)
{
    int vectorSize;
    cout << "Enter vector size\n";
    cin >> vectorSize;

    _vector = vector<int>(vectorSize);

    cout << "Enter the array\n";
    for (int &element : _vector)
        in >> element;
}

Но потом я понял, что этот метод работает только для vector<int> и не работает для других векторов. Как сделать его универсальным и работать с любым вектором?

Ответы [ 2 ]

1 голос
/ 29 сентября 2019

С минимальными изменениями:

template <class T>
void operator >> (istream &in, vector<T> &_vector)
{
    int vectorSize;
    cout << "Enter vector size\n";
    cin >> vectorSize;

    _vector = vector<T>(vectorSize);

    cout << "Enter the array\n";
    for (T &element : _vector)
        in >> element;
}

Обратите внимание, что в код необходимо внести множество улучшений: используйте std::size_t, используйте std::vector::resize(), избегайте std::cin/cout внутри оператора, избегайте using namespace std;, верните соответствующий тип, избегайте идентификаторов, которые начинаются с _ (даже если они действительны здесь) ... Кроме того, все остальное, что они сказали вам также в комментариях к вопросу.

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

Мне было весело с этим. Вот мое:

Исходный файл json-style-vector-input.cpp:

#include <vector>
#include <iostream>
#include <utility>
#include <string_view>
#include <string>

using namespace std::literals;

template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T> &v) {
    std::string_view separator = "";
    constexpr std::string_view comma = ", ";
    os << '[';
    for(const auto &i: v) {
        os << separator;
        separator = comma;
        os << i;
    }
    os << ']';
    return os;
}

template<typename T>
std::istream& operator>>(std::istream& is, std::vector<T> &v) {
    char c;
    is >> c;
    if(c != '[') {
        is.setstate(std::ios::failbit);
        return is;
    }
    v.clear();
    bool done = false;
    while(!done) {
        T tmp;
        is >> tmp;
        if(!is) return is;
        v.push_back(std::move(tmp));
        is >> c;
        if(!is) return is;
        if(c == ']') {
            done = true;
        } else if(c != ',') {
            is.setstate(std::ios::failbit);
            done = true;
        }
    }

    return is;
}

std::ostream& operator<<(std::ostream &os, const std::ios::iostate &state) {
    using std::ios;
    if(state == ios::goodbit) os << "goodbit"sv;
    if((state & ios::badbit) == ios::badbit) os << "badbit"sv;
    if((state & ios::failbit) == ios::failbit) os << "failbit"sv;
    if((state & ios::eofbit) == ios::eofbit) os << "eofbit"sv;
    return os;
}

template<typename Ch = char>
class quoted_string : public std::basic_string<Ch> {
};

template<typename Ch>
std::istream& operator>>(std::istream &is, quoted_string<Ch> &s) {
    char c;
    is >> c;
    if(!is) return is;
    if(c != '"') {
        is.setstate(std::ios::failbit);
        return is;
    }
    std::getline(is, s, '"');
    while(s.length() > 0 && s[ s.length()-1 ] == '\\') {
        s[ s.length()-1 ] = '"';
        std::basic_string<Ch> more;
        std::getline(is, more, '"');
        s += more;
    }
    return is;
}

template<typename Ch>
std::ostream& operator<<(std::ostream &os, const quoted_string<Ch> &s) {
    os << '"';
    if( s.find('"') != std::basic_string<Ch>::npos ) {
        for( const auto& c: s ) {
            if( c == '"' ) os << '\\';
            os << c;
        }
    } else {
        os << static_cast<std::basic_string<Ch>>(s);
    }
    os << '"';
    return os;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::vector<int> a;
    std::cin >> a;
    if(!std::cin) {
        std::cout << "input failure: "sv << std::cin.rdstate() << std::endl;
        std::cin.clear();
    }
    std::cout << a << std::endl;

    std::vector<quoted_string<char>> b;
    std::cin >> b;
    if(!std::cin) {
        std::cout << "input failure: "sv << std::cin.rdstate() << std::endl;
        std::cin.clear();
    }
    std::cout << b << std::endl;
    return 0;
}

Команда сборки (Linux):

g++ -Wall -W -pedantic -g -pthread -O3 -flto -fno-fat-lto-objects  -std=c++17   -pthread  json-style-vector-input.cpp   -o json-style-vector-input

Тестовый файл test2.txt:

[1,99,2222]
["fred", "string with spaces", "", "another space string",
"string \"string\" string"]

Команда тестирования:

$ ./json-style-vector-input <test2.txt 
[1, 99, 2222]
["fred", "string with spaces", "", "another space string", "string \"string\" string"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...