将虚函数与类和构造函数一起使用来打印书籍信息
Using virtual functions with classes and constructors to print book info
我正处于这个项目的最后一步,我被困在了该怎么做上。该项目将获取一个包含书籍信息的输入文件,如下所示:
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,我需要:
- 输入有关每本书的更多信息。我需要有两个子类,
InfoBookRecord
包含价格和作者传记,TypeBookRecord
包含书籍类型。 - 使用虚拟函数打印新信息。我认为在类
ListRecords
中制作虚函数是有意义的,但评分键似乎暗示我应该将它们用于两个子类InfoBookRecord
和TypeBookRecord
。我想不出任何办法可以做到这一点。
标题.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){;}
完全没问题。
相关文章:
- 按字母顺序打印存储在字符数组中的信息
- CppUnit:如何立即打印故障详细信息
- 当遇到不是来自 STL 的未捕获异常时,有没有办法打印其信息?
- C++代码不打印信息,有什么问题?
- 有打印库信息的命令吗?(C++)
- C GTEST在测试结束时仅在测试失败时打印其他信息
- 如何使dumpObjectInfo打印调试信息
- 将虚函数与类和构造函数一起使用来打印书籍信息
- 试图在C++中打印存储在类型对象数组中的信息
- boost::exception-如何打印详细信息
- 我在哪里可以找到在NS2库的cpp文件中生成的打印信息,其中我添加了一些cout()函数来打印一些信息
- 为类打印输出(打印调试信息)的最佳实践是什么?
- 在编译时分配内存的工厂模式,以及如何打印编译时信息
- 可以#define用于打印信息
- 在cpp中使用libpcap打印RTP头信息
- 如何使用for循环从数组中打印出交替的信息
- 如何检索或打印"Catch"信息记录缓冲区?
- 打印数字签名信息
- 通过循环另一个用于搜索文件的函数从文件中打印出信息- c++
- 我可以使用什么Mac/iOS/便携式库来格式化信息以打印到标签纸上