Пойдемте, подумайте, что это бит за шагом
int main()
{
std::stringstream stream;
stream
здесь не используется. А пока давайте избавимся от этого. Однако он вернется позже.
std::string current;
Student temp;
Student *database = new Student[50];
Это создаст 50 Student
с.
inFile.open("students.dat", std::ifstream::in);
outFile.open("FullReport.txt",std::ofstream::out);
Открывает файлы. Можно сделать немного лучше, но правильно.
while(getline(inFile,current))
{
Отлично. Получил строку из файла.
for(int i = 0; i < 50; i++)
С этой одной строкой из файла сделайте то же самое 50 раз. Спросите у резиновой утки , считает ли это, что это имеет смысл.
{
Student[i] = new Student(current);
Student
- это тип, а не переменная. Вы не можете хранить в типе. Скорее всего, вы должны использовать database
, но это массив Student
с, а new Student(current)
предоставляет указатели на Student
с.
outFile << Student[i] <<std::endl;
}
inFile.close();
outFile.close();
Закрытие файлов слишком рано. Вы еще не прочитали всех студентов.
}
}
Как исправить:
int main()
{
std::string current;
Student **database = new Student*[50];
database
- это массив из 50 указателей на Student
с, все готовопринять new Student
с. Но об этом позже.
std::ifstream inFile("students.dat");
std::ofstream outFile("FullReport.txt");
Если мы определим здесь файловые потоки и укажем направление (ifstream
, ofstream
), нам не нужно его указывать снова. Плюс мы можем открыть файл прямо в конструкторе. Кому нужны грязные звонки на open
? Наконец, поскольку файлы являются локальными переменными, они будут автоматически уничтожены и закрыты в конце функции. Не нужно беспорядочно звонить на close
. (См. Что подразумевается под Resource Acquisition под инициализацией (RAII)? , чтобы узнать больше об этой концепции). Код, который вам не нужно писать, не содержит ошибок. И если это так или иначе, они не ваша вина.
int count = 0;
count
- гораздо более описательное имя, чем i
while (std::getline(inFile, current))
{
, здесь ничего не изменилось. Это фантастика. Есть знаменитый вопрос о переполнении стека, который известен тем, что многие ошибаются. Престижность. Вы правильно поняли.
database[count] = new Student(current);
новый Student
выделен и добавлен в базу данных. Подробнее об этом позже.
outFile << *database[count] << std::endl;
И записано в выходной файл. Обратите внимание на *
, чтобы разыменовать указатель и получить значение, на которое он указывает, чтобы его можно было печатать с помощью обычного оператора <<
(который, кстати, вы должны указать). Без *
программа распечатает содержимое указателя: адрес.
count++;
}
}
И еще раз без объяснения причин простого чтения кода
int main()
{
std::string current;
Student **database = new Student*[50];
std::ifstream inFile("students.dat");
std::ofstream outFile("FullReport.txt");
int count = 0;
while (std::getline(inFile, current))
{
database[count] = new Student(current);
outFile << *database[count] << std::endl;
count++;
}
}
ОК, это позже. Вы не хотите
Student **database = new Student*[50];
Это довольно грубо по нескольким причинам.
- Современные компьютеры отлично умеют мыслить прямолинейно. Если данные находятся на одной прямой линии, они могут прочитать вперед и подготовить данные, прежде чем они вам понадобятся. Массивы данных потрясающие. Массивы указателя на данные не позволяют компьютеру набрать скорость. Он читает один
Student
, затем должен найти другой указатель, чтобы найти следующий Student
. Это может быть медленно. Калеки медленно. С массивом Student
с, когда вы используете Student
0, компьютер загружает (или уже загрузился, когда загрузил Student
0) следующую связку Student
с. - КаждыйДинамическое распределение имеет стоимость. Программа должна запросить у ОС блок памяти. ОС должна его найти. Это может быть дорого. Намного лучше получить один большой блок памяти и разделить его на массив
Student
с. - Каждое динамическое распределение должно быть убрано. Выделите 50
Student
с, и вам нужен код, который убирает 50 Student
с. Выделите массив из Student
s, вы уберете один массив из Students
Вы хотите что-то более похожее на
int main()
{
std::string current;
Student *database = new Student[50];
std::ifstream inFile("students.dat");
std::ofstream outFile("FullReport.txt");
int count = 0;
while (std::getline(inFile, current))
{
database[count] = Student(current);
outFile << *database[count] << std::endl;
count++;
}
}
И, конечно же, вы действительно хотите
int main()
{
std::string current;
std::vector<Student> database;
std::ifstream inFile("students.dat");
std::ofstream outFile("FullReport.txt");
while (std::getline(inFile, current))
{
database.emplace_back(current);
outFile << database.back() << std::endl;
count++;
}
}
Но это даст хороший круглый ноль от инструктора. Первое правило школы - дать учителю то, что он хочет, и пройти курс. Второе правило - прочитайте кучу других вещей, чтобы узнать, чему вас не учили, так что вы не будете бесполезны после выпуска.