for的用法详解,for循环完全攻略

本文介绍了C语言中的for循环工作原理,并通过实例解释了水仙花数和求和算法。强调了循环变量初始化、条件判断及循环体的执行过程,同时探讨了自增、自减操作符的使用,以及如何优化循环条件以提高效率。此外,还提供了几个练习题,如计算阶乘、求解特定条件的数之和以及找出完全平方数,以加深对for循环和条件判断的理解。
摘要由CSDN通过智能技术生成

说到for循环,比较出名的一个算法当然是很多互联网公司都喜欢在面试的时候考的水仙花数啦,先来看一下这个算法是怎么写的吧。

这串代码其实很短,不过有一点逻辑上的考验,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身。例如: 153是一个“水仙花数”,因为153=1的三次方+5的三次方+3的三次方。那关于水仙花数的每个数是怎么来的,可以具体看一下代码的实现。

public class shuixianhuashu {
	public static void main(String[] args) {
		int a,b,c;
		for(int i = 100; i <= 999; i++){
			a = i / 100;
			b = i / 10 % 10;
			c = i % 10;
			if(i == (a*a*a+b*b*b+c*c*c))
				System.out.println(i);
		}
	}
}

下面说一下这个for循环的使用,我觉得下面这篇文章不错,是转载过来的,里面有很多的练手算法,可以尝试一下。不过下面这篇文章使用c语言编写,看一下方法就行,方法都是一样的。


for 循环语句的一般形式为:

for (表达式1; 表达式2; 表达式3)
{
        语句;
}

首先要强调两点:
1) 表达式1、表达式2和表达式3之间是用分号 ;隔开的,千万不要写成逗号。

2)  for(表达式1;表达式2;表达式3)的后面千万不要加分号,很多新手都会犯这种错误——会情不自禁地在后面加分号。

因为 for 循环只能控制到其后的一条语句,而在C语言中分号也是一个语句——空语句。所以如果在后面加个分号,那么 for 循环就只能控制到这个分号,下面大括号里面的语句就不属于 for 循环了。

下面来看看它的执行过程:
  1. 求解表达式1。
  2. 求解表达式2。若其值为真,则执行 for 语句中指定的内嵌语句,然后执行第3步;若表达式2值为假,则结束循环,转到第5步。
  3. 求解表达式3。
  4. 转回上面第2步继续执行。
  5. 循环结束,执行 for 语句下面的语句。

从这个执行过程中可以看出,“表达式1”只执行一次,循环是在“表达式2”“表达式3”和“内嵌语句”之间进行的。

for语句最简单的形式是:

for (循环变量赋初值; 循环条件; 循环变量增值)
{
    语句;
}


下面给大家写一个程序,求 1+2+3+4+…+100 的总和。

     
     
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int i;
  5. int sum = 0; //sum的英文意思是“总和”
  6. for (i=1; i<=100; ++i) //++是自加的意思, ++i相当于i = i + 1
  7. {
  8. sum = sum + i; /*等价于sum += i;但是不建议这么写, 因为sum = sum + i看起来更清楚、更舒服*/
  9. }
  10. printf("sum = %d\n", sum);
  11. return 0;
  12. }
# include <stdio.h>
int main(void)
{
    int i;
    int sum = 0;  //sum的英文意思是“总和”
    for (i=1; i<=100; ++i)  //++是自加的意思, ++i相当于i = i + 1
    {
        sum = sum + i;  /*等价于sum += i;但是不建议这么写, 因为sum = sum + i看起来更清楚、更舒服*/
    }
    printf("sum = %d\n", sum);
    return 0;
}
输出结果是:
sum = 5050

这个程序的功能是实现求 1+2+3+4+…+100 的和,如果不用循环,加一次就要一条语句,加 100 次就要 100 条语句。这里是从 1 加到 100,要是从 1 加到 10000 那就要 10000 条语句。但有了循环就很方便了,你想加到多少就加到多少,只要改一个参数就可以了。所以循环很重要。

