从文件c ++中分离行读取

时间:2014-06-20 15:03:12

标签: c++ string file-io

我在一个文件中有一个书籍列表,其中包括id,书名,作者,年份,类型等。我无法找到如何从Books.txt文件中读取

(提取物)

1   The Da Vinci Code   Dan Brown   2003    mistery-detective   20  3
2   Think and Grow Rich Napoleon Hill   1937    non-fiction 50  5
3   Harry Potter and the Half-Blood Prince  J. K. Rowling   2005    fantasy 92  8
4   The Catcher in the Rye  J. D. Salinger  1951    novel   100 6

以正确的方式构造数组信息f.e. Book_list [0] .id应为1,Book_list [0] .name =达芬奇密码等。这个想法是每个信息的和平由一个标签分隔。如果我问一些不够清楚的话,我会提前抱歉。

#include <iostream>
#include <string>
#include <fstream>

struct Book
{
    int id;
    std::string name;
    std::string author;
    int year;
    std::string genre;
    int times_given;
    int available;
};

int main()
{
    int book_list_size = 500;
    int number_of_books = 0;

    Book book_list[book_list_size];
    std::ifstream book_input_stream("Books.txt");

    std::string line;

    while (std::getline(book_input_stream, line))
    {
        ++number_of_books;
    }

    book_input_stream.close();
    book_input_stream.open("Books.txt");

    for (int i = 0; i < number_of_books; i++)
    {
        book_input_stream >> book_list[i].id >> book_list[i].name
                >> book_list[i].author >> book_list[i].year
                >> book_list[i].genre >> book_list[i].times_given
                >> book_list[i].available;
    }

    for (int i = 0; i < number_of_books; i++)
    {
        std::cout << book_list[i].id << " " << book_list[i].name << " "
                << book_list[i].author << " " << book_list[i].year << " "
                << book_list[i].genre << " " << book_list[i].times_given << " "
                << book_list[i].available << std::endl;
    }

    book_input_stream.close();

    return 0;
}

2 个答案:

答案 0 :(得分:0)

首先,这个名为std::vector的奇妙类基本上是一个可变长度数组,因此您不必两次读取该文件。你可以添加

#include <vector>

到文件的顶部并写下:

std::vector<Book> book_list;

创建列表。从那时起,您可以添加新书:

book_list.push_back(Book());

以熟悉的方式访问已添加的图书:

book_list[0].id

对于从文件中读取,>>运算符读取直到任何空格,仅在选项卡处停止

string s;
getline(book_input_stream, s, '\t');

当然与所有get*函数空格一样不会被跳过,因此请确保您只使用一个标签,或使用book_input_stream >> std::ws来跳过其他空格。

阅读一本书的一种可能方式是:

Book b;
book_input_stream >> b.id >> std::ws;
getline(book_input_stream, b.name, '\t');
book_input_stream >> std::ws;
getline(book_input_stream, b.author, '\t');
book_input_stream >> b.year >> std::ws;
getline(book_input_stream, b.genre, '\t');
book_input_stream >> b.times_given >> b.available;
book_list.push_back(b);

答案 1 :(得分:0)

如果你有数据行,用制表符分隔字段,那么 正常的解决方案是逐行读取,并打破 每行排成各自的数据,然后最终转换 任何需要转换的数据。而且Book应该有 构造函数;虽然使用C ++ 11,但它可以不用, 构造函数仍然使事情更清洁。类似的东西:

std::vector<Book> books;
std::string line;
int lineNumber = 0;
while ( std::getline( input ) ) {
    ++ lineNumber;
    std::vector<std::string> fields( split( line, '\t' ) );
    if ( fields.size() != 7 /* || other validations */ ) {
        //  error handling...
        //  it's nice when the error messages contain the line number
    } else {
        books.push_back(
            Book(
                asInt( fields[0] ),
                fields[1],
                fields[2],
                asInt( fields[3] ),
                fields[4],
                asInt( fields[5] ),
                asInt( fields[6] ) ) );
}

就此而言,您可以(并且通常应该)定义>> Book的运算符:

std::istream&
operator>>( std::istream& source, Book& dest )
{
    std::string line;
    std::getline( source, line );
    if ( source ) {
        std::vector<std::string> fields( split( line, '\t' ) );
        if ( fields.size() != 7 /* || other validations */ ) {
            source.setstate( std::ios_base::failbit );
        } else {
            dest = Book(
                    asInt( fields[0] ),
                    fields[1],
                    fields[2],
                    asInt( fields[3] ),
                    fields[4],
                    asInt( fields[5] ),
                    asInt( fields[6] ) );
    }
    return source;
}

然后,您需要做的就是:

std::vector<Book> books;
Book book;
while ( input >> book ) {
    books.push_back( book );
}