将虚函数与类和构造函数一起使用来打印书籍信息

Using virtual functions with classes and constructors to print book info

本文关键字:打印 信息 一起 函数 构造函数      更新时间:2023-10-16

我正处于这个项目的最后一步,我被困在了该怎么做上。该项目将获取一个包含书籍信息的输入文件,如下所示:

A Book on C
Al Kelly and Ira Pohl
Addison-Wesley, Fifth Edition 1998.
0201183994
C How to Program
Paul Deitel and Harvey Deitel
Prentice Hall Sixth Edition 2010
0136123562

然后使用多个选项打印它。我将把所有代码放在这里,以便您可以编译并查看每个选项的作用。特别是我在选项 5 上遇到了问题。对于选项 5,我需要:

  1. 输入有关每本书的更多信息。我需要有两个子类,InfoBookRecord包含价格和作者传记,TypeBookRecord包含书籍类型。
  2. 使用虚拟函数打印新信息。我认为在类ListRecords中制作虚函数是有意义的,但评分键似乎暗示我应该将它们用于两个子类InfoBookRecordTypeBookRecord。我想不出任何办法可以做到这一点。

标题.h:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <fstream>
#include <algorithm>
using namespace std;
#define TABLE_SIZE 200
class BookRecord{
  public:
    BookRecord(string input_title, string input_author, string input_publisher, int input_isbn);
    string getTitle();
    string getAuthor();
    string getPublisher();
    int getISBN();
  private:
    string title;
    string author;
    string publisher;
    int isbn;
};
class InfoBookRecord: public BookRecord {
  public:
    InfoBookRecord(string input_title, string input_author, string input_publisher, int input_isbn, double input_price, string input_authorBio) : BookRecord(input_title,input_author,input_publisher,input_isbn) {
      price=input_price;
      authorBio=input_authorBio;}
    double getPrice();
    string getAuthorBio();
  private:
    double price;
    string authorBio;
};
class TypeBookRecord: public BookRecord {
  public:
    TypeBookRecord(string input_title, string input_author, string input_publisher, int input_isbn, string input_genre) : BookRecord(input_title,input_author,input_publisher,input_isbn){
      input_genre.resize(15);
      genre=input_genre;}
    string getGenre();
  private:
    string genre;
};
class ListRecords{
  public:
    ListRecords(char filename[]);
    void insertBookInfo(BookRecord record);
    //virtual void printBookInfo(int bookISBN);
    void printBookInfo(int bookISBN);
    void printListByISBN();
    void printListByTitle();
    BookRecord ** books;
    InfoBookRecord ** books2;
    TypeBookRecord ** books3;
    int line_num;
    int k;
    string garbage;
};
 // problem here
/*
class extraListRecords: public ListRecords{
  public:
    extraListRecords();
    void printBookInfo(int bookISBN){
      cout << "testing 1 2 3 " << endl;
    }
};*/ 

簿记.cpp:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <fstream>
#include <algorithm>
#include "header.h"
using namespace std;
#define TABLE_SIZE 200
BookRecord::BookRecord(string input_title, string input_author, string input_publisher, int input_isbn){
  title=input_title;
  author=input_author;
  publisher=input_publisher;
  isbn=input_isbn;
}
string BookRecord::getTitle() {return title;}
string BookRecord::getAuthor() {return author;}
string BookRecord::getPublisher() {return publisher;}
int BookRecord::getISBN() {return isbn;}
double InfoBookRecord::getPrice() {return price;}
string InfoBookRecord::getAuthorBio() {return authorBio;}
string TypeBookRecord::getGenre() {return genre;}

