当前位置: 首页 > news >正文

第二章 循环结构程序设计

2.1 for循环

for循环的格式为:for(初始化;条件;调整) 循环体;

#include<stdio.h> int main(){ int i; for(i = 1;i<8;i++) printf("%d",i); printf("%d",i); //说是有这一行会报错 return 0; }

建议尽量缩短变量的定义范围。例如,在for循环的初始化部分定义循环变量。

#include<stdio.h> int main(){ int i; for(i=1;i<6;i++) printf("%d\n",i); printf("%d\n",i); for(i=1;i<6;i++) return 0; }

Visual C++6.0等早期编译器允许在循环体之后访问i,但这样,如果再写一个“for(int i = 0;i<n;i++)"则会出现i定义的错误。

但是

#include<stdio.h> int main(){ int i; for(i=1;i<6;i++) printf("%d\n",i); printf("%d\n",i); for(int i=0;i<6;i++) return 0; }

没有出现什么报错嘞?

#include<stdio.h> int main(){ for(int i=1;i<6;i++) printf("%d\n",i); printf("%d\n",i); for(int i=0;i<6;i++) return 0; }

是我错了这样就会像书本上说的报错了.(还是讲究作用范围)

不拘一格的使用伪代码来思考问题和描述算法是一种值得推荐的做法。

判断是否为平方数:

我的代码:

#include<stdio.h> #include<math.h> int main(){ int a,b,c,e; float d; scanf("%d%d",&a,&b); c = 1100*a+11*b; d = sqrt(c); e = d; if(e==d) printf("%d是平方数",c); return 0; }

具体的题目是找出满足AABB形式的完全平方数,我完成以上的代码后AI告诉我,浮点数的运算会有误差因此这个开方的办法行不通,下面是另一种办法是用平方根去推完成平方数。

#include<stdio.h> int main(){ int a; int m = 0; for(m;m*m<10000;m++){ if(m*m > 1000){ a = m*m; int qian = a / 1000; // 千位 int bai = a / 100 % 10; // 百位 int shi = a / 10 % 10; // 十位 int ge = a % 10; // 个位 if(qian == bai && shi == ge) printf("%d是完全平方数",a); } } return 0; } //能正常运行出结果7744

以下是课本上的代码

#include<stdio.h> int mian(){ for(int x = 1; ;x++) { int n = x * x; if(n<1000) continue; if(n>9999) break; int hi = b/100; int lo = n%100; if(hi/10 == hi%10 && lo/10 == lo%10) printf("%d\n",n); } return 0; }

在C语言中,continuebreak是控制循环语句执行流程的关键字,主要用于forwhiledo-while循环中。

break用于立即终止当前所在的循环或switch语句,程序会继续执行循环或switch之后的代码。

  • 在循环中使用break会直接跳出整个循环,不再执行循环内剩余的语句。
  • switch中使用break会跳出当前的case分支,防止“穿透”到下一个case

continue 的用法

continue用于跳过当前循环的剩余部分,直接进入下一次循环的条件判断或迭代。

  • for循环中,continue会跳到迭代部分(如i++)后再判断条件。
  • whiledo-while循环中,continue会直接跳到条件判断部分。

两者区别:

continue 的用法

continue用于跳过当前循环的剩余部分,直接进入下一次循环的条件判断或迭代。

  • for循环中,continue会跳到迭代部分(如i++)后再判断条件。
  • whiledo-while循环中,continue会直接跳到条件判断部分。

2.2while循环和do-while循环

猜想,输入一个大于1的自然数,若n为奇数则把n变为3n+1否则变为n的一半,经过若干次这样的变换结果一定等于1,但是问输入一个数求变换次数。

#include<stdio.h> int n; int s = 0; scanf("%d",&n); while(n!=1){ s++; if(n%2==0) n = n/2; else n=3*n+1; } printf("%d",s); return 0; } //通过实例输入3 输出7.正确。

欧,不不不对,疏忽了,这是算法书上的:

#include<stdio.h> int main() { int n,count = 0; scanf("%d",&n); while(n>1) //这点我疏忽了, 题目有说须有体现 { if(n%2==1) n = n*3+1; //开始我写成了3n+1,注意乘法之间须有乘法符号 else n/=2; count++; } printf("%d/n",count); return 0; }

