实验2:C语言分支与循环基础应用编程

实验2:C语言分支与循环基础应用编程

四、实验结论

编译环境:Visual Studio 2022 的 Microsoft C 编译器。运行截图使用本机运行结果查看器启动各题的可执行程序,显示实际输入和标准输出。

1. 实验任务1

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 100
#define CNT 5
int main(void) {
    int i, number;
    srand((unsigned int)time(0));
    for (i = 0; i < CNT; ++i) {
        number = rand() % N + 1;
        printf("20490042%04d\n", number);
    }
    return 0;
}

task1运行记录

程序从204900420001~204900420100中随机抽取5个编号;抽取独立进行,可能重复,并不保证5人互不相同。

number = rand() % N + 1; 把伪随机数映射到1~100。取模可能有微小分布偏差,此处按题目写法实现。

%04d 将整数按至少4位输出,不足4位在左侧补0,如1输出0001,再与前缀20490042拼接成12位编号。

srand((unsigned int)time(0)); 以当前时间设置随机种子。去掉后,同一实现的程序每次从默认种子开始,重复启动会得到相同序列。保留后,同一秒内启动也可能得到相同序列,不能认为每次结果一定不同。对照测试两次输出一致。

task1_no_seed对照记录

2. 实验任务2

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void) {
    int choice, quantity;
    float total_price = 0, amount_paid, change;
    while (1) {
        printf("\n自动饮料售卖机菜单:\n");
        printf("1. 可乐 - 3元/瓶\n2. 雪碧 - 3元/瓶\n");
        printf("3. 橙汁 - 5元/瓶\n4. 矿泉水 - 2元/瓶\n0. 退出购买流程\n");
        printf("请输入饮料编号: ");
        if (scanf("%d", &choice) != 1) break;
        if (choice == 0) break;
        if (choice < 1 || choice > 4) {
            printf("无效的饮料编号,请重新输入。\n");
            continue;
        }
        printf("请输入购买的数量: ");
        if (scanf("%d", &quantity) != 1) break;
        if (quantity < 0) {
            printf("购买数量不能为负数,请重新输入。\n");
            continue;
        }
        if (choice == 1 || choice == 2) total_price += 3 * quantity;
        else if (choice == 3) total_price += 5 * quantity;
        else total_price += 2 * quantity;
        printf("请投入金额: ");
        if (scanf("%f", &amount_paid) != 1) break;
        change = amount_paid - total_price;
        printf("本次购买总价: %.2f元\n找零: %.2f元\n", total_price, change);
        total_price = 0;
    }
    printf("感谢您的购买,欢迎下次光临!\n");
    return 0;
}

task2运行记录

total_price = 0; 用于一次交易结束后清零。删除后,前次消费会累加到下次:先买2瓶可乐共6元,再买1瓶橙汁应为5元,却计算成11元;若第二次付10元,会出现-1元找零。对照程序实际验证了这一现象。

continue 跳过本轮循环中尚未执行的语句,重新判断循环条件并进入下一轮。两处分别在编号无效和数量为负时返回菜单,均不执行后面的结算。break 则结束整个购买循环。

本题为验证性实验,保留原题允许数量为0、付款不足时直接输出负找零的行为。仅增加读取失败时退出的检查,防止输入结束后无限循环。

task2_no_reset对照记录

3. 实验任务3

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void) {
    char light;
    int i;
    for (i = 0; i < 4; ++i) {
        printf("请输入交通灯颜色(r/g/y): ");
        if (scanf(" %c", &light) != 1) return 0;
        switch (light) {
            case 'r': printf("stop!\n"); break;
            case 'g': printf("go go go\n"); break;
            case 'y': printf("wait a minute\n"); break;
            default: printf("something must be wrong...\n");
        }
    }
    return 0;
}

task3运行记录

使用for循环读取4次输入,switch分别处理r、g、y和其它字符。scanf(" %c", &light) 前的空格跳过换行符,避免把上次回车当成新的灯色。测试r、g、y、x覆盖全部四种分支。

