1016 Phone Bills(map的遍历及使用)

本文详细解析了一种长距离电话公司的计费系统,该系统依据一天中不同的时间段收取不同的费用。通过输入文件中的费率结构和电话记录,文章展示了如何通过算法准备每月的电话账单,包括配对在线和离线记录、计算通话费用等关键步骤。

A long-distance telephone company charges its customers by the following rules:

Making a long-distance call costs a certain amount per minute, depending on the time of day when the call is made. When a customer starts connecting a long-distance call, the time will be recorded, and so will be the time when the customer hangs up the phone. Every calendar month, a bill is sent to the customer for each minute called (at a rate determined by the time of day). Your job is to prepare the bills for each month, given a set of phone call records.

Input Specification:

Each input file contains one test case. Each case has two parts: the rate structure, and the phone call records.

The rate structure consists of a line with 24 non-negative integers denoting the toll (cents/minute) from 00:00 - 01:00, the toll from 01:00 - 02:00, and so on for each hour in the day.

The next line contains a positive number N (≤1000), followed by N lines of records. Each phone call record consists of the name of the customer (string of up to 20 characters without space), the time and date (mm:dd:hh:mm), and the word on-line or off-line.

For each test case, all dates will be within a single month. Each on-line record is paired with the chronologically next record for the same customer provided it is an off-line record. Any on-line records that are not paired with an off-line record are ignored, as are off-line records not paired with an on-line record. It is guaranteed that at least one call is well paired in the input. You may assume that no two records for the same customer have the same time. Times are recorded using a 24-hour clock.

Output Specification:

For each test case, you must print a phone bill for each customer.

Bills must be printed in alphabetical order of customers' names. For each customer, first print in a line the name of the customer and the month of the bill in the format shown by the sample. Then for each time period of a call, print in one line the beginning and ending time and date (dd:hh:mm), the lasting time (in minute) and the charge of the call. The calls must be listed in chronological order. Finally, print the total charge for the month in the format shown by the sample.

Sample Input:

10 10 10 10 10 10 20 20 20 15 15 15 15 15 15 15 20 30 20 15 15 10 10 10
10
CYLL 01:01:06:01 on-line
CYLL 01:28:16:05 off-line
CYJJ 01:01:07:00 off-line
CYLL 01:01:08:03 off-line
CYJJ 01:01:05:59 on-line
aaa 01:01:01:03 on-line
aaa 01:02:00:01 on-line
CYLL 01:28:15:41 on-line
aaa 01:05:02:24 on-line
aaa 01:04:23:59 off-line

Sample Output:

CYJJ 01
01:05:59 01:07:00 61 $12.10
Total amount: $12.10
CYLL 01
01:06:01 01:08:03 122 $24.40
28:15:41 28:16:05 24 $3.85
Total amount: $28.25
aaa 01
02:00:01 04:23:59 4318 $638.80
Total amount: $638.80

Analyze:

       It's important to find paired records. We can sort these data in order by name and time. If the records are valid, the on-line record must be followed by off-line record. For conveniencce, we calculate cost from 00:00:00 to the time recorded. Because I don't konw how to use map(or not good at it) in stl. so I draw on the experience of LiuChuo's code.

#include<iostream>
#include<map>
#include<vector>
#include<algorithm>

using namespace std;

int toll[25];

struct Record{
	string name;
	int month, day, hour, minute, time;
	int status;
};

bool Cmp(Record a, Record b){
	if(a.name != b.name) return a.name < b.name;
	else return a.time < b.time;
}

double CalcCost(Record a){
	double cost = toll[a.hour] * a.minute + toll[24] * 60 * (a.day - 1);
	for(int i = 0; i < a.hour; i++)
		cost += toll[i] * 60;
	return cost / 100;
}