下面按照执行过程看看上面这个程序是怎样执行的。

1) 首先定义一个循环变量 i。定义的时候可以不给它赋初值,在 for 循环里面再给它赋初值也行。但前面说过,最好在定义变量的时候就对它进行初始化,如果值不确定就初始化为 0。所以程序中也可以在定义 i 的时候就给它赋初值,那么 for 循环里的“表达式1”就可以省略了,但分号不可以省略。

这样的话,执行的时候就跳过第1步,直接进入第2步,其他的不变。所以程序也可以像下面这样写:

     
     
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int i = 1;
  5. int sum = 0;
  6. for (; i<=100; ++i)
  7. {
  8. sum = sum + i;
  9. }
  10. printf("sum = %d\n", sum);
  11. return 0;
  12. }
# include <stdio.h>
int main(void)
{
    int i = 1;
    int sum = 0;
    for (; i<=100; ++i)
    {
        sum = sum + i;
    }
    printf("sum = %d\n", sum);
    return 0;
}
当然表达式1加上也行,大不了再重新赋一次值。

2) 然后定义一个用来存放“和”的变量 sum,并给它赋初值 0,然后进入 for 循环:
  1. 首先求解表达式1,即给变量i赋初值,i=1;表达式1只执行这一次,下面都不会再执行了。
  2. 然后求解表达式2,若 1<=100 成立,则执行 for 循环中的内嵌语句,即 sum=0+1。
  3. 然后执行第3步,变量 i 自加 1,即变量 i 由 1 变为 2。
  4. 然后再求解表达式2,2<=100 成立,则执行 for 循环中的内嵌语句,sum=0+1+2。
  5. 然后再执行第3步,变量 i 自加 1,即变量 i 由 2 变为 3。
  6. 然后再求解表达式2,即 3<=100 成立,则执行 for 循环中的内嵌语句,sum=0+1+2+3。
  7. ……

就这样一直循环下去,直到 ++i 等于 100 的时候,求解表达式2,即 100<=100 成立,则执行 for 循环中的内嵌语句,sum=0+1+2+3+…+100。

然后再执行第3步,变量 i 自加 1,即变量 i 由 100 变为 101。然后再求解表达式2,即 101<=100 不成立,则结束循环,执行 for 循环下面的语句即 printf。

以上就是这个程序的执行过程。关于 for 语句的代码规范化问题,有两点要再跟大家强调一下:
1)if、else、for、while、do 都只能控制到其后的一条语句,如果要控制多条语句必须加大括号 {}。但基于代码规范化,if、else、for、while、do 后面的执行语句不论有多少行,就算只有一行也要加 {}

2) 像 if、for、while 等关键字之后应留一个空格再跟左括号 (,以突出关键字。

此外上面的程序还有一个知识点要跟大家说一下:从功能上讲, for(i=1; i<=100;++i)完全可以写成 for(i=1; i<101; ++i),而且建议大家尽量使用这种写法。也就是说,循环语句的循环条件尽量写成半开半闭的,不管是 for 循环还是 while 循环。

for(i=1; i<101; ++i)实际上是 1≤i<101,是半开半闭的;而 for(i=1; i<=100; ++i)实际上是 1≤i≤100,是全闭的。那么为什么建议使用半开半闭的呢?因为如果写成 i<=100 的话,那么每次判断的时候都要判断两次,即 i<100 和 i==100,而写成 i<101 的话每次只需要判断一次。

也许有人说:程序在执行 i<=100 的时候不是将它转换成 i<100||i==100 吗?这样由“短路或”的知识可知,如果前面的为真那么后面的不就不会执行了吗?这样不也是判断一次吗?不是这样的,系统是不会将 i<=100 转换成 i<100||i==100 的,每次判断的时候 i<100 和 i==100 都要判断。

但是写成半开半闭也有一个问题,就是会影响对代码的理解。有时候写成全闭的区间理解起来才顺畅,而写成半开半闭反而不易理解,比如 <=右边是变量或表达式的时候。这时候要以可读性为第一要素,即哪种好理解就使用哪种。现在 CPU 速度那么快,也不在乎那点效率。所以前面说“尽量”,没有要求一定要那样写。

下面再给大家写一个程序,求 1 到 100 之间所有奇数的和。

     
     
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int i;
  5. int sum = 0 ;
  6. for (i=1; i<100; i+=2) //i+=2;等价于i = i + 2;
  7. {
  8. sum = sum + i;
  9. }
  10. printf("sum = %d\n", sum);
  11. return 0;
  12. }
