2017-01-13 14 views
-1

私は、ユーザーからの1日の支出情報を収集するためのプログラムを作成しました。私はプログラムのこの部分を機能させることができました。データを収集して表示します。プログラムを拡張するために、後でアクセス/変更できるテキストファイルにデータを保存する必要があります。C++、クラス内のフレンド関数データにアクセス

したがって、私はクラス内のすべてのプライベートデータにアクセスできるように、クラス内にfriend関数(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); 

} 
+0

プログラム全体ではなく、最小限の例を示してください。 http://sscce.org/ – Klaus

答えて

0

ファイルに無効なデータが含まれている理由は、無効なデータを保存しているためです。 savedata関数は正常に動作します。あなたのメインの終わりに、この部分を見てみましょう:

PersonalExpenses id; 
savedata(id); 

このデフォルトはPersonalExpensesを構築し、それを保存します。初期化されていないメンバーから読み込みます。未定義の動作です。あなたは、ファイルに無作為な文字を仕上げたり、書き込んだりすることを含め、何かを行うことができます。代わりに次の例を試してください。それは有効なデータを含む元帳の最初のエントリを保存します。

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

Andrieuxありがとうございました。私は間違いを認識します。それは動作します。しかし、あなたが言ったように、それは最初のエントリを保存します。入力した複数の情報を保存する場合はどうすればいいですか?私はledger.front()を何か他のものに置き換えなければならないと思います。あなたは、そのコマンドがどんなものであるかを私に知らせてくれますか、私を得るための文書の指示に私を指摘してください。ありがとうございました。 –

+0

@BigHead 'void savedata(PersonalExpenses id);関数は、1つの経費を節約します。あなたは 'void savedata(std :: vector id);'のような経費のベクトルを受け入れるように変更しなければなりません。次に、 'main'に' savedata(ledger);を単に呼び出すことができます。それとは無関係に、 'savedata'を変更してすべてをコピーしないようにconst参照を受け入れるべきです。最終的に、このプロトタイプが必要です: 'void savedata(const std :: vector & id);' –

+0

Andrieux。OK。ありがとうございます。私は関数の本体を変更する必要があります。 –

関連する問題