C Day 20

找到一个可以停,
统计全部要走完

今天在数组遍历的基础上加入条件判断,从寻找第一个目标开始,再学习统计所有匹配项的次数和下标。

先分清目标、位置和状态

练习数组是 {4, 7, 2, 7, 9, 7}。target 表示要找的数,index 表示当前下标,values[index] 是该位置的数据;found 则记录是否已经找到目标,初始为 0,找到后改为 1。

预测输出时,我曾把目标值、下标和标记混在一起。订正后确认:查找 7 的首个匹配结果是“找到 7,下标 = 1”,found 变为 1,但这个 1 不是目标值。

只找第一个匹配:找到后停止

day20.c · 首个匹配
int values[6] = {4, 7, 2, 7, 9, 7};
size_t count = sizeof(values) / sizeof(values[0]);
int target = 7;
int found = 0;

for (size_t index = 0; index < count; index++)
{
    if (values[index] == target)
    {
        printf("找到 %d,下标 = %zu\n", target, index);
        found = 1;
        break;
    }
}
if (found == 0)
{
    printf("没有找到 %d\n", target);
}
printf("查找结束\n");

这里的 break 结束 for 循环,不会结束整个程序,所以循环外的“查找结束”仍然输出。查找 7 时,不再继续检查后面两个 7。

为什么“没有找到”要在循环后判断

我最初只解释为“放在循环内会判断多次”。更重要的原因是:当前元素不匹配,后面仍然可能有目标,不能过早下结论。

只有完整检查后仍然没有匹配,才能判断不存在。found 把查找状态保留下来,让循环后的判断有依据。查找 8 时,所有元素都检查完,found 仍为 0,才输出“没有找到 8”。

统计全部匹配:计数器累计,不使用 break

day20.c · 全部匹配
int search_target = 7;
size_t match_count = 0;

for (size_t index = 0; index < count; index++)
{
    if (values[index] == search_target)
    {
        match_count++;
        printf("匹配下标 = %zu\n", index);
    }
}
printf("%d 共出现 %zu 次\n", search_target, match_count);
printf("统计结束\n");

match_count 在循环外初始化,每找到一个就加 1。如果找到后使用 break,只能记录首个匹配,无法统计后面的目标。count 是数组元素数量,这里为 6;match_count 是匹配次数,查找 7 时为 3。

实际运行:多次、一次和零次

  • 首个匹配查找 7:下标 1,之后输出“查找结束”。
  • 首个匹配查找 8:输出“没有找到 8”和“查找结束”。
  • 全部统计 7:输出匹配下标 1、3、5,共出现 3 次。
  • 全部统计 9:输出匹配下标 4,共出现 1 次。
  • 全部统计 8:不输出匹配下标,共出现 0 次,仍输出“统计结束”。

这些情况都已通过运行截图核对,程序正常退出。上面的示例使用目标 7 展示成功匹配;最终保存的练习把两个目标都设为 8,用于验证没有匹配的路线。

顺便巩固 size_t 和输出格式

今天又复习了 size_t:它是无符号整数类型的别名,常用来保存大小、数量和下标,也是 sizeof 结果的类型,输出使用 %zu。int 同样规定变量类型,但它是有符号整数类型,不能把两者当成完全一样。

热身时仍漏写过两位小数格式中的末尾 0,也再次区分了整数除法和浮点除法。今天完成的是在指导下逐步预测、手写、运行和订正的练习,还需要通过后续题目巩固。

下一课学习用临时变量交换两个数据,再完成数组原地反转,区分“倒着输出”和“真正改变数组”。