C语言 第五周知识点随记

for 语句

一般形式

for (表达式1;表达式2;表达式3)
    语句    //反复执行部分,即循环体。循环体只能是单条语句,如果需要执行多条语句需要用{}括起来

E.g:

for (i=1; i<=3; i++)    //三个表达式以分号隔开的,而不是逗号
    printf("%d",i);    //循环体

/*输出结果为123*/

for 语句执行流程

  1. 首先执行表达式1;
  2. 然后判断表达式2的值是真(非0)还是假(0);
  3. 若为真,则执行一次循环体,在执行表达式3,然后转向第2步;
  4. 若为假,则结束循环,转向循环体之后的语句执行。

  1. 表达式1一般用于给循环变量赋初值;        //给i赋值为1
  2. 表达式2则是循环的条件;                          //判断是否满足循环条件,当i<=3时进入循环体
  3. 表达式3一般用于递变循环变量的值。        //当一个循环体执行结束后i++

for 循环与while循环

一般而言,如果“循环变量赋初值、循环条件、循环变量递变“三部分不复杂,可使用for循环。反之,则使用while循环,更加明了直观。

相互平行的循环

例子:

#include <stdio.h>
int main()
{
    int i;

    for (i=1; i<=5; i++)    //两个循环平行,先做第一个循环
    printf("%d", i*i);    

    for (i=1; i<=6; i++)    //再做第二个循环,且平行循环的循环变量名允许同名
    printf("%d", i*i*i);
    
    return 0;
/*输出结果为1491625(第一个循环)182764125216(第二个循环)*/
}

素数的判断

素数的定义

  • 只能被1和自己整除的数,不包括1

初始代码如下,输入某一个值:

#include <stdio.h>
int main()
{
    int x;


    scanf("%d", &x);

    return 0;
}

为了判断是否为素数,我们要看这个数是否能被2、3、4…(x-1)整除,因此引入一个循环变量i

接着考虑使用什么循环语句,由于变量i有明显的递增,因此使用for循环,更加简洁明了。

#include <stdio.h>
int main()
{
    int x;

    scanf("%d", &x);

    int i;
    for (i=2; i<x; i++) {
        if (x % i == 0) {
            printf("不是素数\n");    //每次执行一次循环体都会打印一次”不是素数“
        }    /*没有跳出循环的指令,当已经可以判断素数后(可被除了1及本身的数整除后),还会继续执行循环体*/
    }

    printf("是素数\n");    //循环体结束后一定会执行该语句,因此无论如何都会输出”是素数“
    return 0;
}

 该算法可继续被优化。

  • 添加一个新的量isPrime,来判断是否是素数。
  • 在循环体中添加一个break语句跳出循环。
  • 添加一个if语句,判断isPrime的值,以输出结果。
#include <stdio.h>
int main()
{
    int x;
    int isPrime = 1;    //添加新变量,证伪,初始值设置为1(true)
    scanf("%d", &x);

    int i;
    for (i=2; i<x; i++) {
        if (x % i ==0) {
            isPrime = 0;   //将能被整除的结果以0(false),即不是素数,赋给isPrime
            break;    //跳出循环
        }    
    }

/* 加入一个if条件判断语句,判断isPrime的值,输出结果。*/

    if (isPrime == 1){
        printf("是素数\n");
    } else {
        printf("不是素数\n");
    }

    return 0;
}

 注意:==是判断是否相等,而=是赋值!!!!

break 与 continue

以唱歌为例子:

B.g:一群同学按照学号轮流站起来唱歌。

  • continue:第一个同学起来唱歌,唱得好听,唱完坐下(执行了一次循环体);第二个同学站起来唱歌,唱的不是很好听,中途打断,直接让他坐下让第三个同学起来唱歌(第二次循环体执行中断,直接跳转第三个)。
  • break:第一个同学起来唱歌,唱得好听,唱完坐下(执行了一次循环体);第二个同学站起来唱歌,唱的让人无法忍受,打断,老师走出房间,停止本节音乐课。(第二次循环体结束,同时也跳出整个循环,不再执行循环体语句)。

