【无标题】

C语言: 我做过的练习题
第一题:喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以喝多少汽水(编程实现)

int main()
{
	int bottle_price = 1;
	int price = 20;
	int bottle_num = price / bottle_price;
	int num = price / bottle_price;
	while (bottle_num > 1)
	{
		bottle_num -= 2;
		num += 1;
		bottle_num += 1;
	}
	printf("%d", num);
}

你编写的代码在逻辑上是正确的,能够正确计算出20元可以喝到的汽水总数。以下是具体分析:
代码逻辑验证
问题的核心逻辑是:初始用20元买20瓶汽水(喝完得20个空瓶),之后每2个空瓶换1瓶新汽水(喝完又产生1个空瓶),直到剩余空瓶不足2个为止。
你的代码通过循环模拟了这一过程:
初始状态:bottle_num = 20(20元买20瓶),num = 20(已喝20瓶)。
循环条件:while (bottle_num > 1)(只要空瓶数大于1,就能继续换汽水)。
循环体:
bottle_num -= 2:用掉2个空瓶换1瓶。
num += 1:喝到1瓶新汽水。
bottle_num += 1:喝完新汽水后,新增1个空瓶(原2个空瓶被消耗,剩余1个新空瓶)。
关键测试用例验证
当输入为20元时:最终输出39瓶(正确结果)。
当输入为2元时:输出3瓶(2元买2瓶→换1瓶→共3瓶,正确)。
当输入为3元时:输出5瓶(3元买3瓶→换1瓶→再换1瓶→共5瓶,正确)。
结论
代码逻辑正确,能够准确计算出20元可以喝到的汽水总数。没有问题。
—————————————————————————————————

题目二:打印图案

打印一个菱形,

int main()
{
	int row = 7;
	int col = 13;
	int i, j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (j >= 6 - i && j <= 6 + i)
				printf("*");
			else {
				printf(" ");
			}
		}
		printf("\n");
	}
	for (i = row - 1; i > 0; i--)
	{
		for (j = 0; j < col; j++)
		{
			if (j >= 6 - i + 1 && j <= 6 + i -1)
				printf("*");
			else {
				printf(" ");
			}
		}
		printf("\n");
	}
}

关键步骤分析

  1. 上半部分(正金字塔)
    外层循环i从0到6(共7行),控制金字塔的层数。
    内层循环j从0到12(共13列),通过条件j >= 6 - i && j <= 6 + i确定的范围:
    当i=0时,j范围为6(仅中间1个
    )。
    当i=1时,j范围为5-7(3个*)。
    以此类推,i每增加1,的数量增加2(奇数递增),最终第7行(i=6)打印13个(整行)。
  2. 下半部分(倒金字塔)
    外层循环i从6到1(共6行),控制倒金字塔的层数。
    内层循环j同样从0到12,通过条件j >= 6 - i + 1 && j <= 6 + i - 1调整的范围:
    当i=6时,j范围为1-11(11个
    )。
    当i=5时,j范围为2-10(9个*)。
    以此类推,i每减少1,的数量减少2(奇数递减),最终第1行(i=1)仅中间1个
    deep seek改进后的代码:
for (int k = 0; k < totalRows; k++)
{
    int d = abs(k - midRow);   // 当前行与中间行的距离
    int start = d;              // 星号起始列索引
    int end = totalCols - 1 - d; // 星号结束列索引(因为列索引从0到12)

    for (int j = 0; j < totalCols; j++)
    {
        if (j >= start && j <= end)
            printf("*");
        else
            printf(" ");
    }
    printf("\n");
}
return 0;

核心思路
沙漏图案的本质是上下对称:上半部分从中间向上下扩展,下半部分从中间向上下收缩。改进代码通过计算当前行与中间行的距离(d),直接推导出该行需要打印的星号(*)范围,无需分别处理上半部分和下半部分。


题目三: 求出0~100000之间的所有“水仙花数”并输出。

“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,如:153=1 ^ 3+5 ^ 3+3 ^ 3,则153是一个“水仙花数”。

#include<math.h>
int main()
{
	for (int i = 0; i < 100000; i++)
	{
		int sum = 0;
		int n = 0;
		int num = i;
		for (int temp = i; temp > 0; temp = temp/ 10)
		{
			n++;
		}
		int temp = i;
		while (temp)
		{
			num = temp % 10;
			sum += pow(num, n);
			temp = temp / 10;
		}
		if (i == sum && i != 0) {  // 跳过0
			printf("%d ", i);
		}
	}

}

这段代码用于找出0到99999之间的所有“水仙花数”(阿姆斯特朗数),其核心逻辑是通过遍历每个数,计算其各位数字的n次方之和(n为该数的位数),并判断是否等于原数。以下是对代码的详细分析:
代码逻辑解读

  1. 遍历范围
    外层循环for (int i = 0; i < 100000; i++)遍历0到99999的所有整数,确保覆盖所有可能的水仙花数(已知水仙花数在十进制中最多为5位数)。
  2. 计算位数n
    内层第一个循环for (int temp = i; temp > 0; temp = temp/10)通过不断将数值除以10,统计其位数n。例如:
    当i=153时,temp依次为153→15→1→0,循环执行3次,故n=3(153是3位数)。
  3. 计算各位数字的n次方和sum
    第二个循环while (temp)通过取模运算(temp % 10)逐位提取数字,并计算其n次方(使用pow(num, n)),累加到sum中。例如:
    当i=153时,依次提取数字3、5、1,计算3³+5³+1³=27+125+1=153,故sum=153。
  4. 判断水仙花数
    最后通过if (i == sum && i != 0)判断当前数是否为水仙花数(跳过0,因通常讨论正整数)。若满足条件则输出。