书上说,当输入为987654321时,结果为1(但是我的电脑上就没显示结果,像是算不出来一样),这明显是错误的。错就错在乘法那里可能数据溢出了,好我们在来回顾一下第一章里,int整数的大小很可能是-2147483648~2147483647,很可能就很讲究了因为C99中只规定了int至少是16位没有规定具体值,但是目前的比赛平台上int都是32位整数。

while循环的格式为“while(条件)循环体;”。

例题2-3 计算4分之派=1-1/3+1/5-1/7+······,知道最后一项小于10的负六次方。

这是课本上的代码,我花了较长时间没能想出来是因为我不知道派怎么打出来,当我看到解答时就疑惑了,直接没有管这个四分之派。那么就是以小于10的负六次方为终止条件。

#include<stdio.h> int main(){ double sum = 0; for(int i = 0; ;i++) { double term = 1.0/ (i*2+1); if(i%2 == 0) sum += term; else sum -=term; if (term < 1e-6) break; } printf("%.6f\n",sum); return 0; }

我有do-while 写的解题代码:

double n, sum = 1.0; int i=1;//不能写在do里面 do { n = 1.0/(i*2+1);//注意要用1.0来除以 if(i%2==0) sum += n;//判断好该加还是改减 else sum -= n; i++;//do-while 本身就是个循环,不要在里面再写一个for循环(我开始就犯了这样的错误) } while(n>(1e-6));//注意加分号 printf("%.6f\n",sum); return 0;//0.785399

do-while 循环的格式为“do{循环体}while(条件);其中循环体至少执行一次,每次执行完循环后判断 条件,满足时再继续循环。

阶乘之和的题目

阶乘之和是一个经典的编程练习题,通常要求计算 1! + 2! + 3! + ... + n! 的末六位。下面是我的代码:

#include<stdio.h> int main(){ const int mod = 1000000; int n,m=1,s=0; scanf("%d",&n); for(int i=1;i<=n;i++) { m=1; for(int j = 1;j<=i;j++) { m = (m * j) % mod; } s=(s+m)%mod; } printf("%d",s); return 0; }

提示:要计算只包含加法、减法和乘法的整数表达式除以正整数 n 的余数,可以在每步计算之后对 n 取余,结果不变。

这句话的意思是:在计算一个只包含加、减、乘运算的整数表达式时,如果我们最终需要的是这个表达式的结果除以一个正整数 n 的余数(即结果对 n 取模),那么我们可以不必等到计算出整个表达式的最终结果后再取余,而是在每一步计算(每次加法、减法或乘法)之后,立即将中间结果对 n 取余,用这个余数继续参与后续计算,最终得到的余数与先算出完整结果再取余的结果是相同的。

为什么这样做?

  • 防止溢出:在编程中,直接计算阶乘等大数可能会超出整数类型的表示范围(溢出)。每步取余可以保证中间结果始终在 0 到 n-1 之间,避免溢出。
  • 提高效率:对于非常大的数,每步取余可以保持数字较小,计算更快。

这样太慢了,加上一个计时器,看看究竟有多慢。

#include<stdio.h> #include<time.h> int main(){ const int mod = 1000000; int n,m=1,s=0; scanf("%d",&n); for(int i=1;i<=n;i++) { m=1; for(int j = 1;j<=i;j++) { m = (m * j) % mod; } s=(s+m)%mod; } printf("%d",s); printf("Time used = %.2f\n",(double)clock() / CLOCKS_PER_SEC); return 0; }

键盘输入的时间也会被计算在内,为了避免输入数据的时间影响测试结果,可以使用一种称为“管道”的小技巧:在Windows命令行下执行echo 20| abc,操作系统会自动把20输入,其中abc是程序名。

2.4 算法竞赛中的输入输出框架

例题2-5 数据统计

输入一些数,求出他们的最大值、最小值和平均值(保留三位小数)。输入保证这些数都是不超过1000的整数。

这里得注意一下,我们的要求是直接输入一系列整数,开始不知道会输入多少个整数。那么这该怎么办呢?这个我想了一下,我不会,只有跟着教材来进行学习。(以下代码有BUG)

#include<stdio.h> //有BUG int main(){ int x,n = 0, min,max,s = 0; while (scanf("%d",&x) == 1) { s+=x; if(x<min) min = x; if(x>max) max = x; n++; } printf("%d %d %.3f\n",min,max,(double)s/n); return 0; }