输出100以内的所有素数

在上一个输入判断是否为素数的程序中做些许修改。

#include<stdio.h>
int main()
{
    int x;
 
    
    for (x=2; x<=100; x++){
    	
    	int isPrime = 1;    //请注意!isPrime要在循环体内定义!因为每给出一个新的数x,就要让它默认是素数做判断
    	int i;
    	
	    for (i=2; i<x; i++) {
	        if (x % i == 0) {
	            isPrime = 0;   //将能被整除的结果以0(false),即不是素数,赋给isPrime
	            break;    //跳出循环
	        }    
	    }
	    
		    if (isPrime == 1){
	        printf("%d,", x);
	    }
	}
    return 0;
}

输出结果:2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,

使用了嵌套的循环。

输出前50个素数。(若使用for循环,不合适,for循环用于次数是确值,或范围是确值)

#include<stdio.h>
int main()
{
	
     int x;
     int cnt = 0;
    while (cnt < 50) {    //用while循环
    	
    	int isPrime = 1;    //请注意!isPrime要在循环体内定义!因为每给出一个新的数x,就要让它默认是素数做判断
    	int i;
    	
	    for (i=2; i<x; i++) {
	        if (x % i == 0) {
	            isPrime = 0;   //将能被整除的结果以0(false),即不是素数,赋给isPrime
	            break;    //跳出循环
	        }    
	    }
	    
		if (isPrime == 1){
	        printf("%d,", x);
            cnt ++;    //输出一个素数后,计数1
	    }
        x++;    //整个流程做完后要把x+1
	}


    return 0;
}

 凑硬币

如何用1角、2角和5角的硬币凑出10元以下的金额呢?

思路:使用枚举法,用3个循环。

#include<stdio.h>
int main()
{
	int x;
	int one, two, five;    //引入变量代表1角、2角、5角的个数
	
	scanf("%d", &x);
	
	for (one=0; one<=x*10; one++){    //第一层循环,先固定1角的个数
		for (two=0; two*2<=x*10; two++){    //第二层循环,固定2角的个数
			for (five=0; five*5<=x*10; five++){    //第三层循环,确定5角的个数,1、2角确定的情况下,将5角符合条件的枚举完
				if(one+two*2+five*5==x*10){    //判断加起来是否与x相等
					printf("可以用%d个1角,%d个2角,%d个五角凑成%d元。\n",one, two, five, x);    //输出结果		
				}
			}
		}
	}
	
	return 0;
	
 } 

(初次看到本题感觉脑袋都大了,如何捋清思路,如何选择语句很重要,使用计算机不怕重复和列举的特性,可以让它把所有的情况都列举出来,从中选择符合条件的结果。)  

继续优化:如果想让这个程序找出一个合适的答案就停止。则需要使用break语句/goto语句。

如果添加了一句break

#include<stdio.h>
int main()
{
	int x;
	int one, two, five;    //引入变量代表1角、2角、5角的个数
	
	scanf("%d", &x);
	
	for (one=0; one<=x*10; one++){    //第一层循环,先固定1角的个数
		for (two=0; two*2<=x*10; two++){    //第二层循环,固定2角的个数
			for (five=0; five*5<=x*10; five++){    //第三层循环,确定5角的个数,1、2角确定的情况下,将5角符合条件的枚举完
				if(one+two*2+five*5==x*10){    //判断加起来是否与x相等
					printf("可以用%d个1角,%d个2角,%d个五角凑成%d元。\n",one, two, five, x);    //输出结果		
                    break;    //break只能跳出当前它所在的这层循环
				}
			}
		}
	}
	
	return 0;
	
 } 

发现仍然输出多个答案,经过调试,我们发现break只能跳出当前它所在的那层循环。

但如果在每个循环体都加了1个break,我们发现无论内层循环以什么方式跳出,都会跳出下一层循环,不符合需求。

