简体   繁体   English

读取txt C ++中的行

[英]Reading lines in a txt c++

I have a text file which lists certain attributes of an object class like DVD title(string) category(string) price(int) runtime(int) year released(int) 我有一个文本文件,其中列出了对象类的某些属性,例如DVD标题(字符串)类别(字符串)price(int)运行时(int)发布年份(int)

the file is listed like 该文件列出如下

Movie1
Action    
10.45
123
2008

Movie2
Sc-fi
12.89
99
2008

I have a function whereby you type in the name of the file and it is supposed to read in the different attributes into an object 我有一个函数,您可以输入文件名,并且应该将不同的属性读入对象

DVD* file(DVD arr[], string fileName, int s, int& e)
{
ifstream file(fileName);

DVD j;
string v;
string w;
double x;
int y;
int z;


while(!file.eof())
{
    file >> v;
    j.setTitle(v);

    file >> w;
    j.setCategory(w);

    file >> x;
    j.setPrice(x);

    file >> y;
    j.setRuntime(y);

    file >> z;
    j.setYear(z);

    arr=add(arr, j, s, e); //this is just a function that adds the object to an arry
}


file.close();

return arr;
}

but it is not working correctly, I want it to read each line into the variable, then if there is a space skip it, but if not the end of file keep reading until it hits a string. 但是它不能正常工作,我希望它将每一行读入变量,然后如果有空格,请跳过它,但如果文件末尾不读,请继续读取直到命中字符串。 Any suggestions? 有什么建议么?

Two things. 两件事情。

Firstly: 首先:

while(!file.eof()) is broken eof() doesn't return true until after a read is attempted. while(!file.eof())已损坏eof()直到尝试读取后才返回true

The second thing is that if you want to read line by line, it is better to use something like this: 第二件事是,如果您想逐行阅读,最好使用如下代码:

void read_file(std::vector<DVD> & arr, string fileName) {
    ifstream file(fileName.c_str());

    DVD j;
    std::string line;
    enum State {
        TITLE, CATEGORY, PRICE, RUNTIME, YEAR
    } state = TITLE;

    while(std::getline(file, line)) {

        // if we encounter an empty line, reset the state    
        if(line.empty()) {
            state = TITLE;
        } else {

            // process the line, and set the attribute, for example
            switch(state) {
            case TITLE:
                j.setTitle(line);
                state = CATEGORY;
                break;
            case CATEGORY:
                j.setCategory(line);
                state = PRICE;
                break;
            case PRICE:
                j.setPrice(boost::lexical_cast<double>(line));
                state = RUNTIME;
                break;
            case RUNTIME:
                j.setRuntime(boost::lexical_cast<int>(line));
                state = YEAR;
                break;
            case YEAR:
                j.setYear(boost::lexical_cast<int>(line));
                arr.push_back(j);
                state = TITLE;
                break;
            default:
                // just in case
                state = TITLE;
                break;
            }
        }
    }
}

This works because std::getline returns a reference which when used in a boolean context will be true if the last operation left the stream in a "good" state. 之所以有效,是因为std::getline返回一个引用,如果最后一个操作使流处于“良好”状态,则在布尔上下文中使用该引用将为true

In this example, I am using boost::lexical_cast<> to convert a string to a numeric type as needed, but you can use std::stringstream to do this manually, or any other method you feel works best for you. 在此示例中,我使用boost::lexical_cast<>根据需要将字符串转换为数字类型,但是您可以使用std::stringstream手动执行此操作,或者使用您认为最适合的其他任何方法。 For example, atoi() , strtol , strtod , etc. 例如atoi()strtolstrtod等。

SIDE NOTE: it is far better to use std::vector<DVD> instead of a native array. 旁注:最好使用std::vector<DVD>代替本地数组。 It will be just as fast, but will properly handle resizing and cleanup for you. 速度一样快,但是可以为您正确地调整大小和进行清理。 You will no longer have a need for your add function since you will be able to just do: arr.push_back(j); 您将不再需要add函数,因为您将能够执行以下操作: arr.push_back(j);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM