3

Допустим, у меня есть структура

struct SCHOOL
{
    unsigned long mark;
    char subject[20];
    char surname[20];
    short age;
};

Для записи её в файл я написал функцию

SCHOOL setInfo()
{
    SCHOOL s;
    ofstream fout("out.txt", ios::app);                 
    cout << "mark: "; cin >> s.mark;
    cout << "subject: "; cin >> s.subject;
    cout << "surname: "; cin >> s.surname;
    cout << "age: "; cin >> s.age;
    fout.write((char*)&s, sizeof(SCHOOL));      
    fout.close();                               
} 

Как правильно написать функцию для считывания и потом работать с элементами структуры, например, вывести все фамилии с оценками 9?

Я написал такую функцию,

void getInfo()
{
    SCHOOL s;
    ifstream fin("out.txt", ios::in);
    while (!fin.eof())
    {
        fin.read((char*)&s, sizeof(SCHOOL));
    }
    fin.close();
}

Но она работает неправильно.

Alex.B
  • 925
  • 8
  • 24
MovieZ
  • 225
  • читайте по элементно, так же как и пишите. Ну или в бинарный режим перейдите файла. – pavel Mar 21 '17 at 10:33
  • ну вы все так делаете. и да выше вам это уже посоветовали, работайте с бинарным пердставлением так проще в том случае если вы работаетте с файлом только в программе. Ну единственное замечание передавайте свою структуру как парметр для функции записи и чтения, а не объявляйте ее локально иначе все, что вы читаете доступно только в вашей функции. – Alex.B Mar 21 '17 at 11:11

1 Answers1

3

Вот ваша структура

struct School
{
    unsigned long mark;
    char subject[20];
    char surname[20];
    short age;
};

Вот так лучше писать и читать

    void setInfo(School& school)
    {
        ofstream fout("out.txt", ostream::binary); //инициализация потока файла                
     //Заполнили структурку
        cout << "mark: "; cin >> school.mark;
        cout << "subject: "; cin >> school.subject;
        cout << "surname: "; cin >> school.surname;
        cout << "age: "; cin >> school.age;
//записали
        fout.write((char*)&school, sizeof(School));      
        fout.close();                               
    } 
    void getInfo(School& school)
    {
        ifstream fin("out.txt", ios::in);
        while (!fin.eof())
        {
            fin.read((char*)&school, sizeof(School));
        }
        fin.close();
    }

    int main()
    {
    School school;
    //так пишем
    setInfo(school);
    //так читаем
    getInfo(school);
    }

это что касается считывания из файла , далее для работы с множественными объектами струтктуры необходио использовать контейнеры, напрмиер vector или list.

вот пример функции которая запишет в файл все ваши объекты

void recAllSchoolObj(vector <School> vSchool)
{
   ostream fout("out.txt", ostream::binary)
   for(int i =0; i<=vSchool.size; ++i)
   {
     fout.write((char*)&vSchool.at(i), sizeof(School));
   }
    fout.close();
}

вот пример который прочитает

void readAllSchoolObj(vector <School> vSchool)
{
   School school;
  istream fin("out.txt");
  while(!fin.eof)
  {
    fin.read((char*)&school, sizeof(School));
     vSchool.push_back(school);  
   }
   fin.close;
}

поиск всех фамилий с одной оценкой

void findMark(vector <School> vSchool, unsigned long mark)
{
  cout<<"Surname "<<endl;
  for(int i =0; i<=vSchool.size; ++i)
  { 
    if(vSchool.at(i).mark == mark)
     cout<<vSchool.at(i).surname<<endl;

   }
}
pavel
  • 9,864
Alex.B
  • 925
  • 8
  • 24
  • и да еще момент, всетаки для строк, лучше использовать string или char* т.к. не всегда ясно сколько будет в строке символов. – Alex.B Mar 21 '17 at 11:20
  • вот зря вы изменили char* на string. String разве можно вот так писать в бинарном виде? Вы хоть на размер посмотрите файла после записи! Я изменения откатил, чтобы людей не смущало... – pavel Mar 21 '17 at 14:34
  • @Abyx это совет. Я например пишу часто. (я в конце строки /n не ставлю). – pavel Mar 21 '17 at 16:29
  • @Alex.B оффтопя: не надо делать такие правки http://s019.radikal.ru/i633/1703/16/173475efa386.jpg не делающие улучшения. .... https://ru.meta.stackoverflow.com/a/2417/191482 Если привилегии редактирования без проверки ещё нет, то вычисткой исключительно избыточного текста (без прочих исправлений) лучше не заниматься. – Алексей Шиманский Mar 24 '17 at 06:13
  • @Alex Добрый день. Ваша функция void recAllSchoolObj(vector vSchool) работать в таком виде точно не будет(на большее не стал проверять). Во-первых, тут ошибка for(int i =0; i<=vSchool.size; ++i) Нужно писать i < vSchool.size(); иначе будет ошибка "terminate called after throwing an instance of 'std::out_of_range'" - индексация то с нуля идет. И вы забылискобочки в конце добавить i<=vSchool.size – dio4 Sep 04 '21 at 08:22
  • @Alex Вынужден добавить, что функция чтения тоже не будет работать. Ошибки тут while(!fin.eof) и тут fin.close; и у меня сомнения по поводу использования в них ostream и istream у нас же файловые операции вроде. – dio4 Sep 04 '21 at 08:45