Некоторые комментарии:
Не пишите свой собственный вид.
STL имеет собственные встроенные алгоритмы сортировки.
Все, что вам нужно сделать, это указать отношения между объектами:
bool operator<(student const& lhs,student const& rhs)
{
return lhs.GetName() < rhs.GetName();
}
// Now a sort is:
std::sort(list.begin(),list.end());
Не использовать: while (! File.eof ())
Это стандартный шаблон для чтения файла.
Проблема в том, что еще слишком рано или два поздно для теста. Если вы ничего не читали, это два рано, так как ничего не произошло. Если вы что-то прочитали, значит, уже слишком поздно, поскольку вы выполнили обработку прочитанного элемента (но не смогли).
Лучший способ - поместить чтение в цикл while. Это потому, что результат чтения возвращает ссылку на поток. Это может быть автоматически преобразовано в объект, который может быть использован в логическом контексте (тест преобразования, чтобы увидеть, если что-то не так с потоком). Таким образом, ошибка чтения оставит поток в состоянии, которое приведет к его преобразованию в эквивалент false в логическом контексте.
std::string line;
while(std::getline(file,line))
{
// loop only entered if getline() worked.
// Thus we know that we have a good value in line.
// use line
}
Не используйте магические числа:
Вы действительно игнорируете 8000 символов или просто пытаетесь удалить строку?
file.ignore(8196,'\n');
У вас есть две альтернативы:
std::string ignoreLine;
std::getline(file,ignoreLine);
// Dont use a magic number but use a number that is guranteed not to fail.
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
Не ленитесь:
Главное в программировании - написание поддерживаемого кода.
Использование такого рода инициализации (относительно универсально) осуждается как просто ленивый. Разместите каждое объявление в отдельной строке. Это облегчает чтение кода.
string tempname, tempgrade, tempcourse = "";
// Like this:
std::string tempname;
std::string tempgrade;
std::string tempcourse;
Используйте поток строк, чтобы разбить строку на части
Я не уверен, что вы пытаетесь здесь?
if (file != "\n")
{ getline(file, tempname, ',');
getline(file, tempcourse, ',');
getline(file, tempgrade, ',');
}
Я думаю, что было бы легче читать, если бы мы объединили его с циклом выше:
std::string line;
while(std::getline(file,line))
{
std::stringstream linestr(line);
if (getline(linestr, tempname, ',') &&
getline(linestr, tempcourse, ',') &&
getline(linestr, tempgrade, ',')
)
{
// Here we have read a line.
// And successfully retrieved three comma separated values from the line
}
}
При появлении возможности замените цикл стандартным алгоритмом
Этот цикл печати можно заменить на std :: copy ()
for (int i = 0; i < StudentList.size(); i++)
{ cout << StudentList[i].GetName() << " "
<< StudentList[i].GetCourse() << " "
<< StudentList[i].GetGrade() << endl;
}
Все, что вам нужно сделать, это определить оператор вывода для вашего класса.
std::ostream& operator<<(std::ostream& str,student const& data)
{
str << data.getName() << " "
<< data.getCourse() << " "
<< data.getGrade() << " "; // No newline here.
return str;
}
Теперь мы можем скопировать вектор в std :: cout
std::copy(StudentList.begin(),StudentList.end(),
std::ostream_iterator<student>(std::cout,"\n")
);
Основная ошибка.
Основная ошибка, которую я вижу, это строка:
if (file != "\n")
Здесь вы сравниваете файл с «C-строкой». Как компилятору удается это скомпилировать, я не уверен.
На ум приходят несколько вариантов, но тот факт, что он неочевиден, делает его вероятным источником ошибок. Также обратите внимание, что это не то, как вы сравниваете две строки (если только одна не является std :: string).
Я думаю, что компилятор преобразует файл в указатель и сравнивает его с "C-String" (поскольку это также просто указатель). Вы можете подумать, что это немного странно, но есть оператор, который преобразует файл в пустоту *. Указатель не указывает на что-либо значимое, но имеет значение NULL или не NULL и может сравниваться с указателем char *, что приводит к значению true (поскольку оно никогда не равно строке "\ n").