# include <stdio.h>
int main(void)
{
    int i;
    int sum = 0 ;
    for (i=1; i<100; i+=2)  //i+=2;等价于i = i + 2;
    {
        sum = sum + i;
    }
    printf("sum = %d\n", sum);
    return 0;
}
输出结果是:
sum = 2500

关于自增和自减

一直以来,++ 和 –– 语法浪费了太多人的时间。说句实在话,++ 和 –– 在C语言中根本就不重要,除了表达简练外,真的没有什么其他好处了。

简单地说:++i 和 i++ 在单独使用时,都表示 i=i+1;––i 和 i–– 在单独使用时,都表示 i=i–1。

而 a=++i 就相当于 i=i+1,a=i;a=i++ 就相当于 a=i,i=i+1。
同理,a=––i 就相当于 i=i–1,a=i;a=i–– 就相当于 a=i,i=i–1。

如果实在搞不明白 ++ 和 –– 是怎么回事,那也不是什么天塌下来的事情。因为 a=++i;完全可以写成 i++; a=i;。而 a=i++;也完全可以写成 a=i; i++;。而且,这也是一种很好的程序风格。

作为一个优秀的程序员,在你的程序中就不应该体现出 ++i 和 i++ 的区别,要么都用 ++i,要么都用 i++,不要一会儿用 ++i 一会儿用 i++。

对于自增和自减还有一点需要强调的是:只有“变量”才能进行自增和自减!你认为 3++ 等于多少?C语言中没有这种写法,常量是不能进行自增和自减的。

for循环练习

1) 求 1! + 2! + 3! + ... + n!

     
     
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int n = 0;
  5. int i = 0;
  6. int m = 1;
  7. int sum=0;
  8. printf("请输入n的值:");
  9. scanf("%d", &n);
  10. for (i=1; i<=n; ++i)
  11. {
  12. m = m * i;
  13. sum = sum +m;
  14. }
  15. printf ("sum = %d\n", sum);
  16. return 0;
  17. }
# include <stdio.h>
int main(void)
{
    int n = 0;
    int i = 0;
    int m = 1;
    int sum=0;
    printf("请输入n的值:");
    scanf("%d", &n);
    for (i=1; i<=n; ++i)
    {
        m = m * i;
        sum = sum +m;
    }
    printf ("sum = %d\n", sum);
    return 0;
}
这个程序虽然短,但逻辑性很强,算法很好,所以建议读者记住。因为逻辑性强,所以只看是很难明白的,自己在纸上试一下,将自己当成计算机一步步地计算就明白了。

假如 n=4:
  1. 当 i=1 时,m=1,sum=1。
  2. 当 i=2 时,m=1×2,sum=1+1×2。
  3. 当 i=3 时,m=1×2×3,sum=1+1×2+1×2×3。
  4. 当 i=4 时,m=1×2×3×4,sum=1+1×2+1×2×3+1×2×3×4。

看出规律来了吗?m 的值是一直往下乘,乘以 i 之前 m 的值是(i–1)的阶乘,乘以 i 之后 m 的值就是 i 的阶乘了。这样 i 循环到多少,m*i 就立刻将这个数的阶乘计算出来,然后加到 sum 中。

