【新书推荐】7.4 多重循环

本节必须掌握的知识点:

        for循环嵌套语句

        示例二十五

        代码分析

        汇编解析

7.4.1 for循环嵌套语句

在我们总结中,语句块这个解释不知道读者是否感到不解,既然语句块里可以做任何事情,那么它的里面就可以再写一个循环语句,我们称为循环嵌套语句。顾名思义,循环语句中再嵌套一个或多个循环语句。

那么我们看下它的语法形式。

for循环嵌套语句

为了使读者更容易理解,我们把嵌套在里面的for循环条件改成,for(表达式4;表达式5;表达式6;语句块2;其中语句块1替换成了for循环语句。

for(表达式1;表达式2;表达式3)

{

//语句块1;

for(表达式4;表达式5;表达式6)

{

语句块2;

}

}

●语法解析:

第一步:执行表达式1,表达式1表示初始化外循环变量;

第二步:执行表达式2,表达式2:终止条件,如果条件表达式为真,则执行循环体内的语句块,否则退出for语句;

第三步:执行循环体内的语句1,语句块1替换成内层for循环语句,执行表达式4,表达式4表示初始化内循环变量;

第四步执行表达式5,表达式5:终止条件,如果条件表达式为真,则执行循环体内的语句块,否则退出内层嵌套for语句;

第五步:执行代码块2;

第六步:执行表达式6后置表达式;

第七步:继续执行下一轮循环,直到表达式5的条件为假,跳出内层for循环语句。

第八步:执行表达式3;

第九步:执行表达式2,如果条件表达式2为真,则执行循环体内的语句块1,否则退出for语句;

……

第N步:继续执行下一轮循环,直到表达式2的条件为假,跳出for循环语句。

执行顺序:表达式1->表达式2->语句块1(表达式4->表达式5->语句块2->表达式6->表达式5->语句块2->表达式6->表达式5->……直到不满足条件跳出内层循环)->表达式3->表达式2->语句块1……一直循环下去,直到到表达式2为假时,停止循环。我们看示例代码二十五来理解循环嵌套for语句的执行流程。

示例代码二十五

7.4.2 示例二十五

●第一步:分析需求,设计程序结构框架。

分析需求:构建一个双重for循环嵌套语句,当i< 3时,重复执行内层for循环语句,当j <= 3时,重复执行内循环的重复语句块。

设计程序结构框架:双循环结构for语句。

       ●第二步:数据定义,定义恰当的数据结构;

       int i;//定义一个int类型的整型局部变量i,并将其初始化为0,作为外循环变量。

       int j;//定义一个int类型的整型局部变量j,并将其初始化为0,作为内循环变量。

       ●第三步:分析算法。

当i< 3时,重复执行内层for循环语句,当j <= 3时,重复执行内循环的重复语句块。

       ●第四步:编写伪代码,即用我们自己的语言来编写程序。

       int main(void) {

    定义一个int类型整型循环变量i和j;

    外循环:

表达式1:将循环变量i初始化为0;

表达式2:当i < 3时执行大括号内的内循环for语句块

表达式3:执行完printf语句后,循环变量i加1

    for (i = 0; i < 3; i++){

    调用printf函数打印信息:"\ni = %d\n"          

       内循环:

表达式1:将循环变量j初始化为0;

表达式2:当j <= 3时执行大括号内的内循环for语句块

表达式3:执行完printf语句后,循环变量j加1

    for (i = 0; j < 3; j++){

    调用printf函数打印信息:"j = %d\t"                

}                   

}

调用printf函数打印信息"\n"

system("pause");

    return 0;                                                                                                    

}

       ●第五步:画流程图,使用Visio、Excel或者其他绘图工具绘制算法流程和逻辑关系图;            如图7-4所示。

图7-4 示例二十五for循环嵌套语句

●第六步:编写源程序,其实就是将我们的伪代码翻译成计算机语言;

/*

   for语句的嵌套

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int i, j;

    for (i = 0; i < 3; i++)

    {

        printf("\ni = %d\n", i);

        for (j = 0; j <= 3; j++)

        {

            printf("j = %d\t", j);

        }

    }

    printf("\n");

    system("pause");

    return 0;

}

●输出结果:

i = 0

j = 0   j = 1   j = 2   j = 3

i = 1

j = 0   j = 1   j = 2   j = 3

i = 2

j = 0   j = 1   j = 2   j = 3                                 

7.4.3 代码分析

分析执行流程:

第一次执行外层循环:

第一步:执行 int i = 0;

第二步:执行 i<3;0<3条件为真,继续往下执行 ;

第三步:执行printf(“\ni=%d\n”,i);输出 i = 0;

第一次执行内层循环:

第四步:执行内层for循环,j=0;

第五步:执行j<=3,0<3,条件为真,继续往下执行;

第六步:执行printf(“j=%d\t”,j);输出 j = 0;

第七步:执行j++,此时j=0+1,j=1;

第八步:执行j<=3,1<3,条件为真,继续往下执行;

第九步:执行printf(“j=%d\t”,j);输出 j = 1;

第十一步:执行j<=3,2<3,条件为真,继续往下执行;

第十二步:执行printf(“j=%d\t”,j);输出 j =2;

第十三步:执行j++,此时j=2+1,j=3;

第十四步:执行j<=3,3=3,条件为真,继续往下执行;

第十五步:执行printf(“j=%d\t”,j);输出 j =3;

第十六步:执行j++,此时j=3+1,j=4;

第十七步:执行j<=3,4>3,条件为假,跳出内层循环。

第二次执行外层循环:

第十八步:执行i++,i=0+1,i=1;

第二十步:执行i<3;1<3条件为真,继续往下执行,

第二十一步:执行printf(“\ni=%d\n”,i);输出 i =1;

第二次执行内循环:(重复第一次执行内循环做的事情)

第二十二步:执行内层for循环,j=0;

第二十三步:执行j<=3,0<3,条件为真,继续往下执行;

第二十四步:执行printf(“j=%d\t”,j);输出 j = 0;

第二十五步:执行j++,此时j=0+1,j=1;

第二十六步:执行j<=3,1<3,条件为真,继续往下执行;

第二十七步:执行printf(“j=%d\t”,j);输出 j = 1;

第二十八步:执行j++,此时j=1+1,j=2;

第二十九步:执行j<=3,2<3,条件为真,继续往下执行;

第三十步:执行printf(“j=%d\t”,j);输出 j =2;

第三十一步:执行j++,此时j=2+1,j=3;

第三十二步:执行j<=3,3=3,条件为真,继续往下执行;

第三十三步:执行printf(“j=%d\t”,j);输出 j =3;

第三十四步:执行j++,此时j=3+1,j=4;

第三十五步:执行j<=3,4>3,条件为假,跳出内层循环。

第三次执行外层循环:

第三十六步:执行i++,i=1+1,i=2;

第三十七步:执行i<3;2<3条件为真,继续往下执行,

第三十八步:执行printf(“\ni=%d\n”,i);输出 i =2;

第三次执行内循环:(重复第一次执行内循环做的事情)

第三十九步:执行内层for循环,j=0;

第四十步:执行j<=3,0<3,条件为真,继续往下执行;

第四十一步:执行printf(“j=%d\t”,j);输出 j = 0;

第四十二步:执行j++,此时j=0+1,j=1;

第四十三步:执行j<=3,1<3,条件为真,继续往下执行;

第四十四步:执行printf(“j=%d\t”,j);输出 j = 1;

第四十五步:执行j++,此时j=1+1,j=2;

第四十六步:执行j<=3,2<3,条件为真,继续往下执行;

第四十七步:执行printf(“j=%d\t”,j);输出 j =2;

第四十八步:执行j++,此时j=2+1,j=3;

第四十九步:执行j<=3,3=3,条件为真,继续往下执行;

第五十步:执行printf(“j=%d\t”,j);输出 j =3;

第五十一步:执行j++,此时j=3+1,j=4;

第五十二步:执行j<=3,4>3,条件为假,跳出内层循环。

第四次执行外层循环:

第五十三步:执行i++,i=2+1,i=3;

第五十四步:执行i<3;3=3条件为假,跳出外层循环,当然结束外层循环那么内层循环将不会执行。

7.4.4 汇编解析

汇编代码

;C标准库头文件和导入库

include vcIO.inc

.data

i sdword  ?

j sdword  ?

.const    

szMsg1 db 0dh,0ah,"i = %d",0dh,0ah,0

szMsg2 db "j = %d",09h,0

szMsg3 db 0dh,0ah,0

.code     

start:

       mov i,0

NEXT1:         

       .while i < 3

              invoke printf,offset szMsg1,i

              mov j,0         

NEXT2:

              .while j <= 3

                     invoke printf,offset szMsg2,j             

                     inc sdword ptr j;

                     jmp NEXT2         

              .endw           

              inc sdword ptr i;

              jmp NEXT1         

       .endw           

       ;

       invoke printf,offset szMsg3

       ;     

       invoke _getch

       ret                       

end start

●输出结果:

i = 0

j = 0   j = 1   j = 2   j = 3

i = 1

j = 0   j = 1   j = 2   j = 3

i = 2

j = 0   j = 1   j = 2   j = 3

上述汇编代码中,使用高级汇编伪指令.while替换C语言中的for语句实现双重循环。NEXT1地址标号作为外循环起始地址,NEXT2地址标号作为内循环起始地址。

【注意】内循环开始前,需要将内循环变量j重新初始化为0。

反汇编代码

    int i, j;

    for (i = 0; i < 3; i++);外循环

00E01838  mov         dword ptr [i],0  ;表达式1

    int i, j;

    for (i = 0; i < 3; i++)

00E0183F  jmp         main+3Ah (0E0184Ah

00E01841  mov         eax,dword ptr [i]  

00E01844  add         eax,1                ;表达式3

00E01847  mov         dword ptr [i],eax 

00E0184A  cmp         dword ptr [i],3  ;表达式2

00E0184E  jge         main+7Eh (0E0188Eh;i>=3时,退出外循环

    {

        printf("\ni = %d\n", i);循环语句块2

00E01850  mov         eax,dword ptr [i] 

00E01853  push        eax 

00E01854  push        offset string "\ni = %d\n" (0E07B30h) 

00E01859  call        _printf (0E0104Bh) 

00E0185E  add         esp,8 

        for (j = 0; j <= 3; j++);内循环

00E01861  mov         dword ptr [j],0  ;表达式4

00E01868  jmp         main+63h (0E01873h

00E0186A  mov         eax,dword ptr [j] 

00E0186D  add         eax,1                ;表达式6

00E01870  mov         dword ptr [j],eax 

00E01873  cmp         dword ptr [j],3  ;表达式5

00E01877  jg          main+7Ch (0E0188Ch)  ;j>3时,退出内循环

        {

            printf("j = %d\t", j);循环语句块2

00E01879  mov         eax,dword ptr [j] 

00E0187C  push        eax 

00E0187D  push        offset string "j = %d\t" (0E07B3Ch) 

00E01882  call        _printf (0E0104Bh) 

00E01887  add         esp,8 

        }

00E0188A  jmp         main+5Ah (0E0186Ah;内循环,跳转到表达式6

    }

00E0188C  jmp         main+31h (0E01841h;外循环,跳转到表达式3

    printf("\n");

00E0188E  push        offset string "\n" (0E07B44h) 

00E01893  call        _printf (0E0104Bh) 

00E01898  add         esp,4 

    system("pause");

00E0189B  mov         esi,esp 

    system("pause");

00E0189D  push        offset string "pause" (0E07B48h) 

00E018A2  call        dword ptr [__imp__system (0E0B168h)] 

00E018A8  add         esp,4 

上述反汇编代码验证了for循环嵌套语句的执行流程。请读者参考注释阅读代码,此处不再赘述。

实验五十三: 打印九九乘法表

在VS中新建项目7-4-2.c:

       /*

   for语句双重循环:打印九九乘法表

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int i, j;

    j = 0;

    for (i = 1; i <= 9; i++)

    {

        for (j = 1; j <= 9; j++)

        {

            printf("%3d ", i * j);

        }

        printf("\n");

    }

    system("pause");

    return 0;

}

       ●输出结果:

       1   2   3   4   5   6   7   8   9

  2   4   6   8  10  12  14  16  18

  3   6   9  12  15  18  21  24  27

  4   8  12  16  20  24  28  32  36

  5  10  15  20  25  30  35  40  45

  6  12  18  24  30  36  42  48  54

  7  14  21  28  35  42  49  56  63

  8  16  24  32  40  48  56  64  72

  9  18  27  36  45  54  63  72  81

请按任意键继续. . .

       上述代码9行*9列的方式在控制台窗口输出九九乘法表。程序使用for语句的双循环结构,循环变量i表示行,循环变量j表示列。循环变量的取值范围为1~9。

实验五十四: 打印直角三角形

在VS中新建项目7-4-3.c:

/*

   for语句双重循环:打印直角三角形

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int i, j, n;

    int len;

    printf("生成直角在左下方的等腰直角三角形。\n");

    printf("短边:");

    scanf_s("%d", &len);

    for (i = 1; i <= len; i++)//输出行

    {

        for (n = 1; n <= len - i; n++)//输出列' '

        {

            putchar(' ');

        }

        for (j = 1; j <= i; j++)//输出列'*'

        {

            putchar('*');

        }

        printf("\n");//换行

    }

    system("pause");

    return 0;

}

●输出结果:

生成直角在左下方的等腰直角三角形。

短边:8

       *

      **

     ***

    ****

   *****

  ******

 *******

********

       上述代码实现其实非常简单,我们可以把直角三角形看成是一个由空格和*号组成的长方形,只需要建立for语句双循环结构分别循环打印行和列就可以实现了。需要注意的是,在输出列时分别输出len-i个空格和i个*号。

提示

       通常在项目中,我们仅需要双循环结构就可以了。很少需要用到三重及以上的循环结构。即使确有多重循环的需要,也可以将其封装为函数调用的形式实现。我们将在第九章详细介绍函数的知识。

练习

  1. 画一个长方形:

高:3,宽:7

*******

*******

*******

2、生成直角在左下方的等腰直角三角形。

短边:5

*

**

***

****

*****

3、编写一段程序,像右面这样显示所输入整数为边长的正方形。

生成一个正方形

正方形有几层:3

***

***

***

4、显示出一个横向较长的长方形。

读取两个边的边长,以较小的数作为行数,以较大的数作为列数。

一边:7

另一边:3

*******

*******

*******

5、编写一段程序,输入一个整数,像右面这样显示出输入整数层的金字塔形状。

提示;第i行显示(i-1)*2+1个星

金字塔有几层:3

  *

 ***

*****

6、编写一段程序,像右面这样显示出输入整数层的向下的金字塔形状。第i行显示i%10的结果。

金字塔有几层:3

11111

 222

  3

7、使用for语句,输出于下面的图所示的样式。

                            2(1)

                             2(2)

                             2(3) 

  1. 编写一段程序,输出九九乘法表。

                             1

本文摘自编程达人系列教材《汇编的角度——C语言》。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/464585.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Swift 初见

Swift 初见 学习swift的记录 控制台输出 print("hello world")可以无分号&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 变量声明 let 常量声明 如果在常量声明后再次修改他会报错 var 变量声明 一个常量的值&#xf…

专业课135+总分400+西安交通大学815/909信号与系统考研电子信息与通信工程,真题,大纲,参考书。

经过将近一年的考研复习&#xff0c;终于梦圆西安交大&#xff0c;今年专业可815(和909差不多)信号与系统135&#xff0c;总分400&#xff0c;回想这一年的复习还是有很多经验和大家分享&#xff0c;希望可以对大家复习有所帮助&#xff0c;少走弯路。 专业课&#xff1a; 这…

BootStrap学习笔记JS插件(一)--模态弹出框

一、弹出框基础 <div class"modal show"><div class"modal-dialog"><div class"modal-content"><div class"modal-header"><button type"button" class"close" data-dismiss"mo…

Hadoop:认识MapReduce

MapReduce是一个用于处理大数据集的编程模型和算法框架。其优势在于能够处理大量的数据&#xff0c;通过并行化来加速计算过程。它适用于那些可以分解为多个独立子任务的计算密集型作业&#xff0c;如文本处理、数据分析和大规模数据集的聚合等。然而&#xff0c;MapReduce也有…

我主编的电子技术实验手册(03)——电阻的识别与测量

本专栏是笔者主编教材&#xff08;图0所示&#xff09;的电子版&#xff0c;依托简易的元器件和仪表安排了30多个实验&#xff0c;主要面向经费不太充足的中高职院校。每个实验都安排了必不可少的【预习知识】&#xff0c;精心设计的【实验步骤】&#xff0c;全面丰富的【思考习…

聚观早报 | 小米14 Ultra官宣;苹果汽车项目调整

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 2月6日消息 小米14 Ultra官宣 苹果汽车项目调整 ROG游戏手机8系列推出福利 一加Ace 3原神刻晴定制机官宣 苹果i…

猫头虎分享已解决Bug || RuntimeError: size mismatch, m1: [32 x 100], m2: [500 x 10]

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

SpringCloud-Nacos服务分级存储模型

Nacos 服务分级存储模型是 Nacos 存储服务注册信息和配置信息的核心模型之一。它通过将服务和配置信息按照不同级别进行存储&#xff0c;实现了信息的灵活管理和快速检索&#xff0c;为微服务架构下的服务发现和配置管理提供了高效、可靠的支持。本文将对 Nacos 服务分级存储模…

Python中HTTP隧道的基本原理与实现

HTTP隧道是一种允许客户端和服务器之间通过中间代理进行通信的技术。这种隧道技术允许代理服务器转发客户端和服务器之间的所有HTTP请求和响应&#xff0c;而不需要对请求或响应内容进行任何处理或解析。Python提供了强大的网络编程能力&#xff0c;可以使用标准库中的socket和…

JAVA反射总结学习

初始反射反射的基本操作反射安全性问题 反射是指在Java运行状态中: 给定一个类对象(Class对象)&#xff0c;通过反射获取这个类对象(Class对象)的所有成员结构&#xff1b; 给定一个具体的对象&#xff0c;能够动态地调用它的方法及对任意属性值进行获取和赋值&#xff1b; …

【数据结构与算法】【小白也能学的数据结构与算法】递归 分治 迭代 动态规划 无从下手?一文通!!!

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

X图形

1.题目 这道题是蓝桥云课上面的一道题目&#xff0c;它是2022年蓝桥杯省模拟题&#xff0c;题目难度为简单。 考察的知识点为递归。 题目链接&#xff1a;X图形 2.思路 如何理解题意&#xff1f; 蓝桥杯的题目和Leetcode题目最大的不同点在于&#xff0c;蓝桥杯的题目大部…