int main(){
	int N;
	string on_off;
	map<string, vector<Record>> m;
	for(int i = 0; i < 24; i++){
		scanf("%d", &toll[i]);
		toll[24] += toll[i];
	}
	scanf("%d", &N);
	vector<Record> records(N);
	for(int i = 0; i < N; i++){
		cin >> records[i].name;
		scanf("%d:%d:%d:%d", &records[i].month, &records[i].day, &records[i].hour, &records[i].minute);
		cin >> on_off;
		records[i].status = (on_off == "on-line") ? 1 : 0;
		records[i].time = records[i].day * 24 * 60 + records[i].hour * 60 + records[i].minute;
	}
	sort(records.begin(), records.end(), Cmp);
	for(int i = 1; i < N; i++){
		if(records[i].name == records[i - 1].name && records[i].status == 0 && records[i - 1].status == 1){
			m[records[i - 1].name].push_back(records[i - 1]);
			m[records[i].name].push_back(records[i]);
		}
	}
	for(auto it : m){
		vector<Record> temp = it.second;
		cout << it.first;
		printf(" %02d\n", temp[0].month);
		double total = 0;
		for(int i = 1; i < temp.size(); i += 2){
			double cost = CalcCost(temp[i]) - CalcCost(temp[i - 1]);
			printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n", temp[i - 1].day, temp[i - 1].hour, temp[i - 1].minute, temp[i].day, temp[i].hour, temp[i].minute, temp[i].time - temp[i - 1].time, cost);
			total += cost;
		}
		printf("Total amount: $%.2f\n", total);
	}
	return 0;
}

 

