Нужна помощь в завершении функции для сортировки k отсортированных потоков - PullRequest
0 голосов
/ 29 марта 2019

Я работаю над своим заданием и мне нужна помощь в выполнении следующей функции.Мне была предоставлена ​​следующая подпись:

void merge(const std::vector<istream>& inputStreams, ostream& o);

Функция должна принимать k целочисленные потоки в качестве входных данных и сортировать их и сохранять результат в ostream объекте,Я завершил определение функции, но проблема в том, что я не могу проверить функцию, предоставив ей входные данные (т. Е. Вектор объектов istream).Если я пытаюсь передать функции вектор объектов istream, компилятор выдает слишком много ошибок для отладки.Вот определение функции:

void merge( vector<istream>&  inputStreams, ostream&  o){
    vector<long long int> input_vec;
    long long int input_vec_size =  inputStreams.size();
    for(int i=0; i<input_vec_size;i++)
    {
        long long int temp;
        while(inputStreams[i]>>temp)
        {
            input_vec.push_back(temp);
        }
    }
    sort(input_vec.begin(),input_vec.end());
    for(int i=0;i<input_vec.size();i++)
    {
        o<<input_vec[i];
    }

}

И чтобы передать vector из istream объектов, я сделал следующее:

int main()
{
    //ifstream a1,a2,a3,a4;
    filebuf fb1,fb2,fb3;
    fb1.open("fb1.txt",ios::in);
    fb2.open("fb2.txt",ios::in);
    fb3.open("fb3.txt",ios::out);
    istream a1(&fb1);
    istream a2(&fb2);
    ostream out(&fb3);
    vector<istream> inp;
    inp.push_back(a1);        
    inp.push_back(a2);
    merge(inp,out);
}

Может кто-нибудь мне помочь?

Ответы [ 2 ]

3 голосов
/ 30 марта 2019

Для начала довольно необычно видеть тип istream, используемый в качестве фактического типа объекта.Причина этого в том, что istream предназначен для использования в качестве базового класса, и эти базовые классы используются чаще.Например, вы будете видеть переменные типа istringstream или типа ifstream гораздо чаще, чем просто старые istream.По сути, это не неправильно иметь переменную, которая будет честной istream, но это необычно.

Обычно, если вы хотите работать с функцией, которая манипулирует каким-либо потоком вводавы бы структурировали его так, чтобы оно либо содержало ссылку на istream, либо указатель на istream.Это общий C ++ способ обработки полиморфных типов.

В вашем случае тот факт, что вы пытаетесь использовать vector<istream>, независимо от того, будет ли код компилироваться или нет, должен заставить вас приостановитьМинуту, чтобы подумать, правильно ли ты поступаешь.Вполне возможно, что да, у вас действительно есть группа istream объектов, и эти объекты не являются istringstream s или ifstream s.Но более вероятно, что вы намеревались сделать здесь, сказали: «Я беру какой-то список входных потоков, и мне все равно, какие это входные потоки, если они наследуются от istream».

Если это то, что вы надеетесь сделать, есть несколько способов решить эту проблему.Возможно, проще всего изменить vector<istream> на vector<istream *> (или, возможно, vector<shared_ptr<istream>>, в зависимости от контекста).Это означало бы: «Я хотел бы взять в качестве входных данных список потоков, и, поскольку я не могу точно сказать, каким будет конкретный тип каждого из этих потоков, я просто сделаю так, чтобы клиент давал мне указатели на каждый из них».«.Это потребует от вас внесения некоторых изменений в ваш код, чтобы при доступе к элементам vector вы воспринимали их как указатели, а не как объекты istream.Например, строка

while (inputStreams[i] >> temp) { ... }

может потребоваться переписать как

while (*inputstreams[i] >> temp) { ... }

для явного разыменования указателя.

Другой вопрос, который вы задали, - как проверитьэтот код вообще, и это отдельный шаг.Помните, что довольно необычно создавать объекты типа istream, поэтому вы, вероятно, захотите создать объекты типа istringstream или ifstream.Вот пример того, как вы можете создать несколько потоков и затем передать их в свою функцию:

istringstream stream1("137 2718");
istringstream stream2("27 182 818");
istringstream stream3("3 14 15 92 653");

merge({ &stream1, &stream2, &stream3 }, cout);

Здесь, вместо того, чтобы объявлять локальную переменную типа vector<istream *>, мы просто используем инициализатор скобок дляскажите «пожалуйста, сделайте мне вектор из этих указателей».

Из предоставленного вами примера кода похоже, что вы хотите прочитать данные из группы файлов.Вот как вы можете это сделать.Вместо того, чтобы создавать filebuf объекты и оборачивать их в istream s, что является законным, но довольно редким, мы просто используем ifstream:

ifstream stream1("fb1.txt");
ifstream stream2("fb2.txt");
ifstream stream3("fb3.txt");

vector<istream *> inputs;
inputs.push_back(&stream1);
inputs.push_back(&stream2);
inputs.push_back(&stream3);

merge(inputs, cout);

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

1 голос
/ 30 марта 2019

istream не может быть скопирован или перемещен, поэтому вы не можете сделать vector из istream с. Попробуйте вместо этого использовать std::vector <std::istream *> (и соответственно измените код).

Демонстрация в реальном времени: https://wandbox.org/permlink/20I2VQqsRI8ofaxP

...