: Write a program to write 5 book records in a file. Program should also perform random access in the file, after taking input for a particular record number to read and it should also perform random record overwriting after taking input of new record and the record number to overwrite. [Attributes of book: Book_id, Book_price, Book_name, Book_author_name]
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
const int BOOKS_AMOUNT = 5;
const std::string RECORDS_FILE = "books.txt";
class Book {
private:
std::string id = "";
float price = 0;
std::string name = "";
std::string author_name = "";
std::string readAttribute(std::string& str, int& i) {
std::string result;
int size = str.size();
// Skip leading spaces
for (; i < size && str[i] == ' '; ++i);
for (; i < size && str[i] != ';'; ++i) {
result += str[i];
}
++i;
// Remove trailing spaces
int j = 0;
for (int k = result.size() - 1; k >= 0 && result[k] == ' '; ++j, --k);
if (j > 0) result.assign(result, 0, result.size() - j);
return result;
}
public:
Book() {}
// Construct object from string record
Book(std::string& str) {
int i = 0;
id = readAttribute(str, i);
// atof() function (for converting string to float) accepts const char* parameter,
// so we should get string's raw pointer by calling c_str() method
price = atof(readAttribute(str, i).c_str());
name = readAttribute(str, i);
author_name = readAttribute(str, i);
}
friend std::ostream& operator <<(std::ostream& os, const Book& book) {
os << "id " << book.id << "\nprice " << book.price << "\nname " << book.name << "\nauthor " << book.author_name << '\n';
return os;
}
std::string getId() {
return id;
}
float getPrice() {
return price;
}
std::string getName() {
return name;
}
std::string getAuthor() {
return author_name;
}
};
Book getBook(std::string& line) {
// Skip the index of record (assuming it is correct because we wrote it ourselves)
int i = 0;
int size = line.size();
for (; i < size && line[i] != ')'; ++i);
++i;
return Book(line.assign(line, i, line.size() - i));
}
std::vector<Book> getBooks() {
std::ifstream is(RECORDS_FILE);
std::vector<Book> books;
std::string line;
for (std::getline(is, line); is; std::getline(is, line)) {
books.push_back(getBook(line));
}
return books;
}
void saveRecords(std::ofstream& os, std::vector<Book>& books) {
for (int i = 0; i < BOOKS_AMOUNT; ++i) {
if (i) os << '\n';
os << i + 1 << ") " << books[i].getId() << "; " << books[i].getPrice() << "; " << books[i].getName() << "; " << books[i].getAuthor();
}
}
int main(int argc, char** argv) {
if (argc == 1) {
std::ofstream os(RECORDS_FILE);
std::cout << "Enter book data, each book in the following format:\n"\
"<book_id>; <book_price>; <book_name>; <book_author_name>\n";
std::string line;
std::vector<Book> books;
for (int i = 0; i < BOOKS_AMOUNT; ++i) {
std::cout << "Enter book " << i + 1 << " data:\n";
std::getline(std::cin, line);
books.push_back(Book(line));
}
saveRecords(os, books);
std::cout << "Data is saved to file '" << RECORDS_FILE << "'\n";
}
else {
std::string option = std::string(argv[1]);
if (argc == 2 && option == "help") {
std::cout << "Options:\n";
std::cout << "#no options# Set up 5 book records\n";
std::cout << "get <record number> Get book record with sequence number <record number>\n";
std::cout << "update <record number> Update book record with sequence number <record number>\n";
}
else if (option == "get" || option == "update") {
if (argc != 3) {
std::cerr << "Using with '" << option << "' option: " << option << " <record number>\n";
return 1;
}
int index = atoi(argv[2]);
if (index <= 0 || index > BOOKS_AMOUNT) {
std::cerr << "Record number must be integer from 1 to " << BOOKS_AMOUNT << '\n';
return 1;
}
if (option == "get") {
std::ifstream is(RECORDS_FILE);
// Skip records before the one we are interested in
std::string line;
for (int i = 0; i < index; ++i, std::getline(is, line));
std::cout << getBook(line);
}
else {
std::vector<Book> books = getBooks();
std::cout << "Enter book data in the following format\n"\
"<book_id>; <book_price>; <book_name>; <book_author_name>\n";
std::string line;
std::getline(std::cin, line);
books[index - 1] = Book(line);
std::ofstream os(RECORDS_FILE);
saveRecords(os, books);
std::cout << "Record updated\n";
}
}
}
return 0;
}
Type 'help' option to see usage information
Setting up records:
After this step content of the file "books.txt" looks like this:
1) a1; 100; Harry Potter and the Philosopher's Stone; J. K. Rowling
2) b2; 98; Harry Potter and the Chamber of Secrets; J. K. Rowling
3) c3; 103; Harry Potter and the Prisoner of Azkaban; J. K. Rowling
4) d4; 96; Harry Potter and the Goblet of Fire; J. K. Rowling
5) e5; 93; Harry Potter and the Order of the Phoenix; J. K. Rowling
Getting record by it's number:
Updating record:
File contents is updated accordingly:
1) a1; 100; Harry Potter and the Philosopher's Stone; J. K. Rowling
2) b2; 98; Harry Potter and the Chamber of Secrets; J. K. Rowling
3) c3; 103; Harry Potter and the Prisoner of Azkaban; J. K. Rowling
4) d4; 96; Harry Potter and the Goblet of Fire; J. K. Rowling
5) f6; 95; Harry Potter and the Half-Blood Prince; Joanne Rowling
Comments
Leave a comment