UVa 277 Cabinets
题目分析本题要求编写一个程序将制造商Woodcraft\texttt{Woodcraft}Woodcraft提供的橱柜电子目录数据重新格式化为符合Well‑Built Cabinet Distributors, Inc.\texttt{Well‑Built Cabinet Distributors, Inc.}Well‑Built Cabinet Distributors, Inc.库存软件要求的格式。输入是一个逗号分隔的ASCII文件每条记录包含555个字段Style Code\texttt{Style Code}Style Code风格代码111‑333位、Style Name\texttt{Style Name}Style Name风格名称000‑151515位、Description\texttt{Description}Description描述111‑151515位、Extension\texttt{Extension}Extension扩展信息000‑252525位、Unit Price\texttt{Unit Price}Unit Price单价美元×100\times 100×100000‑666位。记录按Style Code\texttt{Style Code}Style Code升序排列。输出同样是一个逗号分隔的ASCII文件。第一行为表头Item Id, Item Desc, Item Price。随后每条输出记录包含三个字段Item Id\texttt{Item Id}Item Id444‑131313位、Item Desc\texttt{Item Desc}Item Desc111‑303030位、Item Price\texttt{Item Price}Item Price444‑777位格式为xx.xx。输出记录按输入顺序生成每条输入记录对应一条输出记录但某些输入记录可能被拒绝不输出。解题思路第一步处理输入中的缺失字段题目给出的输入是逗号分隔格式但某些字段可能为空例如Style Name\texttt{Style Name}Style Name或Extension\texttt{Extension}Extension可以为空。在标准的逗号分隔格式中空字段仍然需要用逗号占位但本题的输入样例中空字段有时会被省略连续两个逗号之间没有内容导致每行的逗号数量不足555个。处理方式读取一行后统计该行中逗号的个数。如果逗号数量少于555则在行末尾补足逗号使字段总数达到555个。这样后续用逗号分割时每个字段包括空字段都能被正确提取。第二步按Style Code\texttt{Style Code}Style Code分组记录第一条的Style Name\texttt{Style Name}Style Name题目规定若某条记录的Style Name\texttt{Style Name}Style Name缺失则使用同一Style Code\texttt{Style Code}Style Code组中第一条记录的Style Name\texttt{Style Name}Style Name。如果第一条记录也没有Style Name\texttt{Style Name}Style Name则拒绝该记录。实现方式维护一个字典哈希映射codeAndName\texttt{codeAndName}codeAndName键为Style Code\texttt{Style Code}Style Code值为该组第一条记录的Style Name\texttt{Style Name}Style Name。对于当前处理的记录若当前Style Code\texttt{Style Code}Style Code不在字典中则将其Style Name\texttt{Style Name}Style Name可能为空字符串存入字典。后续遇到相同Style Code\texttt{Style Code}Style Code的记录时若自身的Style Name\texttt{Style Name}Style Name为空则从字典中取出该组的Style Name\texttt{Style Name}Style Name作为备用。第三步生成Item Id\texttt{Item Id}Item IdItem Id\texttt{Item Id}Item Id由Style Code\texttt{Style Code}Style Code和Description\texttt{Description}Description直接拼接而成。若Style Code\texttt{Style Code}Style Code长度不足333个字符则在左侧用字符’0’\texttt{0}’0’填充至333位。拼接后若总长度超过131313个字符则拒绝该记录。代码中通过限制Description\texttt{Description}Description长度不超过101010来间接保证Item Id\texttt{Item Id}Item Id长度不超过131313因为Style Code\texttt{Style Code}Style Code最多333位Description\texttt{Description}Description最多151515位但此处采用了更严格的条件——实际应检查拼接后长度若超过则跳过。第四步生成Item Desc\texttt{Item Desc}Item DescItem Desc\texttt{Item Desc}Item Desc由Style Name\texttt{Style Name}Style Name、一个连字符-和Extension\texttt{Extension}Extension拼接而成。若当前记录的Style Name\texttt{Style Name}Style Name为空则使用同Style Code\texttt{Style Code}Style Code组的第一条记录的Style Name\texttt{Style Name}Style Name从字典中获取。若该备用名也为空则拒绝该记录。若Extension\texttt{Extension}Extension非空则拼接-和Extension\texttt{Extension}Extension若Extension\texttt{Extension}Extension为空则Item Desc\texttt{Item Desc}Item Desc直接等于Style Name\texttt{Style Name}Style Name不加连字符。若拼接后的长度超过303030个字符则从右侧截断至303030个字符。第五步生成Item Price\texttt{Item Price}Item Price输入中的Unit Price\texttt{Unit Price}Unit Price单位为“美元×100\times 100×100”即整数形式例如890089008900表示 $$89.00$。输出时需要转换为带两位小数的格式xx.xx。若价格字段为空则输出默认值0.00。否则将字符串转换为整数除以100100100得到整数部分取模100100100得到小数部分。格式化时若小数部分不足222位则在左侧补0。第六步处理被拒绝的记录被拒绝的记录不输出任何内容直接跳过。代码中通过以下方式实现拒绝若Description\texttt{Description}Description长度超过101010隐含Item Id\texttt{Item Id}Item Id长度可能超过131313则跳过。若当前记录的Style Name\texttt{Style Name}Style Name为空且同组第一条的Style Name\texttt{Style Name}Style Name也为空则跳过。第七步输入与输出格式控制输入第一行为测试用例个数casescasescases随后有一个空行。每两个测试用例之间也有一个空行。对于每个测试用例首先输出表头行Item Id,Item Desc,Item Price。然后循环读取非空行每行处理一条记录直到遇到空行表示当前测试用例结束。两个测试用例的输出之间插入一个空行。代码实现// Cabinets// UVa ID: 277// Verdict: Accepted// Submission Date: 2016-05-26// UVa Run Time: 0.020s//// 版权所有C2016邱秋。metaphysis # yeah dot net#includebits/stdc.husingnamespacestd;intmain(intargc,char*argv[]){string line;getline(cin,line);// 读取测试用例个数intcasesstoi(line);// 转换为整数getline(cin,line);// 读取第一个测试用例之前的空行while(cases--){// 输出表头coutItem Id,Item Desc,Item Priceendl;// 存储每个 Style Code 组的第一条记录的 Style Namemapstring,stringcodeAndName;// 循环读取当前测试用例的每一条记录直到遇到空行while(getline(cin,line),line.length()0){// 统计当前行的逗号数量若不足 5 个则补足到 5 个intcommacount(line.begin(),line.end(),,);while(comma5){line.push_back(,);// 在行尾补逗号comma;}// 用逗号分割当前行提取 5 个字段vectorstringitem;istringstreamiss(line);for(string block;getline(iss,block,,);)item.push_back(block);// 为方便阅读将 5 个字段分别命名string codeitem[0],nameitem[1],descriptionitem[2];string extensionitem[3],priceitem[4];// 如果当前 Style Code 是第一次出现将其 Style Name 存入字典if(codeAndName.count(code)0)codeAndName.insert(make_pair(code,name));// 如果 Description 长度超过 10则 Item Id 可能超过 13 位拒绝该记录if(description.length()10)continue;// 生成 Item IdStyle Code 左补零至 3 位再拼接 Descriptionstring itemIdcode;while(itemId.length()3)itemId.insert(itemId.begin(),0);itemIddescription;// 生成 Item Desc优先使用当前记录的 Style Namestring itemDescname;if(itemDesc.length()0){// 若当前记录没有 Style Name则使用同组第一条记录的 Style Nameif(codeAndName[code].length()0)continue;// 若第一条也没有则拒绝该记录elseitemDesccodeAndName[code];}// 如果 Extension 非空则拼接连字符和 Extensionif(extension.length()){itemDesc-extension;// 如果超出 30 字符则从右侧截断if(itemDesc.length()30)itemDesc.erase(itemDesc.begin()30,itemDesc.end());}// 生成 Item Price将整数美元×100转换为带两位小数的字符串string itemPrice0.00;if(price.length()){intcentstoi(price);// 将价格字符串转为整数单位美分itemPriceto_string(cent/100);// 整数部分美元cent%100;// 剩余美分0-99itemPrice.;if(cent10)// 美分不足两位时补零itemPrice0;itemPriceto_string(cent);}// 输出格式化后的记录coutitemId,itemDesc,itemPriceendl;}// 两个测试用例的输出之间插入一个空行if(cases)coutendl;}return0;}