这时候我们引入一个变量exit,使用if语句来实现跳出功能。称为接力break。

#include<stdio.h>
int main()
{
	int x;
	int one, two, five;    //引入变量代表1角、2角、5角的个数
	int exit = 0;    //引入一个跳出循环的变量

	scanf("%d", &x);
	
	for (one=0; one<=x*10; one++){    //第一层循环,先固定1角的个数
		for (two=0; two*2<=x*10; two++){    //第二层循环,固定2角的个数
			for (five=0; five*5<=x*10; five++){    //第三层循环,确定5角的个数,1、2角确定的情况下,将5角符合条件的枚举完
				if(one+two*2+five*5==x*10){    //判断加起来是否与x相等
					printf("可以用%d个1角,%d个2角,%d个五角凑成%d元。\n",one, two, five, x);    //输出结果		
                    exit = 1;    //找出答案,将1赋值给exit
                    break;    //break跳出当前它所在的这层循环
				} 
			}
            if (exit = 1) break;    //使用if循环和exit,实现接力break
		}
        if (exit = 1) break;
	}
	
	return 0;
	
 } 

 goto

语法:

goto 标号;

     标号:
#include<stdio.h>
int main()
{
	int x;
	int one, two, five;    //引入变量代表1角、2角、5角的个数
	
	scanf("%d", &x);
	
	for (one=0; one<=x*10; one++){    //第一层循环,先固定1角的个数
		for (two=0; two*2<=x*10; two++){    //第二层循环,固定2角的个数
			for (five=0; five*5<=x*10; five++){    //第三层循环,确定5角的个数,1、2角确定的情况下,将5角符合条件的枚举完
				if(one+two*2+five*5==x*10){    //判断加起来是否与x相等
					printf("可以用%d个1角,%d个2角,%d个五角凑成%d元。\n",one, two, five, x);    //输出结果		    
                    goto out;    //goto跳转到out
				}
			}
		}
	}
out:	//直接跳出多重循环,来到结束
	return 0;
	
 } 

 循环应用

前n项求和

 思路不难,但是要注意细节

#include<stdio.h>
int main()
{
    int n;
    int i;
    double sum = 0;

    scanf("%d", &n);

    for(i=1; i<=n; i++){
    sum += sum + 1.0/i;
    }
    printf("f(%d)=%d", n, sum);

    return 0;
} 

 题目修改一下:

#include<stdio.h>
int main()
{
    int n;
    int i;
    double sum = 0;
    double sign = 1.0;    //引入一个浮点数sign

    scanf("%d", &n);

    for(i=1; i<=n; i++){
    sum += sum + sign/i;
    sign = -sign;    //sign符号反转
    }
    printf("f(%d)=%d", n, sum);

    return 0;
} 

 正序分解整数

需求:

 

#include<stdio.h>
int main()
{
	int number;
	int n;	//number的替身,用于算出几位数 
	int mask = 1;	//取最高位
	int d;	//商

	scanf("%d", &number);
	n = number;
	while ( n>9 ){    //翁恺老师的思路真的牛,让mask记录输入的数是几位,同时为接下来除和取余做准备
		n=n/10;
		mask *= 10;
	}
//	printf("%d, %d\n", m, mask);
//    这一步可以输出mask的值判断一下是否正确
	
	while (mask > 0) {
	d = number/mask;
	number = number%mask;
	
	if (mask == 1) {
		printf("%d",d);
	} else {
		printf("%d ",d);
	}
	mask /= 10;
	} 	
		
	return 0;
 } 

翁恺老师的思路真的太绝了!

可以归纳出几个写程序的tips

  • 写程序可以先把思路以注释的形式写下来
  • 先搭建一个框架,再逐步求精
  • 可以在循环后面加printf输出,看循环是如何实现的
  • 联系相似题目,运用已有的经验,比如输出逆序整数的题中,取出每一位对应的数,可以用整除/取余%
  • 写完程序后,要测试几个极值,特殊值来确定是否考虑周全
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值