2017-01-13 12 views
-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); 함수는 단지 하나의 비용 만 저장합니다. 'void savedata (std :: vector id);'와 같은 비용의 벡터를 받아들이도록 변경해야하고 변경 내용을 수용하기 위해 함수 본문을 수정해야합니다. 그런 다음'mainata '에'savedata (ledger);를 호출하면됩니다. 이것과 무관하게 모든 것을 복사하는 것을 피하기 위해'savedata'를 const 참조를 허용하도록 변경해야합니다. 궁극적으로이 프로토 타입이 있어야합니다 :'void savedata (const std :: vector & id);' –

+0

Andrieux, 알았어. 고마워. 내가 함수의 본문을 바꿔야 할거야. –