实验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;
}

程序从204900420001~204900420100中随机抽取5个编号;抽取独立进行,可能重复,并不保证5人互不相同。
number = rand() % N + 1; 把伪随机数映射到1~100。取模可能有微小分布偏差,此处按题目写法实现。
%04d 将整数按至少4位输出,不足4位在左侧补0,如1输出0001,再与前缀20490042拼接成12位编号。
srand((unsigned int)time(0)); 以当前时间设置随机种子。去掉后,同一实现的程序每次从默认种子开始,重复启动会得到相同序列。保留后,同一秒内启动也可能得到相同序列,不能认为每次结果一定不同。对照测试两次输出一致。

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;
}

total_price = 0; 用于一次交易结束后清零。删除后,前次消费会累加到下次:先买2瓶可乐共6元,再买1瓶橙汁应为5元,却计算成11元;若第二次付10元,会出现-1元找零。对照程序实际验证了这一现象。
continue 跳过本轮循环中尚未执行的语句,重新判断循环条件并进入下一轮。两处分别在编号无效和数量为负时返回菜单,均不执行后面的结算。break 则结束整个购买循环。
本题为验证性实验,保留原题允许数量为0、付款不足时直接输出负找零的行为。仅增加读取失败时退出的检查,防止输入结束后无限循环。

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;
}

使用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;
}

用-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;
}

先排序,再用最短两边之和大于最长边判断三角形成立,同时排除非正边长。有效三角形依次判断等边、直角、等腰,否则为普通三角形。等边也满足广义等腰条件,因此先判断等边,输出更具体的类别。直角判断比较两短边平方和与最长边平方。中间运算提升为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;
}

rand() % 30 + 1 生成1~30的幸运日期。for最多执行3次;猜中后break;猜小提示日期早了,猜大提示日期晚了。若循环正常用完3次,公布幸运日。
正式程序使用时间随机种子。为可靠覆盖每个分支,另建测试副本,仅把随机函数返回值固定为14,使幸运日为15日,分别验证第一次、第二次、第三次猜中及三次未中。测试图片明确标出固定日期,这些结果不是正式随机程序的随机抽样结果。正式程序也已单独运行。

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

浙公网安备 33010602011771号