列表记录.cpp:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <fstream>
#include <algorithm>
#include "header.h"
using namespace std;
#define TABLE_SIZE 200
ListRecords::ListRecords(char filename[]){
  ifstream input(filename);
  assert(("Error: File does not exist.", input != NULL));
  string line;
  line_num=0;
  while (getline(input,line)){
    line_num++;
  }
  //go back to beginning of file
  input.clear();
  input.seekg(0, ios::beg);
  char lines[TABLE_SIZE][TABLE_SIZE];
  int i=0;
  // load lines of file into array
  while (i < line_num) {
    input.getline(lines[i],TABLE_SIZE);
    i++;
  }
  input.close();
  books = new BookRecord*[TABLE_SIZE];
  books2 = new InfoBookRecord*[TABLE_SIZE];
  books3 = new TypeBookRecord*[TABLE_SIZE];
  k=0;
  for(i=0;i<line_num;i+=5){
    // check for duplicate entries
    int test=0;
    for(int j=0;j<i/5;j++){
      if(books[j]->getISBN() == atoi(lines[i+3])){
        cout << "Found a duplicate ISBN... ignoring entry " << lines[i+3] << endl;
        test=1;
      }
    }
    // if not a duplicate entry, add to array
    if(test==0){
     int the_price;
      cout << "Please enter price of " << lines[i] << ": " << endl;
      cin >> the_price;
      getline(cin,garbage);
      string the_authorBio;
      cout << "Please enter author bio of " << lines[i] << ": ";
      cin >> the_authorBio;
      getline(cin,garbage);
      string the_genre;
      cout << "Please enter the book genre of " << lines[i] << ": ";
      cin >> the_genre;
      getline(cin,garbage);
      *(books2+k) = new InfoBookRecord(lines[i],lines[i+1],lines[i+2],atoi(lines[i+3]),the_price,the_authorBio);
      *(books3+k) = new TypeBookRecord(lines[i],lines[i+1],lines[i+2],atoi(lines[i+3]),the_genre);
      *(books+k) = new BookRecord(lines[i],lines[i+1],lines[i+2],atoi(lines[i+3]));
      k++;
    }
    else
      i+=5;
  }
}
void ListRecords::insertBookInfo(BookRecord record){
  line_num+=5;
  *(books+k) = new BookRecord(record.getTitle(),record.getAuthor(),record.getPublisher(),record.getISBN());
  k++;
}
void ListRecords::printBookInfo(int bookISBN){
  int found=0;
  for(int i=0;i<k;i++){
    if(books[i]->getISBN() == bookISBN){
      if(to_string(books[i]->getISBN()).length()==9)
        cout << endl << books[i]->getTitle() << endl << books[i]->getAuthor() << endl << books[i]->getPublisher() << endl << "0" << books[i]->getISBN() << endl;
      if(to_string(books[i]->getISBN()).length()==10)
        cout << endl << books[i]->getTitle() << endl << books[i]->getAuthor() << endl << books[i]->getPublisher() << endl << books[i]->getISBN() << endl;
      found=1;
      break;
    }
  }
  if(found==0)
    cout << "The record you requested was not found in the list." << endl;
}
bool compare_by_isbn(BookRecord* x,BookRecord* y) { return (x->getISBN() < y->getISBN()); }
bool compare_by_title(BookRecord* x,BookRecord* y) { return (x->getTitle() < y-> getTitle()); }
void ListRecords::printListByISBN(){
  sort(books, books + k, compare_by_isbn);
  printf("       %-22s %-22s %-17s %sn", "Title", "Author", "Publisher", "ISBN");
  cout << string(22, '-') << " " << string(22, '-') << " " << string(22, '-') << " " << string(10, '-') << endl;
  for(int i=0;i<k;i++){
    if(to_string(books[i]->getISBN()).length()==9)
      printf("%-22.22s %-22.22s %-22.22s 0%dn", books[i]->getTitle().c_str(), books[i]->getAuthor().c_str(), books[i]->getPublisher().c_str(), books[i]->getISBN());
    if(to_string(books[i]->getISBN()).length()==10)
      printf("%-22.22s %-22.22s %-22.22s %dn", books[i]->getTitle().c_str(), books[i]->getAuthor().c_str(), books[i]->getPublisher().c_str(), books[i]->getISBN());
  }
}
void ListRecords::printListByTitle(){
  sort(books, books + k, compare_by_title);
  printf("       %-22s %-22s %-17s %sn", "Title", "Author", "Publisher", "ISBN");
  cout << string(22, '-') << " " << string(22, '-') << " " << string(22, '-') << " " << string(10, '-') << endl;
  for(int i=0;i<k;i++){
    if(to_string(books[i]->getISBN()).length()==9)
      printf("%-22.22s %-22.22s %-22.22s 0%dn", books[i]->getTitle().c_str(), books[i]->getAuthor().c_str(), books[i]->getPublisher().c_str(), books[i]->getISBN());
    if(to_string(books[i]->getISBN()).length()==10)
      printf("%-22.22s %-22.22s %-22.22s %dn", books[i]->getTitle().c_str(), books[i]->getAuthor().c_str(), books[i]->getPublisher().c_str(), books[i]->getISBN());
  }
}

