C语言综述(二)
如何让程序作出判断?

从成绩奖金计算规则到 if-else 单分支结构

上节课的程序还缺什么?

已掌握:顺序结构

按顺序计算成绩平均分:

avg = (a + b) / 2.0;

新需求:条件分支

根据成绩不同,采用不同的计算公式。

程序如何根据条件选路径?

本课核心:先理清判断规则,再写条件分支。

第2课时学习目标

知识目标

  • 掌握关系运算符(<, >, <=, >=, ==, !=)
  • 理解单分支 if-else 的语法与执行流程
  • 理解条件真/假的判断逻辑

能力目标

  • 能将现实分类规则转化为 if-else 条件表达式
  • 掌握临界值/边界点测试方法(如 $x=54, 55, 56$)
  • 能识别常见易错点(如 == 写成 =、误加分号)
2.4 / 关系运算与判断条件
比较两个值的大小,
决定程序的走向
关系运算符比较逻辑真与假

现实问题:成绩奖金计算算法

规则要求

根据成绩发放奖金,规定:

  • 当成绩 $x < 55$ 时:
    奖金 $y = x \times 1.5$
  • 当成绩 $x \ge 55$ 时:
    奖金 $y = (x + 5) \times 1.5$

分析特征

这就是典型的二选一分支:

判断依据是:成绩是否小于 55?

关系运算符:比较两个值

数学含义 C语言表达式 说明
小于 55 x < 55 触发基础奖金计算 ($y = x \times 1.5$)
大于等于 55 x >= 55 触发激励奖金计算 ($y = (x+5) \times 1.5$)
小于等于 100 x <= 100 小于或等于关系
等于 55 x == 55 == 表示相等判断(注意区别于赋值 =)
不等于 0 x != 0 不等于关系比较

条件的“真”与“假”

判断结果

表达式 x < 55 计算后只有两种结果:

  • 真(True):满足条件(如 $x = 50$)
  • 假(False):不满足条件(如 $x = 60$)

C语言数值规则

在 C 语言内部:

  • 逻辑假用数值 0 表示
  • 逻辑真用非零数值(通常为 1)表示

关系比较的常见陷阱

陷阱一:把 == 误写成 =

if (x = 55)  /* 错误!这是赋值语句 */

把 55 赋值给 x,表达式结果恒为真!

if (x == 55) /* 正确:比较是否相等 */

陷阱二:数学连等直接照搬

if (0 <= x <= 100) /* 错误! */

C语言不会按数学逻辑连续比较!

正确写法:单条件分支逐步拦截。

2.5 / 单分支结构
if-else 语句:二选一路径
ifelse语法结构流程图

if-else 语句基本语法

语法格式


if (条件表达式) {
    /* 条件为真时执行的语句 */
} else {
    /* 条件为假时执行的语句 */
}
                

执行流程

  1. 首先计算括号内的条件表达式
  2. 若结果为真,执行 if 后的代码块
  3. 若结果为假,执行 else 后的代码块
  4. 分支执行完毕,汇合继续向下

成绩奖金计算完整代码


#include <stdio.h>

int main(void)
{
    double x, y;
    printf("请输入原始成绩: ");
    scanf("%lf", &x);

    if (x < 55) {
        y = x * 1.5;
    } else {
        y = (x + 5.0) * 1.5;
    }

    printf("计算所得奖金: %.1f\n", y);
    return 0;
}
        

单分支逻辑流程图

if-else流程图

流程特点解析

  • 入口只有一个:读取输入数据 $x$
  • 决策节点:判断条件 x < 55
  • 两条独立分支,互斥执行(只走一条路径)
  • 出口只有一个:输出计算所得奖金 $y$

代码规范:花括号与缩进

良好的书写习惯

  • 哪怕分支内只有一行代码,也始终加上 { }
  • 花括号内的代码保持统一 Tab/空格 缩进
  • if 和 else 对齐,结构清晰

避免“悬挂 else”隐患

省略花括号容易造成逻辑看错和对齐错觉。

加花括号是防止 Bug 的最简单有效习惯!

2.6 / 程序测试与边界验证
边界点测试:
确保程序临界判断精准
边界测试54/55/56测试用例

为什么要重点测试边界?

常见错误集中在临界点

程序员最容易把 < 55 错写成 <= 55。

普通测试值(如 20 或 80)无法暴露边界处的符号写错问题!

临界点确定

条件为 x < 55 时,临界数据刚好是 55。

我们需要取:临界点本身、刚好小于临界点、刚好大于临界点。

临界点测试设计:54、55、56

测试输入 $x$ 匹配条件 执行公式 预期输出奖金 $y$
54 (小于55) x < 55 (真) 54 * 1.5 81.0
55 (临界点) x < 55 (假) (55 + 5) * 1.5 90.0
56 (大于等于55) x < 55 (假) (56 + 5) * 1.5 91.5