潜在问题与改进建议

  1. pow函数的精度问题
    pow(num, n)来自math.h,返回double类型。由于浮点数精度限制,当计算较大数的n次方时(如9^5=59049),可能出现微小误差(如59049.0000001或59048.9999999),导致i == sum判断失败。
    改进方案:用整数运算替代pow,避免精度丢失。例如,计算num的n次方时,通过循环累乘:
    int power(int num, int n) {
    int result = 1;
    for (int k = 0; k < n; k++) {
    result *= num;
    }
    return result;
    }
    // 使用时:sum += power(num, n);
  2. 效率优化
    当前代码对每个数都重新计算位数n,存在重复计算。可预先按位数分组(如1位数、2位数…5位数),对每组数统一计算位数,减少冗余操作。
    改进示例:
    for (int n = 1; n <= 5; n++) { // 遍历1到5位数
    int start = pow(10, n-1); // 起始值(如n=3时,start=100)
    int end = pow(10, n) - 1; // 结束值(如n=3时,end=999)
    for (int i = start; i <= end; i++) { // 仅遍历n位数
    // 计算sum…
    }
    }
  3. 特殊情况处理
    代码中i != 0的条件会跳过0。根据数学定义,0的各位数字的1次方和为0(0^1=0),因此0可视为水仙花数。若需包含0,可移除该条件。
    测试用例验证
    153:3位数,1³+5³+3³=153,应输出。
    370:3位数,3³+7³+0³=370,应输出。
    9474:4位数,9⁴+4⁴+7⁴+4⁴=9474,应输出。
    54748:5位数,5⁵+4⁵+7⁵+4⁵+8⁵=54748,应输出。
    结论
    代码逻辑正确,能够准确找出0到99999之间的所有水仙花数。但需注意pow函数的精度问题,建议用整数运算替代以提高可靠性。优化后可进一步提升效率并覆盖更多边界情况。
    —————————————————————————————————————————————
    题目四:求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字
    例如:2+22+222+2222+22222
    代码如下:
int main()
{
	int n = 5;
	int sum = 0;
	int a = 0;
	scanf("%d", &a);
	while (n)
	{
		sum = sum + a;
		a = a * 10 + (a % 10);
		n--;
	}
	printf("%d\n", sum);
	printf("%d", a);
}

这段代码用于计算数列 Sn=a+aa+aaa+aaaa+aaaaaS_n = a + aa + aaa + aaaa + aaaaaSn=a+aa+aaa+aaaa+aaaaa 的前5项之和(其中 aaa 是一个数字,例如 a=2a=2a=2 时,数列为 2+22+222+2222+222222 + 22 + 222 + 2222 + 222222+22+222+2222+22222)。以下是对代码的详细解析:
代码逻辑分析

  1. 变量初始化
    n = 5:表示需要计算前5项的和。sum = 0:累加和的初始值。a:用户输入的数字(0-9),用于生成数列的每一项。
  2. 核心循环逻辑
    通过 while (n) 循环迭代5次(n 从5递减到0),每次循环完成两个关键操作:
    累加当前项:将当前的 a 加到 sum 中。生成下一项:通过 a = a * 10 + (a % 10) 生成数列的下一项。
  3. 生成下一项的原理
    假设当前项为 aka_kak(例如 a=2a=2a=2 时,第一项是 222),生成下一项 ak+1a_{k+1}ak+1 的逻辑如下:
    a%10a \% 10a%10:提取当前项的最后一位数字(例如 a=22a=22a=22 时,22%10=222 \% 10 = 222%10=2)。a∗10a * 10a10:将当前项左移一位(相当于乘以10,例如 22∗10=22022 * 10 = 2202210=220)。两者相加:a∗10+(a%10)a * 10 + (a \% 10)a10+(a%10) 得到下一项(例如 220+2=222220 + 2 = 222220+2=222)。这一操作巧妙地利用了数字的位运算,无需字符串拼接即可生成连续的 aa…a 形式数。

示例验证(以 a=2a=2a=2 为例)
最终输出 sum=24690,与预期结果 2+22+222+2222+22222=246902+22+222+2222+22222=246902+22+222+2222+22222=24690 完全一致。

潜在问题与注意事项
输入限制:代码假设用户输入的 a 是单个数字(012+122+1222+...12 + 122 + 1222 + ...12+122+1222+...),但题目明确 a 是数字,因此无需额外处理。
数据类型溢出:当 a=9 时,最大项为 999999999999999,前5项和为 9+99+999+9999+99999=1111059+99+999+9999+99999=1111059+99+999+9999+99999=111105,这在 int 类型范围内(32位 int 最大约为 231−1=21474836472^{31}-1=21474836472311=2147483647)。若 n 更大(如 n=10),可能导致溢出,但题目中 n 固定为5,因此无风险。
输出多余值:代码最后额外输出了 a 的值(循环结束后 a 为第6项),这可能是调试残留,实际使用中可根据需求删除。

结论
代码逻辑正确,通过巧妙的位运算生成数列的每一项,并准确计算前5项的和。输入单个数字时(0-9),能正确输出预期结果。若需严格符合题目要求,可添加输入校验(确保 a 是0-9的数字),并删除最后多余的 printf(“%d”, a)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值