1. 项目概述
东华OJ基础题第28题"水果价格"是一个典型的C++入门级编程练习,主要考察基础语法、条件判断和格式化输出能力。题目模拟水果店收银场景,要求根据输入的水果代码和重量计算并输出对应金额。
这个题目看似简单,但涵盖了多个C++核心知识点:
- 标准输入输出处理
- 条件分支结构(if-else/switch)
- 浮点数运算精度控制
- 格式化输出控制
作为新手练习,它完美展现了如何用代码解决现实生活中的简单计算问题。我在大学任教时,经常用这类题目帮助学生建立"问题→算法→代码"的转化思维。
2. 题目需求解析
2.1 题目原文理解
根据网络搜索结果,题目描述大致为:
"一家水果店出售四种水果,每公斤价格为:苹果(代码a)1.5元,橘子(代码o)1.4元,香蕉(代码b)1.48元,菠萝(代码p)1.08元。编写程序使售货员输入代码和重量后输出应付款。"
2.2 输入输出规范
输入格式应为:
code复制[水果代码] [重量(公斤)]
例如:
code复制a 2.5
输出要求:
- 显示水果名称和金额
- 金额保留2位小数
- 非法代码需提示错误
示例输出:
code复制苹果:3.75元
2.3 边界情况分析
需要考虑的特殊情况:
- 代码大小写问题(A/a是否视为相同)
- 负重量输入
- 非数字重量输入
- 多余空格处理
- 未提及代码的处理
3. 实现方案设计
3.1 基础实现思路
最直接的实现方式是使用switch-case结构:
cpp复制char code;
double weight;
cin >> code >> weight;
switch(code) {
case 'a':
cout << "苹果:" << 1.5 * weight << "元";
break;
// 其他水果类似...
default:
cout << "错误代码";
}
3.2 进阶优化方向
-
价格常量定义:使用const常量而非魔法数字
cpp复制const double APPLE_PRICE = 1.5; -
输入验证:添加重量合法性检查
cpp复制if(weight <= 0) { cout << "重量必须大于0"; return 1; } -
代码规范化:统一转为小写处理
cpp复制code = tolower(code); -
输出格式化:使用iomanip控制小数位
cpp复制#include <iomanip> cout << fixed << setprecision(2);
4. 完整代码实现
4.1 基础版本代码
cpp复制#include <iostream>
#include <iomanip>
using namespace std;
int main() {
const double APPLE_PRICE = 1.5;
const double ORANGE_PRICE = 1.4;
const double BANANA_PRICE = 1.48;
const double PINEAPPLE_PRICE = 1.08;
char code;
double weight;
cout << "请输入水果代码和重量:";
cin >> code >> weight;
if(weight <= 0) {
cout << "错误:重量必须大于0";
return 1;
}
cout << fixed << setprecision(2);
switch(tolower(code)) {
case 'a':
cout << "苹果:" << APPLE_PRICE * weight << "元";
break;
case 'o':
cout << "橘子:" << ORANGE_PRICE * weight << "元";
break;
case 'b':
cout << "香蕉:" << BANANA_PRICE * weight << "元";
break;
case 'p':
cout << "菠萝:" << PINEAPPLE_PRICE * weight << "元";
break;
default:
cout << "错误:无效的水果代码";
return 1;
}
return 0;
}
4.2 面向对象改进版
对于想练习类封装的读者,可以这样重构:
cpp复制#include <iostream>
#include <iomanip>
#include <map>
using namespace std;
class FruitShop {
private:
map<char, pair<string, double>> priceTable = {
{'a', {"苹果", 1.5}},
{'o', {"橘子", 1.4}},
{'b', {"香蕉", 1.48}},
{'p', {"菠萝", 1.08}}
};
public:
void calculate() {
char code;
double weight;
cout << "请输入水果代码和重量:";
cin >> code >> weight;
if(weight <= 0) {
throw invalid_argument("重量必须大于0");
}
code = tolower(code);
auto it = priceTable.find(code);
if(it == priceTable.end()) {
throw invalid_argument("无效的水果代码");
}
auto& [name, price] = it->second;
cout << fixed << setprecision(2);
cout << name << ":" << price * weight << "元";
}
};
int main() {
try {
FruitShop shop;
shop.calculate();
} catch(const exception& e) {
cerr << "错误:" << e.what();
return 1;
}
return 0;
}
5. 关键知识点详解
5.1 格式化输出控制
C++中使用iomanip头文件控制输出格式:
cpp复制#include <iomanip>
// 固定小数格式
cout << fixed;
// 保留2位小数
cout << setprecision(2);
注意:setprecision会一直生效,直到再次修改。在需要恢复默认格式时使用:
cpp复制cout << defaultfloat;
5.2 浮点数比较问题
由于浮点数精度问题,避免直接使用==比较:
cpp复制// 不推荐
if(price == 1.5) {...}
// 推荐做法
const double EPSILON = 1e-6;
if(fabs(price - 1.5) < EPSILON) {...}
5.3 输入验证技巧
处理用户输入时的防御性编程:
cpp复制while(true) {
cout << "请输入重量:";
if(cin >> weight) {
if(weight > 0) break;
cout << "重量必须大于0,请重新输入\n";
} else {
cout << "请输入有效数字\n";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
6. 常见问题与解决方案
6.1 编译环境问题
很多新手会遇到"Microsoft Visual C++ 14.0 or greater is required"错误,解决方法:
- 安装最新Visual Studio Build Tools
- 或者使用MinGW等替代工具链
- 对于学生,推荐使用Dev-C++或Code::Blocks等轻量IDE
6.2 典型运行时错误
-
输入格式错误:
- 现象:输入"a2.5"(无空格)导致程序异常
- 解决:添加输入格式检查或使用getline+字符串解析
-
浮点数精度问题:
- 现象:1.48*2输出2.9600000000000004
- 解决:必须使用setprecision控制输出
-
大小写敏感问题:
- 现象:输入'A'无法识别
- 解决:统一转换为小写/大写处理
6.3 调试技巧
-
在关键位置添加调试输出:
cpp复制cout << "[DEBUG] code=" << code << ", weight=" << weight << endl; -
使用IDE的调试功能:
- 设置断点
- 单步执行
- 查看变量值
-
对于输入问题,可以先用固定值测试:
cpp复制// 测试时注释掉cin,使用固定值 char code = 'a'; double weight = 2.5;
7. 题目扩展练习
完成基础版本后,可以尝试以下扩展:
- 增加折扣策略(满10元打9折)
- 支持同时输入多种水果
- 添加销售记录功能
- 从文件读取价格表
- 图形化界面版本(Qt/WxWidgets)
例如折扣功能实现:
cpp复制double total = price * weight;
if(total >= 10) {
total *= 0.9;
cout << "(已应用9折优惠)";
}
cout << "总价:" << total << "元";
8. 学习建议
-
代码规范:从一开始就培养良好习惯
- 有意义的变量名
- 适当注释
- 合理空行分段
-
测试驱动:先设计测试用例再编码
- 正常情况
- 边界情况
- 异常输入
-
版本控制:使用Git管理代码版本
bash复制git init git add . git commit -m "基础版本完成" -
性能考量:虽然本题不关键,但要养成意识
- switch比多重if更高效
- 避免不必要的计算
- 减少IO操作
这个题目虽然简单,但涵盖了C++程序开发的完整流程。我在指导学生时发现,能把这类基础题目做到极致的学生,后期学习数据结构时往往表现更出色。建议初学者不要轻视基础练习,每个程序都力求代码整洁、功能完整、鲁棒性强。
