C语言学习笔记20260623-真假话推理(3种方法)

C语言学习笔记20260623-真假话推理(3种方法)

一、学习目标

深入理解计算机解决逻辑推理题的核心思想------枚举法。通过经典的"3真1假"推理题,对比分析三种不同层级的代码实现方式,体会从"直观逻辑"到"结构化编程",再到"算法优化"的思维进阶过程。

二、问题拆解与核心逻辑

本题要求从A、B、C、D四人中找出做坏事的人,核心约束条件为:四人中恰好有3人说真话,1人说假话。四人的陈述转化为计算机可识别的布尔表达式如下:

  • A说"不是我" → bad != 'A'
  • B说"是C" → bad == 'C'
  • C说"是D" → bad == 'D'
  • D说"C在胡说" → bad != 'D'

三、方法一:拆分变量写法(直观逻辑)

3.1 代码解析

c 复制代码
char bad;
for (bad = 'A'; bad <= 'D'; bad++)
{
    int a_say = (bad != 'A');  // A:不是我
    int b_say = (bad == 'C');  // B:是C
    int c_say = (bad == 'D');  // C:是D
    int d_say = (bad != 'D');  // D:C撒谎
    int true_cnt = a_say + b_say + c_say + d_say;
    if (true_cnt == 3)
    {
        printf("犯错的人:%c\n", bad);
    }
}

3.2 核心思想与优势

这是最符合人类自然语言思维的实现方式。将四句话分别赋值给具名变量(a_say, b_say等),代码的可读性极高,任何初学者都能一眼看懂每行代码对应的现实逻辑。利用C语言中"真为1、假为0"的特性,将四个变量直接相加得到真话总数,简洁明了。

四、方法二:数组存储证词(结构化与扩展性)

4.1 代码解析

c 复制代码
char bad;
for (bad = 'A'; bad <= 'D'; bad++)
{
    int cond[4] = { bad != 'A', bad == 'C', bad == 'D', bad != 'D' };
    int sum = 0;
    for (int i = 0; i < 4; i++)
        sum += cond[i];
    if (sum == 3)
        printf("犯错的人:%c\n", bad);
}

4.2 核心思想与优势

此方法引入了"数据结构"和"循环"的思想。将四句证词的真假值封装进一个数组,并通过一个内层循环进行累加。

最大优势在于极强的扩展性:如果题目从4人扩展到100人,方法一需要手动写100个变量和100次加法,而方法二只需修改数组大小和循环条件。这体现了从"硬编码"到"通用算法"的工程思维跃迁。

五、方法三:switch分支枚举(算法优化与剪枝)

5.1 代码解析

c 复制代码
char bad;
for (bad = 'A'; bad <= 'D'; bad++)
{
    int total = 0;
    switch (bad)
    {
    case 'A': total = 0 + 0 + 0 + 1; break;
    case 'B': total = 1 + 0 + 0 + 1; break;
    case 'C': total = 1 + 1 + 0 + 1; break;
    case 'D': total = 1 + 0 + 1 + 0; break;
    }
    if (total == 3)
        printf("犯错的人:%c\n", bad);
}

5.2 核心思想与优势

这是一种"预计算"或"查表法"的优化思路。在编写代码前,程序员已经通过人脑推理,提前计算出了当A、B、C、D分别是坏人时,四句话的真假状态。

最大优势在于极致的运行效率 :在程序运行时的循环中,完全省去了4次关系运算(!===)以及4次加法运算,直接通过查表赋值获取结果。虽然代码的通用性变差(增加嫌疑人需要手动修改switch分支),但在处理固定规模、对性能有极致要求的场景下,这种"空间换时间"或"预计算"的思路极具价值。

总结

在C语言的学习与工程实践中,没有绝对最好的代码,只有最适合场景的代码。方法一是理解逻辑转化的基石;方法二展示了数据结构与循环带来的通用性,是进阶程序员的必备思维;方法三则揭示了底层优化的本质。掌握这三种写法,能够帮助我们在面对不同需求时,灵活权衡"可读性、扩展性与性能"三者之间的关系。