我正在尝试编写一个程序来读取文件并设置名称和该人投的 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;
}
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";
}
您几乎已经涵盖了打印例程。只需两个提示:
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);
}
我留下了很多不完整的细节。那是故意的。这应该给你一个好的开始,但我也想让你享受一些乐趣!