2) for 和 if 的嵌套使用。求 1 到 100 之间所有能被 3 整除的数之和。

     
     
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int i;
  5. int sum = 0;
  6. for (i=3; i<100; ++i)
  7. {
  8. if (0 == i%3)
  9. {
  10. sum = sum +i;
  11. }
  12. }
  13. printf("sum = %d\n", sum);
  14. return 0;
  15. }
# include <stdio.h>
int main(void)
{
    int i;
    int sum = 0;
    for (i=3; i<100; ++i)
    {
        if (0 == i%3)
        {
            sum = sum +i;
        }
    }
    printf("sum = %d\n", sum);
    return 0;
}
输出结果是:
sum = 1683

大家想想如果不用 if,这个程序能不能写出来?当然能,能被 3 整除的数肯定是 3 的倍数,只要 i 每次自加 3 就行了。我们将这个程序写一下:

     
     
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int i;
  5. int sum = 0;
  6. for (i=3; i<100; i+=3)
  7. {
  8. sum = sum +i;
  9. }
  10. printf("sum = %d\n", sum);
  11. return 0;
  12. }
# include <stdio.h>
int main(void)
{
    int i;
    int sum = 0;
    for (i=3; i<100; i+=3)
    {
        sum = sum +i;
    }
    printf("sum = %d\n", sum);
    return 0;
}
因为 ++i 每次只加 1,而 i+=3 每次加 3,所以这种写法与第一种写法比较起来计算机少执行很多步,所以执行起来更快。由此可知,完成相同的功能,算法不一样则效果就不一样。对计算机而言当然是执行得越快越好。

3) 编写程序,输出 1~1000 之间所有的完全平方数。

     
     
  1. # include <stdio.h>
  2. # include <math.h> //要用sqrt()
  3. int main(void)
  4. {
  5. int i; //循环变量
  6. int x; //存储每个数的二次方根
  7. for (i=1; i<1000; ++i)
  8. {
  9. x = sqrt(i); /*如果i不是完全平方数, 那么sqrt(i)肯定是小数, 而i是int型, 所以x是sqrt(i)取整后的值, 这样x*x肯定不等于i*/
  10. if (x*x == i)
  11. {
  12. printf("%d\t", i); // \t是跳到下一个Tab位置
  13. }
  14. }
  15. printf("\n");
  16. return 0;
  17. }
# include <stdio.h>
# include <math.h>  //要用sqrt()
int main(void)
{
    int i;  //循环变量
    int x;  //存储每个数的二次方根
    for (i=1; i<1000; ++i)
    {
        x = sqrt(i);  /*如果i不是完全平方数, 那么sqrt(i)肯定是小数, 而i是int型, 所以x是sqrt(i)取整后的值, 这样x*x肯定不等于i*/
        if (x*x == i)
        {
            printf("%d\t", i);  // \t是跳到下一个Tab位置
        }
    }
    printf("\n");
    return 0;
}
输出结果是:
1       4       9       16      25      36      49      64      81    100
121     144     169     196     225     256     289     324     361   400
441     484     529     576     625     676     729     784     841   900
961

其实这个程序还有更简单的算法,不需要使用 sqrt()。下面将这个程序也写下来:

     
     
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int i; //循环变量
  5. for (i=1; i*i<1000; ++i)
  6. {
  7. printf("%d\t", i * i); // \t是跳到下一个Tab位置
  8. }
  9. printf("\n");
  10. return 0;
  11. }
# include <stdio.h>
int main(void)
{
    int i;  //循环变量
    for (i=1; i*i<1000; ++i)
    {
        printf("%d\t", i * i);  // \t是跳到下一个Tab位置
    }
    printf("\n");
    return 0;
}
输出结果是:
1       4       9       16      25      36      49      64      81    100
121     144     169     196     225     256     289     324     361   400
441     484     529     576     625     676     729     784     841   900
961
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值