【问题标题】:Reading books information from txt file in C++?从 C++ 中的 txt 文件中读取书籍信息?
【发布时间】:2018-08-06 02:59:53
【问题描述】:

我想阅读书籍 - 来自 txt 文件的书名、作者和价格。 The 3 properties of the book are separated by '|' - Title|Author|Book. 但是,我不知道该怎么做。我有结构书,有 3 个元素。我想,对于每一行读取书名、作者和价格,将它们分别保存到结构的 3 个变量中并在控制台上打印它们。我尝试仅使用标题来执行此操作,但它会打印整行。我想问如何为每本书分别打印其作者名称和价格?

【问题讨论】:

  • getline 将读取整行。之后,您需要根据行的格式对其进行解析。
  • 使用ptstr有什么好处?为什么不直接使用a.title
  • getline 有两个主要用途:getline(stream, line) 获取线路,getline(stream, token, delimiter) 获取令牌。将std::stringstream 放入混合中,以便您将行解析为流,您就完成了。
  • 请不要急于接受答案。下面发布的,您已经接受的错误。

标签: c++ file structure getline display


【解决方案1】:

您需要的包含库,以及您的Book 结构定义。一旦你开始学习更高级的 C++ 主题,你就可以学习如何为输入和输出流重载友元函数,以使你的 I/O 操作为 Book 对象自包含。

#include <iostream> ///< std::cout
#include <fstream>  ///< std::ifstream
#include <sstream>  ///< std::istringstream, std::string
#include <vector>   ///< std::vector

struct Book
{
    std::string title;  ///< title of the book
    std::string author; ///< author of the book
    std::string price;  ///< price of the book (TODO use float instead?)
    // TODO consider friend std::istream& operator>> for parsing input data
    // TODO consider friend std::ostream & operator<< for printing object
};

如果你有输入文件的句柄,你可以像这样解析它。一次阅读每一行。 Do not read until input.eof() 因为错了!将每一行存储到一个临时的std::istringstream 对象中以供进一步解析。使用重载的std::getline(stream, token, delimiter)| 来解析行中的数据,并将它们直接保存到您的临时Book 对象中。最后,如果您希望以后能够处理它们,请将对象存储到您的向量中,并可选择将它们打印到控制台。

void readBooks(std::ifstream& input, std::vector<Book>& books)
{
    std::string line;
    while (std::getline(input, line)) ///< while we have a line to parse
    {
        std::istringstream iss(line); ///< line to parse as sstream
        Book book; ///< temporary book object
        std::getline(iss, book.title, '|');
        std::getline(iss, book.author, '|');
        std::getline(iss, book.price, '|');
        books.push_back(book); ///< add book object into vector
        std::cout << "Title:  " << book.title << std::endl;
        std::cout << "Author: " << book.author << std::endl;
        std::cout << "Price:  " << book.price << std::endl << std::endl;
    }
}

int main()
{
    std::vector<Book> books;  ///< store each Book object
    std::ifstream input("books.txt");
    if (input.is_open())
    {
        readBooks(input, books); ///< read your books
    }
    return 0;
}

使用以下输入文件内容测试

Tales from Shakespeare (1807)|Shakespeare|6.74
The Jungle Book (1894)|Rudyard Kipling|9.99
Through the Looking-Glass (1871)|Lewis Carroll|12.97

得到以下结果

Title:  Tales from Shakespeare (1807)
Author: Shakespeare
Price:  6.74

Title:  The Jungle Book (1894)
Author: Rudyard Kipling
Price:  9.99

Title:  Through the Looking-Glass (1871)
Author: Lewis Carroll
Price:  12.97

【讨论】:

    【解决方案2】:
    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    
    struct Book {
        string title;
        string author;
        string price;
    };
    void read_Books(std::ifstream&, Book&);
    
    int main()
    {
        ifstream p("books.txt", ios::in);
        Book a;
        read_Books(p, a);
        return 0;
    }
    void read_Books(std::ifstream& p, Book& ptstr) {
        while(p.is_open() && !p.eof()){
            getline(p, ptstr.title, '|');
            getline(p, ptstr.author, '|');
            getline(p, ptstr.price, '|');
            cout<<ptstr.title << ptstr.author << ptstr.price << std::endl;
            //The whole line is printed, it ought to be the title only
        }
    }
    

    【讨论】:

    • 没有。这不是如何从循环中的流中读取。请多读stackoverflow.com/questions/5605125/…
    • 如果您要一次又一次地覆盖它,那么传递对Book 对象的引用到底有什么意义呢?也许在这里引用std::vector&lt;Book&gt; 更有意义?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 2020-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多