题目分析
本题是一道电话计费模拟题,要求根据拨打的号码和通话时长,结合给定的区号(或国家代码)与费率表,计算出每一通电话的费用。
输入格式
输入分为两部分:
费率表
每行格式为:代码 地区名称$每分钟费用(美分)地区名称不超过252525个字符,费率以美分为单位。
此部分以一行000000结束。通话记录
每行格式为:号码 时长(分钟)号码与时长之间至少有一个空格。
此部分以一行#结束。
号码分类
- 国际长途(IDD\texttt{IDD}IDD):以
00开头,后接111至333位国家代码,再后接444至101010位用户号码。 - 国内长途(STD\texttt{STD}STD):以
0开头(但非00),后接111至555位区号,再后接444至777位用户号码。 - 本地通话:不以
0开头,免费。 - 无效号码:若号码以
0或00开头,但未在费率表中找到匹配的代码,或用户号码长度不符合规定,则视为Unknown,费用为−1.00-1.00−1.00。
输出格式
输出每行包含:
- 拨打的号码(左对齐,宽度161616)
- 地区名称
- 用户号码
- 通话时长(右对齐,宽度555)
- 每分钟费用(右对齐,宽度666,保留两位小数)
- 总费用(右对齐,宽度777,保留两位小数)
若为未知号码,则每分钟费用处留空。
解题思路
步骤分解
解析费率表
将每行的代码、地区名称、费率分别提取出来,存储在一个结构体数组中。处理通话记录
对每条记录:- 提取号码和时长。
- 根据号码前缀判断类型:
- 若以
00开头,尝试匹配国际代码。 - 若以
0开头(非00),尝试匹配国内区号。 - 否则为本地通话。
- 若以
- 匹配时需检查用户号码长度是否符合规定。
- 若未匹配成功,则为
Unknown。
计算费用
费率以美分存储,计算时需除以100.0100.0100.0转换为美元。格式化输出
使用cout的格式化输出功能(如setw、setprecision)控制对齐与精度。
关键点
- 匹配代码时使用
find判断前缀是否一致。 - 用户号码长度需在匹配后验证。
- 输出格式需严格对齐,包括空格数量。
代码实现
// Telephone Tangles// UVa ID: 139// Verdict: Accepted// Submission Date: 2016-01-19// UVa Run Time: 0.085s//// 版权所有(C)2016,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;structprice{string code;string area;intcost;};intmain(){string line;vector<price>prices;// 处理第一部分输入while(getline(cin,line),line.find("000000")!=0){string code,area,fee;intindex=0;while(index<line.length()&&isdigit(line[index]))code+=line[index++];// 跳过空格,直到 $ 都属于国家或地区名称index++;while(index<line.length()&&line[index]!='$')area+=line[index++];// 跳过 $index++;while(index<line.length()){if(isdigit(line[index]))fee+=line[index];index++;}// cout << code << " " << area << " " << fee << endl;prices.push_back((price){code,area,stoi(fee)});}// 处理第二部分输入并输出while(getline(cin,line),line!="#"){intindex=0;string calledNumber,duration;while(index<line.length()&&isdigit(line[index]))calledNumber+=line[index++];while(index<line.length()&&isblank(line[index]))index++;while(index<line.length()&&isdigit(line[index]))duration+=line[index++];string area,subscriber;doublecost,totalCost;boolunknown=true;for(inti=0;i<prices.size();i++){if(calledNumber.find(prices[i].code)==0){area=prices[i].area;subscriber=calledNumber.substr(prices[i].code.length());if(calledNumber.find("00")==0){if(subscriber.length()<4||subscriber.length()>10)continue;}elseif(calledNumber.find("0")==0){if(subscriber.length()<4||subscriber.length()>7)continue;}cost=prices[i].cost/100.00;totalCost=stoi(duration)*cost;unknown=false;break;}}if(unknown){if(calledNumber.find("00")==0||calledNumber.find("0")==0){area="Unknown";subscriber.clear();totalCost=-1.0;}else{area="Local";subscriber=calledNumber;cost=0.00;totalCost=0.0;unknown=false;}}cout.setf(ios::fixed);cout<<setw(16)<<left<<calledNumber;cout<<area;cout<<string(35-area.length()-subscriber.length(),' ');cout<<subscriber;cout<<setw(5)<<right<<duration;if(unknown)cout<<string(6,' ');elsecout<<setw(6)<<right<<setprecision(2)<<cost;cout<<setw(7)<<right<<setprecision(2)<<totalCost;cout<<endl;}return0;}总结
本题主要考察字符串处理与格式化输出能力,同时需要注意细节处理(如号码长度验证、费用单位转换)。通过合理设计数据结构并逐步匹配,即可正确计算并输出每通电话的费用。