从文本文件加载对象数据时出现问题

时间:2011-09-02 08:04:36

标签: c++

为什么这段代码不想加载文本文件中的所有值?它只能正确加载第一个对象的项目,但之后开始变得怪异。这是代码:

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;
class Location
{
public:
    Location()
    {
        locName = "No Name";
        locDesc = "No Description";
        locID = 0;
    }

    friend ostream& operator <<(ostream& outs, const Location & showMe)
    {
        // keeping output same as input...
        outs << showMe.locName << endl;
        outs << showMe.locDesc << endl;
        outs << showMe.locID << endl;

        return outs;
    }

    friend istream& operator >>(istream& ins, Location & inLoc)
    {
        getline(ins, inLoc.locName);
        getline(ins, inLoc.locDesc);
        ins >> inLoc.locID;

        return ins;
    }

private:
    string locName;
    string locDesc;
    int locID;
};

int main()
{
    ifstream inFile;

    inFile.open("loc_data.txt");
    if (inFile.fail())
        {
            cout << "\nCould not open the input file!";
            exit(1);
        }

    Location fileLoc[10];
    int i = 0;

    while (inFile.good())
        {
            inFile >> fileLoc[i];
            i++;
        }

    for (int j = 0; j < 10; j++)
        cout << fileLoc[j];

    return 0;
}

输入文件是:

Town Hall
Main venue for functions
1
City Park
Outdoor venue
2
Train Station
Commuting point
3
Local Airport
Long distance travel
4

输出是:

Town Hall
Main venue for functions
1

City Park
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0

我怀疑getline对此负有责任,但我不知道该怎么做,但是我真的想知道为什么会这样,而不仅仅是'修复'。

3 个答案:

答案 0 :(得分:2)

您的第一个问题是此行不会提取换行符:

ins >> inLoc.locID;

这意味着第二个getline的{​​{1}} in正在Location之后提取行的其余部分 - 即空字符串 - 用于名称。

这意味着您很快就会与想要阅读的行不同步。

您还应该考虑更改while循环,因为它会在您提取新位置之前检查流是否“良好”,但是您不检查提取是否成功,您认为提取有效。

答案 1 :(得分:1)

这有效:

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <sstream>

using namespace std;
class Location
{
public:
    Location()
    {
        locName = "No Name";
        locDesc = "No Description";
        locID = 0;
    }

    friend ostream& operator <<(ostream& outs, const Location & showMe)
    {
        // keeping output same as input...
        outs << showMe.locName << endl;
        outs << showMe.locDesc << endl;
        outs << showMe.locID << endl;

        return outs;
    }

    friend istream& operator >>(istream& ins, Location & inLoc)
    {
        getline(ins, inLoc.locName);
        getline(ins, inLoc.locDesc);
        std::stringstream ss;
        std::string s;
        getline(ins, s);
        ss << s;
        ss >> inLoc.locID;

        return ins;
    }

private:
    string locName;
    string locDesc;
    int locID;
};

int main()
{
    ifstream inFile;

    inFile.open("loc_data.txt");
    if (inFile.fail())
        {
            cout << "\nCould not open the input file!";
            exit(1);
        }

    Location fileLoc[10];
    int i = 0;

    while (inFile.good())
        {
            inFile >> fileLoc[i];
            i++;
        }

    for (int j = 0; j < 10; j++)
        cout << fileLoc[j];

    return 0;
}

答案 2 :(得分:1)

我认为问题在于这一行:ins&gt;&gt; inLoc.locID;

问题在于,当您使用&gt;&gt;读取此值时操作符它将下一行字符留在缓冲区中,这会导致读取循环结束(如果你单步执行它就可以看到)。

为了解决这个问题,我认为你需要故意从缓冲区中清空这个字符,或者使用getline并将输入(我想希望验证!)转换为字符串中的数字。

希望这有帮助,