![見出し画像](https://assets.st-note.com/production/uploads/images/146110255/rectangle_large_type_2_f35b270eaa5e5105401ae3514a91d591.jpeg?width=1200)
2024-07-03C++プログラミング練習
こんにちわ。ケロッグです。今日も今日とてC++プログラミング練習をChatGPTと一緒にやっていきます。
いつもと同じようにGPTに問題を出してもらって、プログラムを書いて、フィードバックをもらいます。今日はフィードバックをもらってさらにプログラムを書き直しました。
GPTとのやり取り
今日の学び
今日の学びを先に書いてしまいます。今日、主に学んだことは以下の2点です。
・ポインタ渡しと参照渡しの違い
・参照型への型推論
ポインタ渡しと参照渡しの違い
値渡しとそれ以外については、違いを理解できていましたが、今回プログラムを書くときに、ポインタ渡しをしようか参照渡しをしようか学びました。この2つ、何が違うねんと思って迷ってしまいました。詳しい解説は他の記事に譲るとして、今回私の中で言語化したものを残しておきます。
ポインタ渡し
・変数のメモリ上のアドレスを渡す。
・NULLチェックが必要。
参照渡し
・元の変数に別名をつける。
・NULLがない。→呼び出し元で、NULLでないことをプログラムに文法レベルで要求される。
つまり、主な違いはNULLがあるかないか。参照渡しはNULLがないことで簡易的に渡すことができるが、渡しているものがNULLではないことをしっかり保証してあげる必要がある。
参照型への型推論
下は今回書いたプログラムの一部です。
Transactionクラスのベクター型にtransactionsベクターを定義しています。そして、範囲for文の中で型推論を行い、auto& transactionはTransaction&と推論されていることがわかります。これは教科書いわく良く使う書き方らしいので、しっかり覚えておきたいです。
class HouseholdAccount {
private:
std::vector<Transaction> transactions;
public:
void addTransaction(const Transaction& transaction) {
transactions.push_back(transaction);
}
void printMonthlyReport() {
std::map<std::string, int> monthlyBalance;
for (const auto& transaction : transactions) {
// 型推論を使用
const auto& date = transaction.getDate();
std::string month = date.substr(0, 7); // YYYY-MM 部分を抽出
monthlyBalance[month] += transaction.getAmount();
}
今回作った成果物
最後に今回作った成果物を載せておきます。
簡易的な家計簿アプリを作りました。いちいちコマンド上で入力しなくてはいけないので、使い物になりませんが、これを応用してCSVなどからデータをインプットする仕様にすれば、使い道はあるかなあと思いました。
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip> // for std::setw
class Transaction {
private:
std::string Category;
int Money;
std::string Day;
public:
Transaction(const std::string& category, int money, const std::string& day)
: Category(category), Money(money), Day(day) {}
std::string getCategory() const { return Category; }
int getMoney() const { return Money; }
std::string getDay() const { return Day; }
};
class HouseholdAccount {
private:
std::vector<Transaction> transactions;
public:
void addTransaction(const Transaction& transaction) {
transactions.push_back(transaction);
}
void printMonthlyReport() const {
std::cout << "月間レポート" << std::endl;
if (transactions.empty()) {
std::cout << "取引がありません。" << std::endl;
return;
}
int sumIncome = 0;
int sumExpense = 0;
std::cout << std::setw(12) << "日付" << std::setw(12) << "金額" << std::setw(20) << "カテゴリー" << std::endl;
std::cout << "----------------------------------------" << std::endl;
for (const auto& transaction : transactions) {
std::cout << std::setw(12) << transaction.getDay() << std::setw(12) << transaction.getMoney() << std::setw(20) << transaction.getCategory() << std::endl;
if (transaction.getMoney() >= 0) {
sumIncome += transaction.getMoney();
} else {
sumExpense += transaction.getMoney();
}
}
std::cout << "----------------------------------------" << std::endl;
std::cout << std::setw(12) << "合計収入:" << std::setw(12) << sumIncome << std::endl;
std::cout << std::setw(12) << "合計支出:" << std::setw(12) << sumExpense << std::endl;
std::cout << std::setw(12) << "純収支:" << std::setw(12) << sumIncome + sumExpense << std::endl;
}
};
int main() {
HouseholdAccount acc;
std::string day;
std::string moneyStr;
std::string category;
while (true) {
std::cout << "取引の日付を入力してください (例: 2024-07-03): ";
std::getline(std::cin, day);
if (day.empty()) {
break;
}
std::cout << "金額を入力してください: ";
std::getline(std::cin, moneyStr);
std::istringstream moneyStream(moneyStr);
int money;
if (!(moneyStream >> money)) {
std::cout << "無効な金額です。再度入力してください。" << std::endl;
continue;
}
std::cout << "カテゴリーを入力してください: ";
std::getline(std::cin, category);
Transaction tra(category, money, day);
acc.addTransaction(tra);
}
acc.printMonthlyReport();
return 0;
}
出力
![](https://assets.st-note.com/img/1720019868112-1yhPCzK0sA.png)
今日は以上です。どうもありがとうございました。