当一个输入可能同时满足多个条件,并且题目要求输出所有命中的结果时,条件之间不是互斥关系。此时应分别判断每个条件,而不是使用只选择一个分支的 if ... else if ... 链。
独立判断与互斥分支
例如,要输出正整数 n 在 3、5、7 中所有能整除它的数,可以用取余判断整除:
n % d == 0
其中余数为 0 表示 n 能被 d 整除。因为 15 可以同时命中 3 和 5,三个判断应彼此独立:
if (n % 3 == 0) { /* 输出 3 */ }
if (n % 5 == 0) { /* 输出 5 */ }
if (n % 7 == 0) { /* 输出 7 */ }
如果改成 if ... else if ...,第一个成立的分支执行后,后续分支不会再判断,因此只能得到一个结果。else if 适合“至多选择一个结果”的互斥分类;多个条件可以同时成立时,应使用独立 if,或者先收集全部命中结果再统一处理。
用“是否已有输出”控制分隔符
连续输出多个结果时,常见格式是元素之间有空格、首尾没有多余空格。与其枚举单项、两两组合和全部组合,不如维护一个状态:前面是否已经输出过元素。
#include <iostream>
int main()
{
int n;
std::cin >> n;
bool has_output = false;
if (n % 3 == 0) {
std::cout << 3;
has_output = true;
}
if (n % 5 == 0) {
if (has_output) std::cout << ' ';
std::cout << 5;
has_output = true;
}
if (n % 7 == 0) {
if (has_output) std::cout << ' ';
std::cout << 7;
has_output = true;
}
return 0;
}
状态的含义是:
false:当前元素是第一个,直接输出;true:前面已有元素,先输出分隔符,再输出当前元素。
这里用 bool 比用 int flag = 0/1 更直接地表达二值语义。核心模式不是变量名 flag,而是“在非首个元素之前输出分隔符”。它同样适用于逗号分隔、日志字段拼接和简单文本序列化。
更易扩展的写法
候选值增多时,可以把重复判断改为循环:
const int divisors[] = {3, 5, 7};
bool has_output = false;
for (int d : divisors) {
if (n % d != 0) continue;
if (has_output) std::cout << ' ';
std::cout << d;
has_output = true;
}
这种写法的复杂度随候选数量线性增长;枚举所有命中组合则会迅速膨胀,也更容易遗漏。
边界与检查
- 如果没有任何条件命中,应该输出什么,必须由题目或接口契约决定;不能自行假定为空输出、
0或提示文字。 - 不应默认末尾多余空格一定会被接受。严格评测、协议文本和快照测试可能逐字符比较输出。
- 候选顺序决定输出顺序;若要求升序或指定顺序,应按该顺序检查或先收集后排序。
- 测试应覆盖:无命中、单个命中、多个命中和全部命中,而不只是普通输入。
相关知识
- 编程范式与命名约定