C语言入门Day_16 循环的嵌套

目录

前言

1.循环的嵌套

2.循环和判断相互嵌套

3.易错点

4.思维导图


前言

我们已经知道如何通过循环结构来遍历一个一维数组,访问里面的每一个元素。

我们用循环里面的计数器,来作为数组的下标,就可以简单的遍历数组里面的每一个元素。

那我们怎么遍历一个二维数组呢?可以通过循环的嵌套来实现。

1.循环的嵌套

1.1

我们可以用两个for循环嵌套,外层的for循环的计数器是二维数组的第一个下标,内测的for循环的计数器是二维数组的第二个下标

这里就有两层for循环,来遍历访问一个二维数组:

int doouble_list[3][3]={{1,2,3},{4,5,6},{7,8,9}};
for(int i=0;i<3;i++){
    for(int j=0;j<3;j++) {
        printf("%d\n",double_list[i][j]) ;
    }
}

1.定义一个二维数组    int double_list[3][3] ={{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

2.外层的for循环,里面的i会作为二维数组的第一个下标   for(int i=0;i<3;i++){

3.内层的for循环,里面的j会作为二维数组的第二个下标   for(int j=0;j<3;j++){

int doouble_list[3][3]={{1,2,3},{4,5,6},{7,8,9}};
for(int i=0;i<3;i++){
    for(int j=0;j<3;j++) {
        printf("%d\n",double_list[i][j]) ;
    }
}

4.打印单个二维数组的元素   printf("%d\n",double_list[i][j]);

5.二维数组的第一个下标   [i]

6.二维数组的第二个下标   [j]

1.2

外层for循环一共会执行三次,分别是i = 0i = 1i = 2的时候。

i = 3的时候,循环条件不符合,就不会执行了。

内层的for循环会执行9次,当i=0的时候,会执行j=0j=1j=2这3次;

i=1i=2的时候也会分别执行3次;

一共9次。

1.3

循环嵌套的代码执行顺序也是一层一层深入,外层循环判断以后,会完整执行内层循环的判断和代码块;

然后再回到外层循环进行判断,以及继续进入内层循环来执行。

1.4 

eg:

int double_list[2][2]={{1,2},{3,4}};
for(int i=0;i<2;i++){
    for(int j=0;j<2;j++){
    printf("%d\n",double_list[i][j])
    }
}

1.首先定义二维数组   int double_list[2][2] ={{1, 2}, {3, 4}};

2.执行外层循环的判断,判断条件为真,进入循环内部   for(int i=0;i<2;i++){

3.进入内层循环,判断条件为真,进入printf()代码   for(int j=0;j<2;j++){

4.执行printf()代码   printf("%d\n",double_list[ i ][ j ]);

int double_list[2][2]={{1,2},{3,4}};
for(int i=0;i<2;i++){
    for(int j=0;j<2;j++){
    printf("%d\n",double_list[i][j])
    }
}

5.再进行内层循环的判断,判断为真,继续printf()代码   for(int j=0;j<2;j++){

6.继续printf()   printf("%d\n",double_list[ i ][ j ]);

7.再一次进行内层循环的判断,判断条件为假,退回到外层循环   for(int j=0;j<2;j++){

8. i = 1外层循环条件判断为真,继续进入内层循环   for(int i=0;i<2;i++){

int double_list[2][2]={{1,2},{3,4}};
for(int i=0;i<2;i++){
    for(int j=0;j<2;j++){
    printf("%d\n",double_list[i][j])
    }
}

9. j 重新等于0,内层循环重新开始,执行printf()   for(int j=0;j<2;j++){

10.执行printf()代码   printf("%d\n",double_list[ i ][ j ]);

11.再一次内层循环的判断   for(int j=0;j<2;j++){

int double_list[2][2]={{1,2},{3,4}};
for(int i=0;i<2;i++){
    for(int j=0;j<2;j++){
    printf("%d\n",double_list[i][j])
    }
}

12.判断条件为真,执行printf()代码   printf("%d\n",double_list[ i ][ j ]);

13.此时j=2,内层判断不成立,退回到外层   for(int j=0;j<2;j++){

14.外层循环判断条件也不成立,循环执行结束   for(int i=0;i<2;i++){
 

1.5

由于外层循环判断以后,会执行数次内层循环,所以我们又习惯于把外层循环叫做大循环,内层循环叫做小循环

一个大循环对应多个小循环,而且每次小循环都是从头开始

我们可以看到,小循环都会重新定义 j,所以每次大循环进入小循环以后,都会从新定义j,也就是从0开始:

int double_list[2][2]={{1,2},{3,4}};
   for(int i=0;i<2;i++){
    for(int j=0;j<2;j++){
    printf("%d\n",double_list[i][j]);
  }  
}

1.6

while循环也是类似的执行顺序——外层循环到内层循环,只不过在代码的写法上面略有不同。

int double_list[2][4]={{1,2,3,4},{5,6,7,8}};
int i=0;
int j=0;
while(i<2){
     j=0;
     while(j<4){
        printf("%d\n",int double_list[i][j]);
        j++;    
    }
    i++;
}

1.定义二维数组double_list和计数器i和j   

int double_list[2][4] ={{1, 2, 3, 4}, {5, 6, 7, 8}};

int i = 0;

int j = 0;

2外层循环

while(i<2){

j = 0;

j++;

}

3.内层循环

while(j<4){

printf("%d\n",double_list[i][j]);

j++;

}

4.while循环需要自己实现计数器的清零,和迭代自增

5.打印数组元素 

 printf("%d\n",double_list[ i ][ j] );

1.7

while循环的嵌套和for循环的嵌套之间的细微差别主要在于,for循环可以在循环框架内实现的变量定义和自增,while循环需要自己实现

这也是用while循环很容易出错的地方,尤其需要注意。

这里的循环嵌套只有两层,只要你愿意,你可以嵌套无数层循环,但我们不建议嵌套太多。

一来这样会把代码的执行顺序搞得很复杂,二来很容易让循环的次数指数级别的上升,最后导致程序运行时间很长。

除了判断嵌套判断,和循环嵌套循环以外,

我们还可以灵活的让判断和循环相互嵌套,以实现一些复杂的代码逻辑。

2.循环和判断相互嵌套

2.1

比如我们要输出一个长度为10的数组里面的所有大于0的正数:

int number_list[10] = {4, 5, -1, -5, 0, 2, 10, 8, -2, 9};
for(int i = 0;i < 10; i++){
    if(number_list[i] > 0){
        printf("%d\n", number_list[i]);
   }
}

1.定义一个一维数组    number_list   int number_list[10] = {4, 5, -1, -5, 0, 2, 10, 8, -2, 9};

2.在外层我们循环遍历整个数组    for(int i = 0;i < 10; i++){

3.在内层我们对数组的元素进行判断是否大于0    if(number_list[i] > 0){   }

4.大于零的值我们就进行打印输出    printf("%d\n", number_list[i]);

仍然是外层循环先遍历所有的数组元素,然后每个值我们都进行了一次判断,大于0的就进行输出。

2.2

我们看看代码的执行顺序:

int number_list[4]={4,5,-1,-5};
for(int i=0;i<4;i++){
    if(number_list[i]>0){
       printf("%d\n",number_list[i]);
    }
}

1.定义一个数组   

number_list   int number_list[4] = {4, 5, -1, -5};

2.执行外层的循环   

 for(int i = 0;i < 4; i++){

3.判断number_list[0]是4,大于0,进行输出   

if(number_list[ i ] > 0){

printf ("%d\n", number_list[ i ]);

}

4.执行外层的循环 

 for(int i = 0;i < 4; i++){

5.判断number_list[1]是5,大于0,进行输出

if(number_list[i] > 0){

printf("%d\n", number_list[i]);

}

int number_list[4]={4,5,-1,-5};
for(int i=0;i<4;i++){
    if(number_list[i]>0){
       printf("%d\n",number_list[i]);
    }
}

6.执行外层的循环   

for(int i = 0;i < 4; i++){

7.判断number_list[2]是-1,小于0,不进行输出 

  if(number_list[i] > 0){

8.执行外层的循环 

  for(int i = 0;i < 4; i++){

9.判断number_list[3]是-5,小于0,不进行输出 

  if(number_list[i] > 0){
 

2.3

我们可以看到代码的执行顺序仍然是从外到内层层递进,然后根据循环结构的执行顺序和判断结构的执行顺序,一步一步的执行。

除了循环嵌套判断,我们同样可以判断来嵌套循环。

bool today_is_sat = true;
if(today_is_sat){
	for(int i=0; i<5; i++){
		printf("运动一次\n");
	}
}else{
	for(int i=0;i < 2;i++){
        printf("运动一次\n");
    }
}

1.定义布尔变量 

  bool today_is_sat = true;

2.外层的判断

if(today_is_sat){

}else{

}

3.内层的循环,这里会循环执行5次

for(int i=0; i<5; i++){

printf("运动一次\n");

}

4.内层的循环,这里会循环执行2次

for(int i=0;i < 2;i++){

printf("运动一次\n");

}

2.4

同样的,不管怎么嵌套,我们都一层一层按照代码的执行顺序去分析就可以了

理论上,我们可以无限嵌套到无限深,但是同样我们要考虑代码的复杂度和可读性

所以我们建议最多不要超过两层,这样代码结构会清爽很多。

3.易错点

 下面这段代码,会输出什么?

int i = 0, j = 0;
while (i < 3) {
  do {
    printf("%d, %d\n", i, j);
    j++;
  } while (j < 2);
  i++;
}

在这段代码中,一定要搞清楚do-while是先执行再判断:

第一次输出:

  • i = 0,j = 0;
  • 满足外层循环条件 i < 3,然后紧接着进入内层循环输出0,0

第二次输出:

  • 然后 j++--> j = 1,小于2,满足条件,继续内层循环,输出0,1
  • 然后 j++ --> j = 2,不满足小于2,跳出内层循环;

第三次输出:

  • 然后 i++ --> i = 1,满足外层循环条件i<3,然后进入内层循环,先do,输出1,2
  • 然后 j++,j=3,不满足小于2,跳出内层循环;

第四次输出:

  • 然后 i++ --> i = 2,满足外层循环条件 i<3 ,然后进入内层循环,先do,输出2,3
  • 然后 j++ --> j=4,不满足小于2,跳出内层循环;

接着 i++ --> i = 3,不满足外层循环条件,跳出外层循环,整个循环结束。

因此,输出结果为:

0, 0
0, 1
1, 2
2, 3

循环嵌套中,循环的顺序选择是至关重要的。选择正确的循环顺序可以避免逻辑错误和重复计算。

循环嵌套可能导致性能问题,特别是在处理大规模数据集时。要注意避免不必要的重复计算或循环次数过多的情况,可以考虑优化循环结构或使用其他数据结构来提高性能。

嵌套的循环控制变量不能相同

外层循环可包含两个以上内循环,但不能相互交叉。

4.思维导图

​​​​​​​

最后我想说的是:

在撰写这篇文章时,我参考了《白纸编程》这个app的观点和思想,我要感谢他们对我的启发和帮助。 

  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值