Замена контейнера multimap на multiset
Есть код программы, только в нём используется контейнер multimap, и строки с длиной больше 11 и меньше 20. В файл должны быть записаны только строки длиной больше 10 и меньше 50 символов. Использовать контейнер multiset<std::string, Compare>. Входной файл существует на диске, выходной файл создается программой.
Задача данной программы - вывод строк где больше 10 символов и меньше 20. Сейчас программа работает с контейнером multimap. Нужно чтобы программа работала с контейнером multiset и выводила строки где больше 10 символов и меньше 50, и чтобы эти строки были упорядочены по длине.
#include <stdio.h>
#include <iostream>
#include <set>
#include <exception>
#include <stdexcept>
int main() {
try {
FILE* filein;
FILE* fileout;
/*char name[256];
std::cout << "Enter the opening file's path:" << std::endl;
std::cin >> name;*/
/*char nameout[256];
std::cout << "Enter the saving file's path:" << std::endl;
std::cin >> nameout;*/
char name[] = "in.txt";
char nameout[] = "out.txt";
if ((filein = fopen(name, "r")) == NULL)
throw std::runtime_error("Can't open the file.");
if ((fileout = fopen(nameout, "w")) == NULL) {
fclose(filein);
throw std::runtime_error("Can't create the file.");
}
std::multiset<int, int, std::greater <int>> mySet; //создание контейнера
char str[1024];
int len;
int pos;
std::string s;
bool counter = 0;
while (!feof(filein)) {
if (fgets(str, 1024, filein)) {
std::cout << str;
s = str;
len = s.length();
pos = ftell(filein);
if (len >= 11 && len <= 21)
counter++;
mySet.insert(std::make_pair(len, pos - 1)); //заполнение контейнера
}
}
if (counter == 0) {
std::cout << '\n';
fclose(filein);
fclose(fileout);
throw std::runtime_error("Required strings are missing.");
}
std::cout << std::endl;
std::multiset<int, int>::iterator it; //объявление итератора
std::cout << "result:" << std::endl;
std::multiset<int, int>::iterator itlow, itup; //границы контейнера
itlow = mySet.lower_bound(51);
itup = mySet.upper_bound(11);
for (it = itlow; it != itup; ++it)
{
if ((it == mySet.end()) && (it->first >= 11) && (it->first <= 51)) //без доп условия последняя строка не выводится корректно
{
fseek(filein, it->second - it->first + 1, SEEK_SET);
fgets(str, it->first + 1, filein);
}
else
{
fseek(filein, it->second - it->first, SEEK_SET);
fgets(str, it->first, filein);
}
fputs(str, fileout);
fputs("\n", fileout);
//std::cout << it->first << "=" << it->second << std::endl;
std::cout << str << std::endl;
}
fclose(filein);
fclose(fileout);
}
catch (std::exception& exception)
{
std::cerr << "Standard exception: " << exception.what() << std::endl;
}
}
Ответы (1 шт):
Если - подчеркиваю - если ваш код работоспособен для multimap - в чем я не очень уверен, но не проверял (однако один лишь счетчик bool counter = 0; наводит на очень грустные размышления), то изменить его для multiset можно просто заменив ключ и значение на пару ключ/значение с компаратором, который сравнивает только ключи. Примерно так - определив компаратор наподобие
struct Cmp
{
bool operator()(const std::pair<int,int>& a,
const std::pair<int,int>& b) const
{
return a.first < b.first;
}
};
и изменив ваш "multiset<int,int>" на
std::multiset<std::pair<int,int>, Cmp> mySet;
Соответственно надо изменить и объявления итераторов - раз вас не устраивает auto, то
std::multiset<std::pair<int,int>, Cmp>::iterator itlow, itup;
а при поиске границ надо передавать пару, наподобие
itlow = mySet.lower_bound(std::make_pair(51,0));
Это - примерный план работ по замене. Еще раз повторюсь - я не проверял работоспособность вашего кода, но имею насчет этого большие сомнения...