我输入了一大串按了enter没有反应,回顾一下(scanf的输入格式是,空格,TAB和回车都是无关紧要的,那么我们应该怎么告诉他输入结束了呢?)

提示:在windows下,输入完毕后先按Rnter键,再按Ctrl+Z,最后再按Enter键即可结束。在Linux下,输入完毕后按Ctrl+D即可结束。

结果可得,但是你应该发现最大值是一个与输入无关的值,为什么?,因为变量max一开始就等于那个数,自然不能更新为更小的。

提示:变量在未赋值之前的值是不确定的。特别的,他不一定是0。

解决方法:把max的初始值定义成一个比较小的数,把min的初始值定义为一个比较大的数就行,或者先读取第一个数x,把max=min=x。

还有就是说,每次都要输入许多数,这样会很不方便,那么好,一个好的方法就是用文件————

把输入的数据保存在文件中,就不必每次输入了;也避免了输出太多一卷屏前面看不到的尴尬。使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入以下两条语句:

freopen("input.txt","r",stdin);

freopen("output.txt","w",stdout):

上述语句将使得scanf从文件input.txt读入 ,printf写入文件output.txt.事实上,不只是scanf和printf,所有读键盘、写屏幕输出的函数都将改用文件。尽管这样做很方便,但是不是所有的算法竞赛都允许用程序读写文件。

http://www.cnnetsun.cn/news/4001550.html

相关文章:

  • 揭秘绵阳网站建设费用背后的真实逻辑,为什么你的报价总是差这么多
  • 开源AI视频工具ZJT智剧通:从文本到分镜与口型同步实战指南
  • The Empowerment of Science of Science by Large Language Models: New Tools and Methods
  • TranslucentTB:让你的Windows任务栏焕然一新的透明美化神器
  • 硬盘分区消失、照片被误删?TestDisk 与 PhotoRec 数据恢复完整指南
  • 零基础快速制作专业泳道图的实用指南
  • 心血管损伤多通路同步检测取得突破!云克隆液相悬浮芯片推出血管病变 10 标志物 CBA 多因子检测方案
  • Python多进程与队列实战:突破GIL限制,实现高效并行计算
  • C++日志库选型指南:从Qt项目实践到18种方案对比
  • VisualCppRedist AIO:3分钟搞定VC++运行库一键安装,从此告别DLL报错与游戏闪退
  • OpenCore Legacy Patcher技术揭秘:3步破解苹果硬件限制,让老Mac重获新生
  • 揭秘杭州网站建设公司有哪些优质选择:避开陷阱,打造真正高转化的企业官网
  • 2026年数学建模国赛B题算法(28):蚁群算法在离散寻优中的信息素更新策略研究:基于动态自适应调控的改进框架
  • Vue3双向代码转换:攻克事件、Props与指令的动态解析难题
  • QSFP/QSFP-DD/OSFP 通用管理接口规范(CMIS)解读:02 低页内存(控制与状态的基本信息)
  • TVA-World:具身智能“类脑想象力”基座(4)
  • 从源码到刷机:深度定制LineageOS 17的完整实践指南
  • 英辰朗迪GEO知识库第92期:AI搜索平台的差异化引用偏好与适配策略
  • 微信QQ防撤回补丁完整教程:RevokeMsgPatcher使用指南与避坑手册
  • 深度解析福建省住房和城乡建设厅网站作为官方信息发布与便民服务核心平台的重要价值与实用功能指南
  • 揭秘最牛的网站建设:从零基础到行业标杆的实战进化论,打造流量与转化的双重引擎
  • 【多模态】19-基于Nomic Embed和Anthropic的多模态RAG系统
  • Velo 3.0 核心技术全解:全链路AI视频生成、私有知识库与MCP协同架构深度剖析
  • 告别AI编码助手“瞎忙活”:构建高效Harness规则体系
  • 免费Illustrator脚本合集上手指南:3分钟装好,批量任务一键完成
  • Win11Debloat:一个 PowerShell 脚本如何替你把 Windows 系统的“出厂包袱“一件件拿掉
  • 网站建设要学什么:零基础入门指南,从HTML到全栈思维的进阶之路
  • Windows系统文件duser.dll丢失找不到问题解决
  • 从LangChain到AI Agent实战:6个核心判断与避坑指南
  • Snipe-IT容器化部署避坑指南:一次真实故障诊断背后的4个关键抉择