Fstream 无法正确读取文件

问题描述 投票:0回答:1

我正在尝试编写一个程序来读取文件并设置名称和该人投的 5 票。问题是 fstream 没有正确读取文件。但是,如果我在主方法中打开另一个对象,它们都会完美打印。

我尝试过查看类似的问题,但似乎没有一个能解决它。

#include <iostream>
#include <fstream>
using namespace std;

class pledge {
        public:
                string name;
                string *vote;
                void setName(string n) {name = n;}
                void setVote(string *v) {vote = v;}
                void printName() {cout << name << endl;}
                void printVote();
                void print();
};

void pledge::printVote() {
        cout << vote[0] << endl;
        cout << endl;
}
void pledge::print() {
        cout << name << ": ";
        for (int i = 0; i < 5; i++) {
                cout << vote[i] << ", ";
        }
        cout << endl;
}

pledge* createPledges(char[], int);

int main(int agrc, char *argv[]) {
        int n;
        n = stoi(argv[2]);
        pledge *p = createPledges(argv[1], n);
        cout << p -> vote[0] << endl;
}

pledge* createPledges(char filename[], int n) {
        fstream input;
        input.open(filename);
        pledge* p = new pledge();
        string name, vote[5];
        getline(input, vote[0]);
        p -> setVote(vote);
        return p;
}
c++ fstream
1个回答
0
投票

fstream
不起作用的最大原因之一是
votes
数组未正确实现。这个答案提供了一些关于如何纠正这个问题的提示。

我假设这是一项家庭作业,并且您对一些可以使作业变得更容易的高级(和不太高级)C++ 功能没有经验。

  • 没有
    std::vector
  • 没有
    std::array
  • 没有像
    operator<<
    operator[]
  • 这样的运算符功能
  • 没有基本成员初始化列表

好吧,所以使用内置数组来保存投票。请勿使用指针。

class Pledge
{
    // This class manages the data for a single pledge (and his 5 votes).

    enum : std::size_t { n_votes = 5u };
    std::string name;
    std::string votes[n_votes];  // use a built-in array to store votes.

public:
    // ...
};

假设您需要两个构造函数,一个仅采用名称,另一个采用名称和一个包含五票的数组。第一个应该很容易,但第二个需要复制投票数组。您必须传递数组(及其大小),然后运行循环来进行复制。

这是一个示例,它仔细地将传递到构造函数的数组的大小与存储在

Pledge
中的数组的大小进行匹配。如果它们不同,它会避免访问任何超出范围的元素。

public:
    Pledge(
        std::string const& name,
        std::string votes[],
        std::size_t const size)
    {
        this->name = name;

        // We can take up to `n_votes` votes.
        // Anything beyond that, we have to discard.
        if (size > n_votes)
        {
            std::cout << "ERROR: Expecting " << +n_votes << " votes, "
                "but " << size << " were passed into the constructor "
                "of class Pledge. The extras have been discarded.\n";
        }
        else if (size < n_votes)
        {
            std::cout << "ERROR: Expecting " << +n_votes << " votes, "
                "but only " << size << " were passed into the constructor "
                "of class Pledge.\n";
        }
        std::size_t n_elements_to_copy = n_votes;
        if (size < n_votes)
            n_elements_to_copy = size;
        for (std::size_t i = 0; i < n_elements_to_copy; ++i)
            this->votes[i] = votes[i];
    }

这可行,并且可能值得保留,但我有另一个想法。如果我们将五票硬编码到构造函数中会怎样?这几乎就像作弊一样,但代码非常简单。

    Pledge(
        std::string const& name,
        std::string const& vote0,
        std::string const& vote1,
        std::string const& vote2,
        std::string const& vote3,
        std::string const& vote4)
    {
        this->name = name;
        votes[0] = vote0;
        votes[1] = vote1;
        votes[2] = vote2;
        votes[3] = vote3;
        votes[4] = vote4;
    }

接下来,我们应该看一下集合并获取用于投票的例程。他们应该接受下标作为参数,并检查以确保它没有超出范围。

    void set_vote(std::size_t const i, std::string const& v)
    {
        if (i < n_votes)
            votes[i] = v;
        else
            std::cout << "ERROR - subscript out of range";
    }

    std::string get_vote(std::size_t const i) const
    {
        if (i < n_votes)
            return votes[i];
        else
            std::cout << "ERROR - subscript out of range";
    }

您几乎已经涵盖了打印例程。只需两个提示:

  1. 您可以通过在循环外部(顶部)打印第一个投票来避免额外的逗号,然后以 1(而不是 0)开始循环。
  2. 整个打印例程应调用
    print_name
    ,然后调用
    print_votes
    ,并让它们完成工作。

我认为你应该完全重写函数

createPledges
(甚至删除它)。我首先编写一个函数,该函数精确读取一个
Pledge
和他的五票,然后直接返回它。不要使用任何指针或运算符
new

Pledge readOnePledge(std::istream& ist)
{
    // `ist` is the `std::ifstream` object you create (and open) elsewhere.
    // When you open a file, you have to use `ifstream` (or `fstream`).
    // When you read from that file, it is okay to use either `istream` 
    // or `ifstream`. They both work.

    std::string name, vote0, vote1, vote2, vote3, vote4;

    // Read name and votes...

    // And then use the constructor to create (and return) a `Pledge`
    // object.
    return Pledge(name, vote0, vote1, vote2, vote3, vote4);
}

我留下了很多不完整的细节。那是故意的。这应该给你一个好的开始,但我也想让你享受一些乐趣!

© www.soinside.com 2019 - 2024. All rights reserved.