主.cpp:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <fstream>
#include <algorithm>
#include "header.h"
using namespace std;
#define TABLE_SIZE 200
int main(int argc, char* argv[]){
  char filename[50];
  cout << "Enter the name of a file to load:" << endl;
  cin >> filename;
  ListRecords listrecords(filename);
  while(true){ // looping for the selection menu
    int selection, n;
    cout << "Please select a menu option:n1) Insert a book record into the listn2) Print information of a book with a given ISBN numbern3) Print the list of books sorted by ISBNn4) Print the list of books sorted alphabetically by titlen5) Print the books also with info on price, author biography, and genre.n6) Quit the program" << endl;
    cin >> selection;
    if(cin.fail()){ // make sure input is a digit
      cout << "Invalid selection. Quitting program..." << endl;
      break;
    }
    if(selection==1){
      string in_title;
      string in_author;
      string in_publisher;
      int in_isbn;
      string junk;
      getline(cin, junk);
      cout << endl << "Please enter a title: ";
      getline(cin, in_title);
      cout << "Please enter an author: ";
      getline(cin, in_author);
      cout << "Please enter a publisher: ";
      getline(cin, in_publisher);
      cout << "Please enter an ISBN: ";
      cin >> in_isbn;
      BookRecord new_record(in_title, in_author, in_publisher, in_isbn);
      listrecords.insertBookInfo(new_record);
      cout << endl << "The record has been added to the list." << endl;
      cout << endl << endl;
    }
    if(selection==2){
      int in_isbn;
      cout << endl << "Please enter ISBN number: " << endl;
      cin >> in_isbn;
      listrecords.printBookInfo(in_isbn);
      cout << endl << endl;
    }
    if(selection==3){
      cout << endl;
      listrecords.printListByISBN();
      cout << endl << endl;
    }
    if(selection==4){
      cout << endl;
      listrecords.printListByTitle();
      cout << endl << endl;
    }
    if(selection==5){
      int in_isbn;
      cout << endl << "Please enter ISBN number: " << endl;
      cin >> in_isbn;
cout << endl << "List of books also with info on price and author biography: " << endl;
      cout << endl << endl;
      // problem here
      // extraListRecords extras;
      //ListRecords *bookextras= &extras;
      // bookextras->printBookInfo(in_isbn);

cout << endl << "List of books also with info on genre: " << endl;

    }
    if(selection==6){
      cout << endl << "Program terminating normally..." << endl;
      break;
    }
  } // end of while(true) loop
  return 0;
};

制作文件:

LFLAGS = -Wno-write-strings -std=c++11
CFLAGS = -Wno-write-strings -std=c++11 -c
myprogam: main.o BookRecord.o ListRecords.o
        g++ $(LFLAGS) -o myprogram main.o BookRecord.o ListRecords.o header.h
main.o: main.cpp header.h
        g++ $(CFLAGS) main.cpp
BookRecord.o: BookRecord.cpp header.h
        g++ $(CFLAGS) BookRecord.cpp
ListRecords.o: ListRecords.cpp header.h
        g++ $(CFLAGS) ListRecords.cpp
clean:
        rm *.o
        rm myprogram

我注释掉了给我带来麻烦的两个部分。一个在header.h的末尾,另一个在main.cpp的末尾。

当我尝试这样做时,我收到错误

main.cpp:(.text+0x4c7): undefined reference to `extraListRecords::extraListRecords()'
collect2: error: ld returned 1 exit status
make: *** [myprogam] Error 1
我已经尝试了

其他一些带有虚拟函数的子类的尝试,例如将 book2 和 book3 的初始化添加到其构造函数的主体中,因此将其构造函数编写为extraListRecords(char filename[]) :ListRecords(filename){ / the chunk of code in ListRecords.cpp above around line 55 / }

谢谢大家的帮助!

你需要为 extraListRecords 提供构造函数定义

class extraListRecords: public ListRecords {
  public:
    extraListRecords() = default;
    //                 ^^^^^^^^^^
}; 

我想通了。这个问题很愚蠢。我只是忘了刷新整数上的 cin 和 getline 之间的缓冲区。CIN 和获取线路跳过输入

虚拟函数与标头中的构造函数一样extraListRecords(char filename[]): ListRecords(filename){;}完全没问题。