👍 touch dbstu
👍 g++ personal.cpp student.cpp 
   database.cpp
👍 ./a.out
File name: dbstu
1. Add 2. Find 3. Modify a rec 4. Exit
Enter an option: 1
SSN: 111000111
Name: Peter
City: Toronto
Birthyear: 2005
Salary: 1002
Major: Computer
Enter an option: 4

👍 cat dbstu 
111000111PeterToronto??Computer%  

👍 cat personal.h
#ifndef PERSONAL
#define PERSONAL
#include <fstream>
using namespace std;
class Personal {
public:
  Personal();
  void writeToFile(fstream&) const;
  void readFromFile(fstream&);
  void readKey();
  int size() const {
    return 9 + nameLen + cityLen +
      sizeof(year) + sizeof(salary);
  }
  bool operator==(const Personal &p)
    const { 
    return strncmp(p.SSN,SSN,9) == 0;
  }
protected:
  const int nameLen, cityLen;
  char SSN[10], *name, *city
  int year;
  int salary;
  ostream& writeLegibly(ostream&);
  friend ostream& operator<<(
    ostream &o, Personal &p) {
    return p.writeLegibly(o);
  }
  istream& readFromConsole(istream&);
  friend istream& operator>>(
    istream &i, Personal &p) {
    return p.readFromConsole(i);
  }
};
#endif

👍 cat personal.cpp 
#include <iostream>
#include "personal.h"

Personal::Personal():
  nameLen(10), cityLen(10) {
  name = new char[nameLen + 1];
  city = new char[cityLen + 1];
}

void Personal::writeToFile(
  fstream &o) const {
  o.write(SSN, 9);
  o.write(name, nameLen);
  o.write(city, cityLen);
  o.write(
    reinterpret_cast<const char*>
      (&year), sizeof(int));
  o.write(
    reinterpret_cast<const char*>
      (&salary), sizeof(int));
}

void Personal::readFromFile(
  fstream &i) {
  i.read(SSN, 9);
  i.read(name, nameLen);
  i.read(city, cityLen);
  i.read(
    reinterpret_cast<const char*>
      (&year), sizeof(int));
  i.read(
    reinterpret_cast<const char*>
      (&salary), sizeof(int));
}

void Personal::readKey() {
  char s[80];
  cout << "Enter SSN: ";
  cin.getline(s, 80);
  strncpy(SSN, s, 9);
}

ostream& Personal::writeLegibly(
  ostream &o){
  SSN[9] = '\0';
  o << "SSN = " << SSN
    << ", name = " << name
    << ", city = " << city
    << ", year = " << year
    << ", salary = " << salary;
  return o;
} 

istream& Personal::readFromConsole(
  istream &i){
  SSN[9] = name[nameLen] 
         = city[cityLen] = '\0';
  char s[80];
  cout << "SSN: ";
  i.getline(s, 80);
  strncpy(SSN, s, 9);
  cout << "Name: ";
  i.getline(s, 80);
  strncpy(name, s, nameLen);
  cout << "City: ";
  i.getline(s, 80);
  strncpy(city, s, cityLen);
  cout << "Birthyear: ";
  i >> year;
  cout << "Salary: ";
  i >> salary;
  i.ignore();
  return i;
}

👍 cat student.h 
#ifndef STUDENT
#define STUDENT
#include "personal.h"

class Student : public Personal {
public:
  Student();
  void writeToFile(fstream&)const;
  void readFromFile(fstream&);
  int size() const {
    return Personal::size()+majorLen;
  }
protected:
  char *major;
  const int majorLen;
  ostream& writeLegibly(ostream&);
  friend ostream& operator<<(
    ostream &o, Student &s) 
    {return s.writeLegibly(o);}
  istream& readFromConsole(istream&);
  friend istream& operator>>(
    istream &i, Student &s)
    {return s.readFromConsole(i);}
};
#endif 

👍 cat student.cpp 
#include <iostream>
#include "student.h"

Student::Student() : majorLen(10) {
  Personal();
  major = new char[majorLen];
}

void Student::writeToFile(fstream &o)
  const {
  Personal::writeToFile(o);
  o.write(major, majorLen);
}

void Student::readFromFile(fstream &i){
  Personal::readFromFile(i);
  i.read(major, majorLen);
}

istream& Student::readFromConsole(
  istream &i) {
  Personal::readFromConsole(i);
  char s[80];
  cout << "Major: ";
  i.getline(s, 80);
  strncpy(major, s, 9);
  return i;
}

👍 cat database.h 
#ifndef DATABASE
#define DATABASE

template <typename T>
class Database {
public:
  Database();
  void run();
private:
  fstream database;
  char fName[20];
  void add(T&);
  bool find(const T&);
  void modify(const T&);
  ostream& print(ostream&);
  friend ostream& operator<<(
    ostream &o, Database &db) {
    return db.print(o);
  }
};
#endif

👍 cat database.cpp
#include <iostream>
#include "personal.h"
#include "database.h"

template <typename T>
Database<T>::Database() {
}

template<typename T>
void Database<T>::add(T &d) {
  database.open(fName,
    ios::in|ios::out|ios::binary);
  database.seekp(0, ios::end);
  d.writeToFile(database);
  database.close();
}

template<typename T>
bool Database<T>::modify(const T &d) {
  T tmp;
  database.open(fName,
    ios::in|ios::out|ios::binary);
  while (!database.eof()) {
    tmp.readFromFile(database);
    if (tmp == d) {
      cin >> tmp;
      database.seekp(
        -d.size(), ios::cur);
      tmp.writeToFile(database);
      database.close();
      return;
    }
  }
  database.close();
  cout << "The record to be modified"
       << " is not in the database\n";
}

template<typename T>
void Database::find(const T &d) {
  T tmp;
  database.open(
    fName,ios::in|ios::binary);
  while (!database.eof()) {
    tmp.readFromFile(database);
    if (tmp == d) {
      database.close();
      return true;
    }
  }
  database.close();
  return false;
}

template<typename T>
ostream& Database<T>::print(
  ostream &o) {
  T tmp;
  database.open(fName,
                ios::in|ios::binary);
  while (true) {
    tmp.readFromFile(database);
    if (database.eof())
      break;
    o << tmp << endl;
  }
  database.close();
  return o;
}

template <typename T>
void Database<T>::run() {
  cout << "File name: ";
  cin >> fName;
  char option[5];
  T rec;
  cout << "1. Add "
       << "2. Find "
       << "3. Modify a record "
       << "4. Exit\n";
  cout << "Enter an option: ";
  cin.getline(option, 4); // get '\n'
  while (cin.getline(option, 4)) {
    if (*option == '1') {
      cin >> rec;
      add(rec);
    } else if (*option == '2') {
      rec.readKey();
      cout << "The record is ";
      if (!find(rec)) cout << "not ";
      cout << "in the database\n";
    } else if (*option == '3') {
      rec.readKey();
      modify(rec);     
    } else if (*option != '4')
      cout << "Wrong option\n";
    else return;
//    cout << *this;
    cout << "Enter an option: ";
  }
}

int main() {
  //Database<Personal>().run();
  Database<Student>().run();
}

    

ch 1.10 CASE STUDY: RANDOM ACCESS FILE p43 of

© 拇指 2023