【问题标题】:C++, accessing a friend function data within a classC++,在类中访问友元函数数据
【发布时间】:2017-01-13 18:13:05
【问题描述】:

我编写了一个程序来收集用户的日常支出信息。我能够让程序的这一部分工作。它收集数据,然后显示数据。为了扩展程序,我现在希望它将数据存储在一个文本文件中,以便以后访问/修改。

因此,我在类中添加了一个友元函数(savedata),这样我就可以访问类中的所有私有数据。当我打印数据时,它似乎打印了日期和标签信息,但所有其他信息都显示为空白。我做错了什么,为什么我无法访问 PersonalExpenses 类中的其他私人信息?如果有人可以帮助我,请。谢谢你。

#include <iostream>
#include <iomanip>
#include <vector>
#include <array>
#include <string>
#include <ctime>
#include <fstream>

class PersonalExpenses{
private:
static constexpr size_t expense_count{5};
static const std::array<std::string, expense_count> labels;

std::string first_name;
std::string last_name;
std::tm date;
std::array<int, expense_count> expn;

public:
PersonalExpenses();

friend void savedata(PersonalExpenses id);

friend std::istream &operator>>(std::istream &in, PersonalExpenses &ud);
friend std::ostream& operator<<(std::ostream& out, const PersonalExpenses &ud);
};

const std::array<std::string, PersonalExpenses::expense_count>   PersonalExpenses::labels {
"Medical", "Cosmetics", "Stationery", "Food & Drinks", "Assorted"
};

PersonalExpenses::PersonalExpenses() {
time_t t = time(NULL);
date = *localtime(&t);
}

std::ostream& operator<<(std::ostream& out, const PersonalExpenses &ud) {

out << ud.last_name << ", " << ud.first_name
<< "\nExpenditure for "
<< std::put_time(&ud.date, "%B %e,`%y")
<< " is \n"
<< "\n";
for (size_t i=0; i < PersonalExpenses::expense_count; ++i ) {
    out << "      " << ud.labels[i] << ":" << ud.expn[i] << "$.\n";
}

return out;
}

std::istream &operator>>(std::istream &in, PersonalExpenses &ud) {
std::string val;
std::cout << "Enter your first name:";
std::getline(std::cin,ud.first_name);
std::cout << "Enter your last name:";
std::getline(std::cin,ud.last_name);

std::cout << "How much money did you spend today?. Specify (in  Dollars) against each category."<<std::endl;
for (size_t i=0; i < PersonalExpenses::expense_count; ++i) {
    std::cout << ud.labels[i] << " = " ;
    std::getline(std::cin, val);

    if (val.empty() || val.find_first_not_of(' ') ==    std::string::npos) {
        val = "0";
    }

    ud.expn[i] = std::stoi(val);
}
std::time_t t = std::time(nullptr);
ud.date = *std::localtime(&t);
return in;
}

bool addmore() {
std::string yn;
std::cout << "Would you like to add a name to the register or quit(Press 0 to exit or 1 to continue)?";
std::getline(std::cin, yn);
return yn != "0";
}

void savedata(PersonalExpenses id)
{

    std::ofstream data_file("Expenditure_data.txt",  std::fstream::app);

    if(data_file.good())
    {
        data_file << "\n" << id.first_name << "\n";
        data_file << id.last_name << "\n";
        data_file << std::put_time(&id.date, "%B %e,`%y") << "\n";
        data_file << id.labels[0] << ":" << id.expn[0] << "$.\n";
        data_file << id.labels[1] << ":" << id.expn[1] << "$.\n";
        data_file << id.labels[2] << ":" << id.expn[2] << "$.\n";
        data_file << id.labels[3] << ":" << id.expn[3] << "$.\n";
        data_file << id.labels[4] << ":" << id.expn[4] << "$.\n";
    }
    else
    {
        //You're in trouble!
    }

 }


int main() {
std::vector<PersonalExpenses> ledger;

while (addmore()) {
    PersonalExpenses udone;
    std::cin >> udone;
    ledger.push_back(udone);
}

for (const auto &item : ledger) {
    std::cout << "\n";
    std::cout << item << "\n";
}

PersonalExpenses id;
savedata(id);

}

【问题讨论】:

  • 请提供一个最小的例子,而不是你的整个程序。 sscce.org

标签: c++ friend-function


【解决方案1】:

您的文件包含无效数据的原因是您保存了无效数据。 savedata 函数工作正常。看看这部分,在你的主要结尾:

PersonalExpenses id;
savedata(id);

此默认构造一个PersonalExpenses 并保存它。这从未初始化的成员中读取,这是未定义的行为。你的函数可以做任何事情,包括完成随机字符并将其写入文件。请尝试以下示例。它将保存分类帐中的第一个条目,其中包含有效数据。

if(ledger.empty() == false) {
    savedata(ledger.front());
}

【讨论】:

  • 安德里厄,谢谢。我意识到我的错误。它确实有效。但就像你提到的那样,它保存了第一个条目。如果我希望它保存输入的多个信息怎么办。我猜我将不得不用其他东西替换 ledger.front() 。您能否让我知道该命令是什么,或者为我指明一些可以让我继续前进的文件的方向。谢谢。
  • @BigHead void savedata(PersonalExpenses id); 函数只节省了一笔费用。您必须对其进行更改以接受这样的费用向量:void savedata(std::vector&lt;PersonalExpenses&gt; id); 并修改函数的主体以适应更改。然后你可以简单地在你的main 中调用`savedata(ledger);`。与此无关,您应该更改 savedata 以接受 const 引用以避免复制所有内容。最终,它应该有这个原型:void savedata(const std::vector&lt;PersonalExpenses&gt; &amp; id);
  • 安德里厄。好的。知道了。谢谢你。我将不得不更改函数体。
猜你喜欢
  • 2018-08-14
  • 2020-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多