1. 题目解析与需求拆解
这道题目要求我们编写一个C++程序,根据输入的电量值输出对应的显示内容。具体规则如下:
- 当电量≤10时,输出字符"R"
- 当10<电量≤20时,输出字符"L"
- 当电量>20时,直接输出电量数值
题目还要求我们处理多组输入数据,即首先输入一个整数t表示测试用例的数量,然后循环t次处理每个电量值。
1.1 输入输出分析
输入格式:
- 第一行一个整数t,表示测试用例的数量
- 接下来t行,每行一个整数p,表示手机电量值
输出格式:
对于每个测试用例:
- 如果p≤10,输出"R"
- 如果10<p≤20,输出"L"
- 如果p>20,输出p的值
示例:
输入:
3
5
15
25
输出:
R
L
25
1.2 核心算法设计
这个问题的核心在于条件判断和循环控制:
- 使用一个循环来处理多个测试用例
- 在循环体内,使用条件判断语句根据电量值决定输出内容
- 注意边界条件的处理(特别是等于10和20的情况)
2. 代码实现详解
2.1 基础实现
我们先来看题目给出的基础实现代码:
cpp复制#include <iostream>
using namespace std;
int main() {
int t;
cin >> t;
while(t--) {
int p;
cin >> p;
if(p <= 10) {
cout << "R" << endl;
}
else if(p <= 20) {
cout << "L" << endl;
}
else {
cout << p << endl;
}
}
return 0;
}
这段代码已经很好地解决了问题,但我们可以从多个角度进行优化和扩展。
2.2 代码优化建议
- 输入验证:在实际应用中,我们应该验证输入的有效性
- 性能优化:对于大量输入,可以考虑使用更快的输入方式
- 可读性改进:添加适当的注释和常量定义
优化后的代码示例:
cpp复制#include <iostream>
using namespace std;
// 定义常量提高代码可读性
const int LOW_BATTERY_THRESHOLD = 10;
const int MEDIUM_BATTERY_THRESHOLD = 20;
int main() {
int testCases;
cin >> testCases;
// 验证输入有效性
if(testCases <= 0) {
cerr << "无效的测试用例数量" << endl;
return 1;
}
for(int i = 0; i < testCases; ++i) {
int batteryLevel;
cin >> batteryLevel;
// 验证电量值有效性
if(batteryLevel < 0) {
cerr << "电量值不能为负" << endl;
continue;
}
if(batteryLevel <= LOW_BATTERY_THRESHOLD) {
cout << "R" << endl;
}
else if(batteryLevel <= MEDIUM_BATTERY_THRESHOLD) {
cout << "L" << endl;
}
else {
cout << batteryLevel << endl;
}
}
return 0;
}
2.3 边界条件测试
编写测试用例时,特别要注意边界条件:
- 电量正好等于10
- 电量正好等于20
- 电量为0
- 电量为负数(虽然题目可能不要求处理)
测试用例示例:
输入:
5
10
20
0
-5
25
预期输出:
R
L
R
(错误提示)
25
3. 进阶思考与扩展
3.1 多级电量显示
实际应用中,手机电量显示通常有更多级别。我们可以扩展这个程序:
cpp复制#include <iostream>
#include <vector>
#include <utility>
using namespace std;
vector<pair<int, string>> batteryLevels = {
{0, "🟥"}, // 0-5% 红色
{5, "🟧"}, // 5-20% 橙色
{20, "🟨"}, // 20-50% 黄色
{50, "🟩"} // 50%+ 绿色
};
string getBatteryIndicator(int level) {
if(level < 0) return "❌";
for(int i = batteryLevels.size() - 1; i >= 0; --i) {
if(level >= batteryLevels[i].first) {
return batteryLevels[i].second;
}
}
return "❌";
}
int main() {
int testCases;
cin >> testCases;
for(int i = 0; i < testCases; ++i) {
int level;
cin >> level;
cout << getBatteryIndicator(level) << endl;
}
return 0;
}
3.2 性能优化技巧
对于大规模输入(如t>100000),可以考虑以下优化:
- 使用更快的输入方法:
cpp复制ios::sync_with_stdio(false);
cin.tie(nullptr);
- 减少不必要的函数调用
- 使用更高效的条件判断结构
优化后的输入处理:
cpp复制int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while(t--) {
int p;
cin >> p;
// 使用switch可能更快
if(p <= 10) {
cout << "R\n";
}
else if(p <= 20) {
cout << "L\n";
}
else {
cout << p << '\n';
}
}
return 0;
}
4. 常见问题与解决方案
4.1 输入处理问题
问题1:程序在输入非数字时崩溃
解决方案:添加输入验证
cpp复制if(!(cin >> p)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cerr << "输入无效,请输入数字" << endl;
continue;
}
问题2:大量输入时程序运行缓慢
解决方案:使用更快的输入方法,如前文提到的ios优化
4.2 逻辑错误
问题1:边界条件处理不当
解决方案:明确测试边界值(10和20)
cpp复制// 测试边界值
assert(getDisplay(10) == "R");
assert(getDisplay(20) == "L");
assert(getDisplay(21) == "21");
问题2:条件判断顺序错误
解决方案:确保条件判断的顺序正确,从最严格的条件开始
4.3 输出格式问题
问题1:输出多余的空格或换行
解决方案:统一使用endl或'\n',不要混用
cpp复制// 统一使用这种方式
cout << result << '\n';
5. 实际应用扩展
在实际开发中,我们可以将这个简单的电量显示功能扩展为一个完整的电池管理系统:
- 电池状态类设计:
cpp复制class BatteryManager {
public:
enum class Status { Critical, Low, Medium, High };
BatteryManager() : level_(0) {}
void setLevel(int level) {
level_ = max(0, level); // 确保不为负
}
Status getStatus() const {
if(level_ <= 10) return Status::Critical;
if(level_ <= 20) return Status::Low;
if(level_ <= 50) return Status::Medium;
return Status::High;
}
string getDisplay() const {
switch(getStatus()) {
case Status::Critical: return "R";
case Status::Low: return "L";
case Status::Medium: return "M";
case Status::High: return to_string(level_);
default: return "?";
}
}
private:
int level_;
};
- 使用示例:
cpp复制int main() {
BatteryManager battery;
int t;
cin >> t;
while(t--) {
int p;
cin >> p;
battery.setLevel(p);
cout << battery.getDisplay() << '\n';
}
return 0;
}
- 单元测试:
cpp复制void testBatteryManager() {
BatteryManager b;
b.setLevel(5);
assert(b.getDisplay() == "R");
b.setLevel(15);
assert(b.getDisplay() == "L");
b.setLevel(25);
assert(b.getDisplay() == "25");
b.setLevel(-5);
assert(b.getDisplay() == "R"); // 被限制为0
cout << "所有测试通过!" << endl;
}
6. 编程技巧与最佳实践
- 使用枚举提高可读性:
cpp复制enum class BatteryLevel { Critical, Low, Normal, High };
- 避免魔法数字:
cpp复制constexpr int kCriticalThreshold = 10;
constexpr int kLowThreshold = 20;
-
单一职责原则:
将电量判断逻辑与显示逻辑分离 -
防御性编程:
处理无效输入和边界条件 -
性能考虑:
对于高频调用的简单判断,使用内联函数
cpp复制inline BatteryLevel getBatteryLevel(int p) {
if(p <= 10) return BatteryLevel::Critical;
if(p <= 20) return BatteryLevel::Low;
return BatteryLevel::Normal;
}
-
跨平台考虑:
如果需要显示图形符号,考虑不同平台的兼容性 -
国际化支持:
考虑将显示文本提取为可配置的资源
cpp复制const map<BatteryLevel, string> kDisplayText = {
{BatteryLevel::Critical, "R"},
{BatteryLevel::Low, "L"},
{BatteryLevel::Normal, "N"},
{BatteryLevel::High, "H"}
};
通过这个简单的题目,我们不仅学习了基础的分支和循环结构,还探讨了如何将其扩展为更实用的程序组件,并应用了多种编程最佳实践。