C++: Необработанное исключение - нарушение прав доступа при записи по адресу
Нужно создать массив студентов, информация о которых приведена в файле. Студент - это класс. Проблема возникает в функции считывания данных из файла. Сам файл выглядит так:
4
Belkin 2006 75 81 92 5 4 4 5
Sokolov 2007 82 90 90 4 4 4 3
Fedorov 2006 60 61 70 5 5 5 5
Smirnov 2005 100 100 100 5 3 2 2
Его конфигурацию я могу менять. Первая строка - количество студентов, далее в каждой строке: фамилия, год рождения, 3 числа - результаты ЕГЭ и 4 числа - оценки за сессию. Для считывания из файла написал такую функцию:
student* read_st()
{
int col;
char s[20];
int y;
int e[3];
int se[4];
FILE* file = fopen("st.txt", "r");
if (!file)
{
printf("error opening");
}
fscanf(file, "%d\n", &col);
student* st = new student[col];
for (int i = 0; i < col; i++)
{
fscanf(file, "%s %d %d %d %d %d %d %d %d\n", s, &y, &e[0], e[1], &e[2], &se[0], &se[1], &se[2], &se[3]);
st->put_s(s);
st->put_y(y);
st->put_e(e);
st->put_se(se);
}
return st;
}
Она сначала определяет количество студентов, а потом записывает нужные значения в соответствующие переменные. Строки fscanf(file, "%d\n", &col); student* st = new student[col]; работают корректно.
Проблема возникает на этом этапе
fscanf(file, "%s %d %d %d %d %d %d %d %d\n", s, &y, &e[0], e[1], &e[2], &se[0], &se[1], &se[2], &se[3]);
с первой же переменной s - вылезает необработанное исключение. Если поставить 20 перед s (%20s), ничего не меняется. При этом если сразу после %s поставить любое число или цифру (%s20, например) - проблема исчезает и появляется новая - корректно считывается фамилия, но дальнейшие переменные не заполняются. На следующем шаге цикла в s записывается следующее значение из той же строки, в данном случае - 2006, на следующем - 75 и т.д. Для параметра s нужно использовать char по условию, я пользуюсь Visual Studio 2022. Подскажите, пожалуйста, как правильно считать все значения из файла
Заработало вот так:
fscanf(file, "%s %d %d %d %d %d %d %d %d\n", s, &y, &e[0], &e[1], &e[2], &se[0], &se[1], &se[2], &se[3]);
Видимо, ошибка была в , e[1], , не было &
Ответы (1 шт):
Где-то так
#include <iostream>
#include <cstdint>
#include <fstream>
#include <vector>
#include <sstream>
#include <string>
struct USE {
uint8_t first;
uint8_t second;
uint8_t third;
};
struct Session {
uint8_t first, second, third, forth;
};
class Student {
public:
Student(const std::string& sn, uint16_t y, USE use, Session se)
: m_Surname(sn),
m_Year(y),
m_Use(std::move(use)),
m_Session(std::move(se)) {};
auto getName() const noexcept {
return m_Surname;
}
auto getYear() const noexcept {
return m_Year;
}
auto getUse() const noexcept {
return m_Use;
}
auto getSession() const noexcept {
return m_Session;
}
private:
std::string m_Surname = "undefined";
uint16_t m_Year = 0;
USE m_Use = {0, 0, 0};
Session m_Session = {0, 0, 0, 0};
};
class VecOfStudents {
public:
VecOfStudents(std::ifstream& file, uint8_t col) {
m_Students.reserve(col);
std::string line;
std::string name;
uint16_t year;
uint8_t values[7];
while (std::getline(file, line)) {
std::istringstream iss(line);
iss >> name >> year;
for (uint8_t i = 0; i < 7; ++i) {
iss >> values[i];
}
m_Students.emplace_back(
name,
year,
USE {values[0], values[1], values[2]},
Session {values[3], values[4], values[5], values[6]}
);
}
}
auto getVec() const noexcept {
return m_Students;
}
private:
std::vector<Student> m_Students;
};
int main() {
uint8_t col;
std::cin >> col;
std::ifstream file("st.txt");
if (!file) {
std::cout << "ERROR\n";
return EXIT_FAILURE;
}
VecOfStudents ss(file, col);
for (auto& i: ss.getVec()) {
std::cout << i.getName() << " " << i.getYear() << " "
<< static_cast<int>(i.getUse().first) << " "
<< static_cast<int>(i.getUse().second) << " "
<< static_cast<int>(i.getUse().third) << " "
<< static_cast<int>(i.getSession().first) << " "
<< static_cast<int>(i.getSession().second) << " "
<< static_cast<int>(i.getSession().third) << " "
<< static_cast<int>(i.getSession().forth) << "\n";
}
}
Где st.txt:
Ivanov 2000 90 85 95 4 5 4 5
Petrov 2001 80 75 85 3 4 3 4