<think>好的,我现在需要帮用户解决用C++实现家庭财务管理系统的问题。用户之前已经用Python实现过,现在需要转换为C++版本。首先,我需要回顾之前的问题,确保C++代码满足所有需求。首先,用户的需求包括管理用户和账单,支持增删改查,以及统计功能。在Python中使用了类和列表来存储数据,现在在C++中需要使用类似的结构。考虑到C++的面向对象特性,可以定义User和Bill类,并使用vector来存储数据。 接下来,需要处理用户和账单的增删改操作。C++中需要手动管理内存,但使用vector可以简化这一点。添加用户时,需要生成唯一的ID,可以通过一个静态计数器来实现。修改用户信息时,需要遍历vector找到对应的ID,然后更新字段。删除操作可以用erase和remove_if组合实现。 对于账单管理,同样使用vector存储,每个账单关联用户ID。添加账单时同样需要自动生成ID。查询功能需要根据条件过滤vector中的元素,比如按类型、用户名或金额范围。这里要注意,C++中字符串比较需要使用compare方法,并且需要处理大小写是否敏感的问题,但用户需求中没有提到,暂时假设是精确匹配。 统计功能需要按月份和年份汇总账单金额。在Python中使用了字典,C++中可以用map或unordered_map来存储统计结果,键可以是年份和月份的组合,比如使用pair<int,int>。需要遍历所有账单,解析日期,然后累加到对应的统计条目中。日期解析在C++中可能比较麻烦,可以使用字符串流或手动分割字符串来处理。 然后,考虑数据持久化的问题。Python版本是内存存储,C++中可能需要文件操作来保存数据。但用户当前的需求可能只是基础功能,所以暂时不实现,但可以预留接口。 测试部分需要编写main函数来演示功能,添加用户和账单,调用各种方法并输出结果。需要注意的是C++的输出需要包含iostream头文件,并使用std::cout。现在,检查是否满足所有基本功能:1.用户增删改:已覆盖,add_user,modify_user, delete_user。2.账单增删改:add_bill,modify_bill,delete_bill。3.查询用户:searchUsersByName。 4.查询账单:searchBills,支持类型和用户名。5.金额范围查询:searchBillsByAmount。6.统计功能:getStatisticsByTime。可能遗漏的是按用户名查询账单,需要根据用户ID查找用户名,这需要辅助方法getUserName,通过用户ID查找对应的用户名称。在统计功能中,日期处理需要将字符串转换为月份和年份。这里使用substr方法分割字符串,假设日期格式是"YYYY-MM-DD"。如果格式不正确,可能需要错误处理,但用户示例中假设输入正确,暂不处理异常。 另外,用户管理中的删除操作需要考虑是否有账单关联,否则删除用户后账单会残留。但需求中没有提到级联删除,可能需要在delete_user时同时删除相关账单,或者保留账单但标记为无效。根据需求文档,可能不需要处理,但这是一个潜在的问题,用户可能后续会问到。现在编写代码,确保所有功能都被正确转换。注意C++中的字符串处理、范围查询、统计汇总等细节。最后,测试代码是否能够编译运行,并给出示例输出。</think>以下是使用C++实现的家庭财务管理系统基础框架: ```cpp #include <iostream> #include <vector> #include <string> #include <map> #include <ctime> using namespace std; class User { public: int user_id; string name; string phone; string address; User(int id, string n, string p, string a) : user_id(id), name(n), phone(p), address(a) {} }; class Bill { public: int bill_id; string bill_type; double amount; int user_id; string date; // 格式:YYYY-MM-DD Bill(int id, string type, double amt, int uid, string d) : bill_id(id), bill_type(type), amount(amt), user_id(uid), date(d) {} }; class FamilyFinanceSystem { private: vector<User> users; vector<Bill> bills; int user_counter = 1; int bill_counter = 1; public: // 用户管理 void addUser(const string& name, const string& phone, const string& address) { users.emplace_back(user_counter++, name, phone, address); } bool modifyUser(int user_id, const string& name = "", const string& phone = "", const string& address = "") { for (auto& user : users) { if (user.user_id == user_id) { if (!name.empty()) user.name = name; if (!phone.empty()) user.phone = phone; if (!address.empty()) user.address = address; return true; } } return false; } void deleteUser(int user_id) { users.erase(remove_if(users.begin(), users.end(), [user_id](const User& u) { return u.user_id == user_id; }), users.end()); } // 账单管理 void addBill(const string& type, double amount, int user_id, const string& date) { bills.emplace_back(bill_counter++, type, amount, user_id, date); } bool modifyBill(int bill_id, const string& type = "", double amount = -1) { for (auto& bill : bills) { if (bill.bill_id == bill_id) { if (!type.empty()) bill.bill_type = type; if (amount >= 0) bill.amount = amount; return true; } } return false; } void deleteBill(int bill_id) { bills.erase(remove_if(bills.begin(), bills.end(), [bill_id](const Bill& b) { return b.bill_id == bill_id; }), bills.end()); } // 查询功能 vector<User> searchUsersByName(const string& name) { vector<User> result; for (const auto& user : users) { if (user.name == name) { result.push_back(user); } } return result; } vector<Bill> searchBills(const string& type = "", const string& user_name = "") { vector<Bill> result; for (const auto& bill : bills) { bool type_match = type.empty() || (bill.bill_type == type); bool user_match = user_name.empty() || (getUserName(bill.user_id) == user_name); if (type_match && user_match) { result.push_back(bill); } } return result; } // 金额范围查询 vector<Bill> searchBillsByAmount(const string& type, double min_amt, double max_amt) { vector<Bill> result; for (const auto& bill : bills) { if (bill.bill_type == type && bill.amount >= min_amt && bill.amount <= max_amt) { result.push_back(bill); } } return result; } // 统计功能 map<pair<int, int>, map<string, double>> getStatisticsByTime(int year = 0, int month = 0) { map<pair<int, int>, map<string, double>> stats; for (const auto& bill : bills) { int y = stoi(bill.date.substr(0, 4)); int m = stoi(bill.date.substr(5, 2)); if ((year != 0 && y != year) || (month != 0 && m != month)) continue; auto key = make_pair(y, m); stats[key][bill.bill_type] += bill.amount; } return stats; } private: string getUserName(int user_id) { for (const auto& user : users) { if (user.user_id == user_id) { return user.name; } } return "Unknown"; } }; // 示例用法 int main() { FamilyFinanceSystem ffs; // 添加用户 ffs.addUser("张三", "13800138000", "北京市朝阳区"); // 添加账单 ffs.addBill("电费", 150.5, 1, "2024-05-10"); ffs.addBill("水费", 80.0, 1, "2024-05-12"); // 查询统计 auto stats = ffs.getStatisticsByTime(2024, 5); for (const auto& [period, types] : stats) { cout << period.first << "-" << period.second << "月统计:" << endl; for (const auto& [type, total] : types) { cout << type << ": " << total << endl; } } return 0; } ``` 代码解释: 1. 使用面向对象设计,`User`和`Bill`类存储基础数据 2. `FamilyFinanceSystem`类核心功能: - 使用vector存储用户和账单数据 - 使用lambda表达式实现数据删除 - 通过组合查询条件实现灵活搜索 - 使用map嵌套实现多维统计 3. 统计功能通过日期字符串解析实现年月过滤 4. 查询方法返回vector副本保证数据安全
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值