【问题标题】:how to fill an array from a text file in c++如何在 C++ 中从文本文件中填充数组
【发布时间】:2014-04-15 13:38:17
【问题描述】:

您好,我正在尝试填写我创建的类对象的数组。输入来自文本文件。文本文件包含字符串和数字。我得到了第一组信息,但文件的其余部分不会读入,任何想法都将不胜感激!

    class mess
    {
        private: 
            string name;
            float age, weight, height;
        public: 
            void setname(string a) {name=a;}
            void setage(float b){age=b;}
            //etc.
            string getname(){return name;}
            float getage(){return age;}
            //etc.
    }

    ifstream input;
    input.open("test.txt");

    mess people[2]
    string str;
    float num;

    for(inti=0; i<2; i++)
    {
        getline(input,str,'\n');
        people[i].setname(str);

        input >> num;
        people[i].setage(num);

        input >> num;
        people[i].setweight(num);

        input >> num;
        people[i].setheight(num);
    }
    for(inti=0; i<2; i++)
    {
        cout << people[i].getname() << endl;
        cout << people[i].getage() << endl;
        cout << people[i].getweight() << endl;
        cout << people[i].getheight() << endl;
    }

test.txt

杰克 17 150.3 5.10 艾米 18 110.4 5.11

输出:

杰克 17 150.3 5.10 (空白的) 0 0 0

【问题讨论】:

  • for(inti=0; i&lt;2; i++) 不会编译,除非您在某处声明了变量 inti。这不是真正的代码,是吗?
  • 在 StackOverflow 中搜索“c++ 读取文件解析”以获取其他示例。
  • @Mile DeSimone :这不是真正的代码,只是我试图做的一个例子。我的意思是 int i = 0。

标签: c++ file class ifstream


【解决方案1】:

这里的问题是,当您使用输入运算符&gt;&gt; 时,它将在第一条记录的最后一个数字之后留下换行符。这意味着下一个 getline 调用会将换行符读取为空行,然后数字将无法读取。

有几种方法可以解决这个问题。第一种是在读取记录中的最后一个数字后丢弃输入中的所有文本,直到换行。为此,您可以这样做,例如

// All other input in loop

input.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

了解ignore 函数。

另一种方法是读取第二行,完成,放入std::istringstream,然后从中读出数字:

// Reading the name...

std::string numbers;
std::getline(input, numbers);

std::istringstream istr(numbers);

istr >> num;
people[i].setage(num);

// ...

另请注意,std::getline 的第三个参数已经默认为换行符,因此如果您使用它来读取行,则不需要提供它。

【讨论】:

  • 编辑:我添加了 input.clear();和 input.ignore(1,'\n');在最后几个人之后[i]setheight(num);并且对象被正确填充。你不知道我有多高兴你帮助了我!
【解决方案2】:

我建议你在课堂上重载运算符 &lt;&lt;&gt;&gt;

class mess
{
    private: 
        string name;
        float age, weight, height;
    public: 
        void setname(string a) {name=a;}
        void setage(float b){age=b;}
        //etc.
        string getname(){return name;}
        float getage(){return age;}
        //etc.
        friend std::istream& operator>>(std::istream& inp, mess& m);
        friend std::ostream& operator<<(std::ostream& out, const mess& m);
}

std::istream& operator>>(std::istream& inp, mess& m)
{
    std::getline(inp, m.name);
    inp >> m.age;
    inp >> m.weight;
    inp >> m.height;
    return inp;
}

std::ostream& operator<<(std::ostream& out, const mess& m)
{
    out << m.name   << endl;
    out << m.age    << endl;
    out << m.weight << endl;
    out << m.height << endl;
    return out;
}

这将您的输入简化为:

std::vector<mess> people;
mess              p;
while (input_file >> p)
{
  people.push_back(p);
}

你的输出看起来像:

for (unsigned int i = 0; i < people.size(); ++i)
{
  cout << people[i];
  cout << "\n";
}

【讨论】:

  • 我要做的唯一区别是使用 std::getline() 来获取名称(以防它包含空格)。我不喜欢 operator> 对于字符串不对称。
  • @LokiAstari 实际的文本文件确实包含名字和姓氏之间的空格,所以我使用了 getline()。
  • @LokiAstari:我支持你的cmets,但是帖子的重点是重载类中的输入和输出操作。 :-)
【解决方案3】:

我会定义operator&lt;&lt; 来写出你的类的一个对象。然后定义operator&gt;&gt; 来读取你的类的对象。然后您可以使用std::istream_iterator 将值直接读取到容器中:

class M
{
    private:
        string name;
        float  age;
        float  weight;
        float  height;
    public:
        <STUFF>

    friend std::ostream& operator<<(std::ostream& s, M const& data)
    { 
        return s << data.age    << " " 
                 << data.weight << " " 
                 << data.height << " " 
                 // Put name on the edn because it may contain space.
                 // So we want to read it off using std::getline
                 << data.name   << "\n";
    }
    friend std::istream& operator>>(std::istream& s, M& data)
    { 
        s >> data.age >> data.wight >> data.height;
        std::getline(s, data.name);

        // Strip leading space (see output operator)
        data.name = data.name.substring(1);

        return s;
    }

};

然后易于在大多数容器中使用。

int main()
{
    std::ifstream  f("data");
    // OK.
    // A vector is not actually an array.
    // But you can use the same principle with a manual loop.
    // as std::istream_iterator is just a normal iterator.
    std::vector<M> data(std::istream_iterator<M>(f), std::istream_iterator<M>());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-16
    相关资源
    最近更新 更多