1.云服务计算
难度适中,通过stringstream对输入的字符串进行拆分;以及getline的用法
编写一个程序为某云服务计算客户话单,输入为某云服务的计费日志和各种计费因子的计费单价的列表,计费日志内容包含时间戳、客户标识、计费因子、计费时长4个字段。日志中如果同一客户同一计费因子在相同时间戳上报多次话单只能计费一次,选先上报的日志计费。计算每个客户的话单总费用。
解答要求
时间限制: C/C++ 1000ms,其他语言: 2000ms内存限制: C/C++ 256MB,其他语言: 512MB
输入
第1行表示计费日志的条数n,是一个正整数,范围是1<=n<=1000
第2到n+1行表示云服务的计费日志,共4列,第1列表示时间戳(是一个数字字符串,长度为10) 、第2列表示客户标识(是一个字符串,长度为1-16),第3列表示计费因子 (是一个字符串,长度为1-16,计费因子查不到时认为计费因子单价是0),第四列表示计费时长时长(范围为0-100,当计费时长不在范围内要认为是计费日志有问题,当成计费为0处理),这4个字段使用迈号分隔
第n+2行表示计费因子的数量m,m是一个正整数,范围是1<=m<=100
第n+3到n+3+m行表示各种计费因子的计费单价的列表,该表有2列,第1列表示计费因子 (是一个字符串,长度为1-16),第2列表示单价(是一个正整数,范围为1~100),这2个字段使用逗号分
输出
每个客户的话单总费用,共2列,第1列表示客户名,第2列表示话单费用,2列用逗号分割,输出按客户标识字典序升序排序
样例
输入
5
1627845600,client1,factorA,10
1627845605,client2,factorB,15
1627845610,ciient1,factorA,5
1627845610,client1,factorB,8
1627845620.client2,factorB,20
2
factorA,5
factorB,7
输出
client1,131
client2,245
思路与代码
本题题目量特别多,属于是阅读理解了,理解题目就简单。
通过stringstream对输入的字符串进行拆分;
通过set进行判断是否存在相同的时间戳客户和计费因子;
通过map进行存储不同的客户和计费因子;
最后合并统计出各个用户的消费。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n; cin >> n;
string a[5];
map<pair<string, string>, int> h1;
set<string> ses;
while (n -- )
{
string s, t;
cin >> s;
stringstream ss(s);
int k = 0;
while(getline(ss, t, ','))
a[k ++] = t;
string ts = a[0] + a[1] + a[2];
if(ses.count(ts)) continue;
else ses.insert(ts);
int tt = stoi(a[3]);
if(tt< 0 || tt > 100) continue;
h1[{a[1], a[2]}] += tt;
}
int m; cin >> m;
unordered_map<string, int> h2;
while (m -- )
{
string s, t;
cin >> s;
int k = 0;
stringstream ss(s);
while(getline(ss, t, ','))
a[k ++] = t;
h2[a[0]] = stoi(a[1]);
}
map<string, int> h3;
for(auto &[k, v] : h1)
{
string client = k.first, factor = k.second;
h3[client] += (h2[factor] * v);
}
vector<pair<string, int>> res;
for(auto &[k, v] : h3) res.push_back({k, v});
sort(res.begin(), res.end());
for(int i = 0; i < res.size(); i ++)
cout << res[i].first << "," << res[i].second << endl;
return 0;
}
stringstream的用法
C++中标准IO库有三大类
iostream : 支持对标准输入输出设备(键盘,显示器)的读写;
fstream: 支持对文件的读写;
stringstream: 支持对string 对象更灵活的处理;
stringstream 一般可以用来实现安全的数据类型转换:
以int 类型为例
1. int 类型转string 类型
int a = 50;
string b;
stringstream ss;
ss << a;
ss >> b;
// 转换后 b="50";
2. string 类型转int
int a ;
string b = "100";
stringstream ss;
ss << b;
ss >> a;
// a= 100
3. string 转wstring (wstring -> string)
string -> int -> wstring
===========================================
int a;
string b = "100";
wstring c;
stringstream ss;
ss << b;
ss >> a;
cout<<a<<endl;
wstringstream ws;
ws << a;
ws >> c;
wcout<<c<<endl;
getline用法
getline() 是 C++ 标准库中的一个函数,用于从输入流中读取一行文本,并将其存储为字符串。它可以从标准输入、文件流、字符串流等不同类型的输入流中读取数据
std::istream& getline(std::istream& is, std::string& str, char delim);
参数说明:
- is:输入流对象,可以是 std::cin(标准输入)、文件流对象(std::ifstream)、字符串流对象(std::istringstream)等等。
- str:存储读取到的一行文本的字符串。
- delim:分隔符,表示在哪个字符处停止读取,默认为换行符 '\n'。
返回值:
返回输入流对象的引用,通常是 is,表示函数成功执行。