思考:如果错误把代码写成 if (x <= 55),输入 55 时计算出的奖金会变成多少?

单分支典型错误:分号陷阱

错误:if 条件后面误加分号


if (x < 55); {  /* 注意末尾的分号! */
    y = x * 1.5;
}
                

分号代表“空语句”,导致 if 结束!后方的 `{ }` 会无条件执行!

总结口诀

if 括号后面不要随手打分号!

分号放在具体语句的结尾,而不是条件判断句之后。

边界测试与陷阱小结

测试要点总结

  • 临界值测试(如 54, 55, 56)是验证 < 与 <= 符号准确性的关键。
  • 必须用程序输出结果与手算预期结果逐一比对。

语法陷阱防御

  • 严禁在 if (条件) 括号后直接随手写分号!
  • 严格区分相等比较 == 与赋值符号 =。
2.7 / 数据输入与类型
scanf 详解:
整数与浮点数输入
scanffloatdouble%d / %f / %lf

scanf 格式占位符与数据类型

常用数据类型与占位符

类型说明 C语言关键字 scanf 占位符 printf 占位符
整型 int %d %d
单精度浮点型 float %f %f
双精度浮点型 double %lf %f / %.2f

输入原理

scanf 按照占位符指示的格式,从键盘读取数据并写入变量所对应的内存地址。

注意:必须使用 & 取地址符传递变量存储地址!

单精度 float 与双精度 double 的区别

内存占用与精度对比

特性 float (单精度) double (双精度)
占用内存 4 字节 (32 位) 8 字节 (64 位)
有效数字 约 6 ~ 7 位数字 约 15 ~ 17 位数字
scanf 占位符 %f %lf (不可省略 l)

开发建议

在 C 语言程序设计中,涉及小数计算时,推荐优先选用 double 类型。

它能大幅降低浮点数累计误差,且在现代 CPU 上运算效率极高。

代码演进:从整数到浮点数输入

整数版本 (int)


int x;
scanf("%d", &x);
if (x < 55) {
    y = x * 1.5;
}
                

缺点:无法输入带有小数的成绩(如 54.5 分)。

浮点数版本 (double)


double x, y;
scanf("%lf", &x);
if (x < 55) {
    y = x * 1.5;
}
                

优点:精准支持小数输入与高精度奖金计算。

scanf 输入浮点数易错点

易错点一:double 类型混用 %f


double x;
scanf("%f", &x);  /* 错误!scanf 中 double 必须用 %lf */
                

会导致内存数据截断或未定义解析错误!

易错点二:遗漏 & 取地址符


double x;
scanf("%lf", x);  /* 错误!未加 & 传递地址 */
                

程序运行时会导致非法内存写入崩溃(Segmentation Fault)!

2.8 / 常用数学函数
C语言标准数学库:
头文件 <math.h> 与常用函数
<math.h>sqrtfabspowexp / log

引入数学库 <math.h>

引入方式

在源程序顶部加入预处理指令:

#include <math.h>

该头文件声明了标准数学运算相关函数的函数原型。

适用场景

当需要完成超出加减乘除基本运算符的复杂数学计算(如求根号、绝对值、次方等)时使用。

常用数学函数一览表

函数原型 功能说明 数学对应 示例与结果
double sqrt(double x) 求平方根 $\sqrt{x}$ sqrt(9.0) $\to$ 3.0
double fabs(double x) 求浮点数绝对值 $|x|$ fabs(-5.5) $\to$ 5.5
double pow(double x, double y) 求 $x$ 的 $y$ 次方 $x^y$ pow(2.0, 3.0) $\to$ 8.0
double exp(double x) 求 $e$ 的 $x$ 次方 $e^x$ exp(1.0) $\to$ 2.71828...
double log(double x) 求自然对数 $\ln(x)$ log(2.7182818) $\to$ 1.0

示例代码:数学函数的应用


#include <stdio.h>
#include <math.h>

int main(void)
{
    double x = 16.0, a = -7.5;

    printf("sqrt(16.0) = %.2f\n", sqrt(x));    /* 输出: 4.00 */
    printf("fabs(-7.5) = %.2f\n", fabs(a));    /* 输出: 7.50 */
    printf("pow(2, 3)   = %.2f\n", pow(2.0, 3.0)); /* 输出: 8.00 */
    return 0;
}
        

第2课时全课小结

  • 关系运算符:<, >, <=, >=, ==, != 用于条件判断。
  • if-else 结构:实现二选一单分支,代码必须注意 {{ }} 规范。
  • 边界点测试:测试临界值(如 54, 55, 56)确保分支判断精准。
  • scanf 数据输入:理解 int (%d)、float (%f)、double (%lf) 格式占位符与取地址符 &。
  • 数学库 <math.h>:熟练使用 sqrt、fabs、pow、exp、log 等常用数学函数。