Почему segmentation fault то появляется, то исчезает?
Решал такую задачу: Девочка Грета занимается исследованиями в области глобального потепления. Грета замеряла температуру на улице в течение N дней. Теперь ей интересна следующая статистика: для каждой температуры в интервале [−T;T] узнать номера дней, в которые держалась данная температура.
Входные данные
В первой строке входных данных содержатся два натуральных числа: T и N (T≤60, N≤1000). В следующей строке содержатся N целых чисел, по модулю не превосходящих 100 — измерение температуры в каждый из дней. Дни нумеруются с единицы.
Выходные данные
Выведите 2T+1 строк. Каждая строка должна содержать данные о днях, в которые держалась данная температура. Используйте формат вывода в соответствии с примером. Температуры необходимо выводить в порядке от меньшей к большей. Дни для каждой температуры необходимо выводить в порядке возрастания.
Вот мой код:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int t, n;
cin >> t >> n;
vector <vector <int> > ans(2*t + 1);
for (int i = 1; i <= n; ++i) {
int temp;
cin >> temp;
ans[temp + t].push_back(i);
}
for (int temp = 0; temp <= 2*t; ++temp) {
cout << temp - t << ": ";
for (int j = 0; j < ans[temp].size(); ++j) {
cout << ans[temp][j] << " ";
}
cout << endl;
}
return 0;
}
Вопрос заключается в том, что когда я ввожу например:
5 10 2 -6 0 4 4 0 -4 -5 -3 2
То дальше программа либо выводит результат:
-5: 8 -4: 7 -3: 9 -2: -1: 0: 3 6 1: 2: 1 10 3: 4: 4 5 5:
Любо segmentation fault. Из-за чего в данном случае происходит segmentation fault, и почему при одних и тех же входных данных в одних случаях мы получаем ошибку, а в других нет?
Ответы (2 шт):
Вы видимо хотели иметь вектор, в котором будет вектор из 2 значений - номер дня и температура в этот день. Тогда вы немного неправильно вносите данные, должно быть вот так:
for (int i = 1; i <= n; ++i)
{
int temp;
cin >> temp;
ans.push_back({ i, temp});
}
Но как написал @Harry from Kiev в данном случае лучше использовать вектор пар, или вектор собственной структуры из 2 элементов.
struct Day
{ int day;
int temp;
}
vector<Day> ans(2*t + 1);
// или
vector< pair<int,int> > ans(2*t + 1);
Если дальше смотреть условия вашей задачи, то болеее оптимальным будет использование вместо vector<> контейнера map<> (или multimap<>, если температура может повторяться), который хранит пары из ключа и значения. Тогда ключом будет температура, а значением - номер дня. В этом случае и сортировка сразу происходит - в map<> данные хранятся в отсортированном виде.
map<int,int> ans;
for (int i = 1; i <= n; ++i)
{
int temp;
cin >> temp;
ans[temp] = i; // если элемента с таким ключом нет, то он вставляется
}
нужно создать вектор который в свою очередь состоит из векторов произвольной длины(температура и произвольное количество дней, в которые была данная температура). И сделать это нужно пользуясь минимумом инструментов, т.е самим вектором и циклом for, не прибегая к использованию вектора собственной структура и контейнеру map.
Тогда так: первый вектор будет из 201 элемента vector <vector > ans(201) - температура от -100 до 100 и плюс 0. А в конечных векторах - номера дней. Тогда чтобы обращаться по температуре как по индексу нужно добавлять к температуре 100 - тогда в ans[0] будет храниться массив дней для температуры -100, в ans[100] - для температуры 0, в ans[200] для температуры +100:
vector <vector <int> > ans(201);
for (int i = 1; i <= n; ++i)
{
int temp;
cin >> temp;
ans[temp + 100].push_back(i);
}
И всё-таки проверяйте вводимые значения на корректность условиям задачи. Т.е. вводимые температуры должны лежать в диапазоне -100 < temp < +100. Иначе т.к. значение температуры используется как индекс, при некорректном вводе всё равно будет выход за границы массива и неопределенное поведение программы.