4. 实验任务4

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void) {
    double cost, total = 0, highest = 0, lowest = 0;
    int count = 0;
    printf("请输入各笔开销,输入-1结束:\n");
    while (scanf("%lf", &cost) == 1 && cost != -1) {
        if (cost <= 0 || cost > 20000) {
            printf("每笔开销应大于0且不超过20000元。\n");
            continue;
        }
        if (count == 0) highest = lowest = cost;
        if (cost > highest) highest = cost;
        if (cost < lowest) lowest = cost;
        total += cost;
        ++count;
    }
    if (count == 0) printf("没有有效开销记录。\n");
    else printf("最高一笔开销: %.1f元\n最低一笔开销: %.1f元\n一天总开销: %.1f元\n", highest, lowest, total);
    return 0;
}

task4运行记录

用-1作为结束标志,不计入统计。第一笔有效开销同时初始化最高值和最低值,后续逐笔更新并累加总额;用%.1f保留一位小数。测试28.5、7、63.5、19得到最高63.5、最低7.0、总计118.0元。额外检查单笔20000元、无记录和范围外输入。

5. 实验任务5

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void) {
    int a, b, c, t, i;
    for (i = 0; i < 5; ++i) {
        printf("请输入三角形的三条整数边长: ");
        if (scanf("%d%d%d", &a, &b, &c) != 3) return 0;
        /* 排序后c为最长边;用long long避免int范围边长运算溢出。 */
        if (a > b) { t = a; a = b; b = t; }
        if (b > c) { t = b; b = c; c = t; }
        if (a > b) { t = a; a = b; b = t; }
        if (a <= 0 || (long long)a + b <= c)
            printf("不能构成三角形\n");
        else if (a == c) printf("等边三角形\n");
        else if ((long long)a*a + (long long)b*b == (long long)c*c)
            printf("直角三角形\n");
        else if (a == b || b == c) printf("等腰三角形\n");
        else printf("普通三角形\n");
    }
    return 0;
}

task5运行记录

先排序,再用最短两边之和大于最长边判断三角形成立,同时排除非正边长。有效三角形依次判断等边、直角、等腰,否则为普通三角形。等边也满足广义等腰条件,因此先判断等边,输出更具体的类别。直角判断比较两短边平方和与最长边平方。中间运算提升为long long,适用于本程序int范围内的正整数边长。

按要求一轮测试5组,分别覆盖退化三角形、普通、直角、等边和等腰;另测非正边长、边长顺序和较大整数。

6. 实验任务6

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
    int lucky_day, guess, i;
    srand((unsigned int)time(0));
    lucky_day = rand() % 30 + 1;
    printf("猜一猜11月的lucky day(1~30),你有3次机会。\n");
    for (i = 0; i < 3; ++i) {
        printf("第%d次猜测: ", i + 1);
        if (scanf("%d", &guess) != 1) return 0;
        if (guess == lucky_day) {
            printf("猜中了!11月的lucky day是%d日。\n", lucky_day);
            break;
        }
        if (guess < lucky_day) printf("你猜的日期早了。\n");
        else printf("你猜的日期晚了。\n");
    }
    if (i == 3) printf("3次机会已用完,11月的lucky day是%d日。\n", lucky_day);
    return 0;
}

task6运行记录

rand() % 30 + 1 生成1~30的幸运日期。for最多执行3次;猜中后break;猜小提示日期早了,猜大提示日期晚了。若循环正常用完3次,公布幸运日。

正式程序使用时间随机种子。为可靠覆盖每个分支,另建测试副本,仅把随机函数返回值固定为14,使幸运日为15日,分别验证第一次、第二次、第三次猜中及三次未中。测试图片明确标出固定日期,这些结果不是正式随机程序的随机抽样结果。正式程序也已单独运行。

task6_fixed对照记录

五、实验总结

分支条件应覆盖正常情况及边界情况。循环次数已知时可用for,次数不确定且由结束标志控制时可用while。continue结束本轮,break退出循环;统计最小值时用第一笔有效记录初始化。随机程序需要区分正式运行与固定条件测试,不能只凭一次随机结果判断所有分支都正确。

posted @ 2026-11-04 07:54  Eurydice  阅读(2)  评论(0)    收藏  举报