C语言基础02——控制语句。二分查找、随机数讲解、求自幂数、整数逆序、X图案打印、猜数字、公约数公倍数、素数

目录

分支语句(选择结构)

if语句

switch语句

循环语句

while循环

do…while循环

for循环

循环语句的练习

转向语句

goto语句

break语句

continue语句

return语句


什么是控制语句?

控制语句用于控制程序的执行流程,以实现程序的各种结构方式,他们由特定的语句定义符组成,C语言有九种控制语句。

可以分为以下三类:
- 条件判断语句/分支语句:if语句、switch语句
- 循环执行语句:do while语句、while语句、for语句
- 转向语句:break语句、goto语句、continue语句、return语句

C语言中真假的表示

- 0表示假
- 非0表示真。

—— 那!0应该返回哪个数?
—— 返回1

分支语句(选择结构)

if语句

  • if语句的结构语法

    //第一种
    if(表达式)
    {
    	语句;
    }
    
    //第二种
    if(表达式)
    {
    	语句;
    }
    else
    {
    	语句;
    }
    
    
    //第三种
    if(表达式)
    {
    	语句;
    }
    else if(表达式)
    {
    	语句;
    }
    else
    {
    	语句;
    }
    
    • 对于if语句来说,只要有一个分支执行,整个if语句全部结束。

    • 所有控制语句都是可以嵌套使用,但是嵌套要合理。嵌套时一定要注意缩进。

    • IF语句的分支只有一条语句时,大括号可以省略不写。(不推荐这种方式,但是别人这样写要可以看懂)

      if(表达式)
      	语句;
      
      
      if(表达式)
      	语句;
      else
      	语句;
      
    • 悬空else:如果没有加{},else与离自己最近的那个if配对

      //这段程序什么都不打印。因为else与离自己最近的那个if配对,因为a!=1,所以程序直接结束
      #include <stdio.h>
      int main()
      {
          int a = 0;
          int b = 0;
          if(a == 1)
              if(b == 2)
                  printf("hahaha");
          else
              printf("hehehehe");
          
          //实际会被解析为
          if(a == 1)
              if(b == 2)
                  printf("hahaha");
          	else
              	printf("hehehehe");
          return 0;
      }
      
      
      

      改正

      #include <stdio.h>
      int main()
      {
          int a = 0;
          int b = 0;
          if(a == 1)
          {
              if(b == 2)
              {
                  printf("hahaha");
              }
          }
          else
          {
              printf("hehehehe");
          }
          return 0;
      }
      
  • 练习

    /*
     * 假设系统给定;一个考生的成绩,成绩可能带有小数点,学生成绩范围在[0-100]
     * 根据学生的成绩判断该学生的成绩等级
     * [90-100]A  、  [80-90) B  、 [70-80) C  、 [60-70) D  、 [0-60) E
     */
    #include <stdio.h>
    
    int main()
    {
        double score = 61;
        if(score>100 || score<0)
        {
            printf("该考生成绩不合法,请确认后重新输入");
        }
        else if(score >= 90)
        {
            printf("该考生成绩等级为:A");
        }
        else if(score >= 80)
        {
            printf("该考生成绩等级为:B");
        }
        else if(score >= 70)
        {
            printf("该考生成绩等级为:C");
        }
        else if(score >= 60)
        {
            printf("该考生成绩等级为:D");
        }
        else
        {
            printf("该考生挂科!");
        }
        return 0;
    }
    

switch语句

  • switch语句的语法结构

    switch语句也属于选择结构,也是分支语句

    /*
    	switch语句可以看作是一种基于计算的跳转,根据整型表达式的值,跳转到相匹配到case处。
    	在匹配了case,执行了其中的语句之后,如果没有break; 就会顺序执行下面的case中的语句。
    	直到遇到break; ,或switch结束。
    */
    /*
    	switch()中的表达式,要是整形的,如n或n+1
    	case 后面跟的是常量或常量表达式,如1或1+3
    */
    switch(整型表达式){
    	case 常量/常量表达式:
    		语句;
        case 常量/常量表达式:
    		语句;
        case 常量/常量表达式:
    		语句;
        ....
        default 常量/常量表达式:
    		语句;	
    }
    
  • switch语句执行原理

    switch()中的数据,与case后面的数据 ,按照自上而下的顺序,依次匹配。匹配成功的分支执行。

  • switch分支中,default字句可以放在任意位置,不是必须在case字句之后。

  • 匹配成功的分支执行

    • 分支中如果有break;语句,则这个分支执行后整个switch语句终止。

    • 分支中如果没有break;语句,则会直接进入下一个分支执行。直到遇到break; ,或switch语句结束。

      这种现象被称为“case穿透”现象

  • 所有分支都没有匹配成功,当有default: 语句时,会执行default分支中的语句

  • case合并

    #include <stdio.h>
    int main()
    {
        int day = 0;
        scanf("%d",&day);
        switch (day)
        {
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                printf("工作日");
                break;
            case 6:
            case 7:
                printf("休息日");
                break;
        }
        return 0;
    }
    
  • 练习

    #include <stdio.h>
    
    int main()
    {
        int n = 1;
        int m = 2;
        switch (n)
        {
            case 1:
                m++;
            case 2:
                n++;
            case 3:
                switch (n) //switch嵌套使用
                {
                    case 1:
                        n++;
                    case 2:
                        m++;
                        n++;
                        break;
                }
            case 4:
                m++;
                break;
            default:
                break;
        }
        printf("m=%d , n=%d",m,n);//m=5 , n=3
        return 0;
    }
    

    2

    /*
    需求:
     假设系统给定;一个考生的成绩,成绩可能带有小数点,学生成绩范围在[0-100]
    根据学生的成绩判断该学生的成绩等级,成绩可能带有小数
        [90-100]A
        [80-90) B
        [70-80) C
        [60-70) D
        [0-60)  E
    
      以上的逻辑判断采用switch语句完成,不考虑[0,100]以外的
     */
    #include <stdio.h>
    
    int main()
    {
        float grade = 0;
        scanf("%f",&grade);
        switch ((int)grade/10) {
            case 9:
            case 10:
                printf("该考生成绩等级为:A");
                break;
            case 8:
                printf("该考生成绩等级为:B");
                break;
            case 7:
                printf("该考生成绩等级为:C");
                break;
            case 6:
                printf("该考生成绩等级为:D");
                break;
            default:
                printf("该考生成绩等级为:E");
                break;
        }
        return 0 ;
    }
    

循环语句

while循环

  • while循环结构

    while(布尔表达式){
        循环体;
    }
    
  • 执行原理

    • while循环的循环体可能的执行次数为0,也可能执行n次。
    先判断表达式的结果:
    	*非0
    		-执行循环体
    			*判断表达式的结果:
    				*非0
    					-执行循环体
    						*判断表达式结果
    							*非0
    								—执行循环体
    									*判断表达式结果:
    										·······
    							*0
    								—循环结束
    				*0
    					-循环结束
    	*0
    		-循环结束
    
  • getchar()方法的使用

    /*
     *  int getchar(void)函数 —— 作用:输入一个字符。通常用于接收空格/换行符
     *  返回值:该函数以无符号char强制类型转换为int的形式返回读取的字符,如果达到文件末尾或发生错误,则会返回(-1)EOF
     *         返回字符对应的ASCII码
     *
     *  int putchar(int char) —— 作用:输出一个字符。char是要输出的参数。
     *  返回值:该函数以无符号char强制转换为int的形式返回写入的字符,如果发生错误则会返回(-1)EOF
     *         参照ASCII表,将char对应的字符返回。
     *
     *注意:
     *  - 当程序调用getchar()时,等待用户按键,用户输入的字符被存放在键盘缓冲器中,直到用户按回车为止(这个回车字符也存放在缓冲区中)。
     *    用户键入回车之后,getchar才开始从stdin流中每次读入一个字符。
     *  - getchar()函数不仅可以从输入设备获取一个可显示的字符,而且可以获得屏幕上无法显示的字符,如:回车换行/空格等
     *  - getchar()函数的返回值是:用户输入的字符的ASCII码,若文件结尾则返回-1(EOF),且将用户输入的字符回显到屏幕
     *  - 如果用户在按回车之前输入了不止一个字符,其他字符也会保留在键盘缓冲区中,等待后续getchar()调用读取
     *    也就是说:后续的getchar调用不会等待用户按键,而是直接读取缓冲区中的字符,直到缓冲区中的字符读取完之后,才等待用户按键
     *
     *主要用法:
     *  - 清空回车符,这种情况一般发生在寻魂中涉及到输入的情况。
     *  - 某些编译平台(IDE)在运行程序时,并没有在程序程序运行后给别人看结果的时间。这时在程序最后加上getchar(),就可以造成程序的暂停。
     *  - 使用getchar();时,输入完字符,要按回车才能读取进去
     *    使用getch();时,在键盘上按一个字符马上就被读取进去,不用按回车,因此可以作为“按任意键继续”的执行语句。
     */
    
    /*
     * - getch()函数
     *   getch与getchar基本功能相同,差别是:getch直接从键盘获取键值,不等待用户按回车,只要用户按一个键,getch就立刻返回
     *   getch返回值是用户输入的字符的ASCII码,出错返回-1。
     *   - 输入的字符不会会现在屏幕上。getch函数常用于程序调试中。在调试时,在关键位置显示有关的结果以待查看。
     *     然后用getch函数暂停函数运行,当按任意键后程序继续运行。
     *   - getch()是非缓冲输入函数,就是不能用getch()来接收缓冲区已存在的字符。
     *
     * - getche()函数
     *   这个函数与前两上类似,功能也相近,都是输入一个字符,返回值同样是输入字符的ASCII码。
     *   但不同的是,此函数在输入后立即从控制台取字符,不以回车为结束(带回显)。
     *
     */
    #include <stdio.h>
    
    int main()
    {
        int ch = 0;
        /*
         * - 虽然getchar()是用于输入一个字符。
         *   但如果用户在按回车之前输入了不止一个字符,其他字符也会保留在键盘缓冲区中,等待后续getchar()调用读取。
         *   也就是说:后续的getchar调用不会等待用户按键,而是直接读取缓冲区中的字符,直到缓冲区中的字符读取完之后,才等待用户按键
         *
         * 程序运行后,等待键盘输入。输入一串字符后,循环读取这串字符,按顺序输出。
         * 如输入abc并回车,实际输入:abc\n
         * 则会输出  97——a----     98——b----     99——c----     10——
                    ----
         * 这里10——后面换行才输出了----,就说明了:\n也被存储到了缓冲区中,其对应的ASCII码是:10。
         *
         */
        while ((ch=getchar()) != EOF)
        {
            //getchar()函数的返回值是其字符对应的ASCII码
            printf("%d——",ch);
    
            //putchar()函数的返回值是其传入变量对应的字符。
            putchar(ch);
            printf("----\t");
        }
    }
    

    统计从键盘输入的一行字符的个数

    //统计从键盘输入的一行字符的个数
    int main()
    {
        int n=0;
        printf("请输入一串字符:");
        //getchar()不为\n,就表示你输入了多少个字符,就循环多少次。
        //当getchar()读取到缓冲区中的\n,说明读取完了,此时就结束循环。
        while(getchar() != '\n')
        {
            n++;
        }
        printf("你输入了%d个字符\n",n);
        return 0;
    }
    

    缓冲区详解

    /*
     * 键入缓冲区——所有从键盘输入的数据,不管是字符还是数字,都是先存储在内存的缓存区,叫做"键盘输入缓冲区",简称"输入缓冲区"或"输入流"
     * 当我们调用的函数需要我们用键盘输入时,我们输入的数据都会被依次存入缓冲区。
     * - 但是只有当按下回车之后,scanf函数才会进入缓冲区取数据,所取数据的个数取决于scanf的"输入参数"的个数。
     *   所以不在于怎么输入。可以存一个取一个,也可以一次性全部存进去,然后一个一个取。
     *
     * 使用%d 和 %c  读取缓存的差别:
     * - 对于%d,在缓冲区中,空格、回车、tab键都只是分隔符,不会被sacnf当成数据使用。%d碰见他们就跳过,取下一个数据。
     *   遇到字符,会直接退出,不再取其中的数据,就算还有变量也不会再取,而是直接为没有取到数据的变量赋值为0.
     * - 对于%c,空格、回车、tab键都会被当成数据输出给scanf取用。
     * - %s,也是只会取出数据。不会取空格、回车、tab键
     */
    
    
    /*
     * 运行程序运行,我们输入:123456回车,却直接弹出了请确认密码(Y/N):确认失败。
     * 原因:我们输入的数据存储到缓冲区中是:123456\n  (\n是我们的回车,也会存储到缓存区中)
     * - scnaf函数执行,用%s读取缓存区,只会取数据123456,把\n剩在了缓存区中。
     * - 接下来调用getchar()获取我们键盘输入时,因为缓存区中还有数据,会先将其中的数据读取完之后才会等待用户继续输入。
     *   这里的\n被getchar()获取走了,赋给了ch变量,而'\n'!='Y',所以没有等待我们输入,直接输出了“确认失败”
     */
    
    //#include <stdio.h>
    //int main()
    //{
    //    //定义字符数组,长度为20   初始化其中所有元素为0
    //    char password[20] = {0};
    //    printf("请输入密码:");
    //    //%s表示输入一个字符串
    //    scanf("%s",password);
    //    printf("请确认密码(Y/N):");
    //    int ch = getchar();
    //    if(ch == 'Y')
    //    {
    //        printf("确认成功\n");
    //    }
    //    else
    //    {
    //        printf("确认失败\n");
    //    }
    //    return 0;
    //}
    
    /*
     * - 解决方法:
     *   在int ch = getchar();语句前加上一个getchar();,用来取走缓冲区中的'\n'
     *   然后等到执行int ch = getchar();时,就是等待我们输入Y/N了。
     * - 注意:
     *   我们使用getchar()取走了缓存区中的‘\n’。但是int ch = getchar();语句执行,也需要回车才会进去取这个字符
     *   这时需要注意的是:与scanf函数取数据一样,getchar()函数取数据之后,也会把其产生的\n遗留在缓冲区中
     */
    
    //#include <stdio.h>
    //int main()
    //{
    //    char password[20] = {0};
    //    printf("请输入密码:");
    //    scanf("%s",password);
    //    printf("请确认密码(Y/N):");
    //    //在%c取字符之前,使用getchar()吸收遗留的\n
    //    getchar();
    //    int ch = getchar();
    //    if(ch == 'Y')
    //    {
    //        printf("确认成功\n");
    //    }
    //    else
    //    {
    //        printf("确认失败\n");
    //    }
    //    return 0;
    //}
    
    /*
     * !思考:如果有多个scanf给int型变量赋值,那么每个scanf都会遗留一个回车,那么这时候是不是有几个scanf就需要几个getchar()呢?
     * - 不需要,仍然只需要一个getchar()就可以。
     *   当scanf用%d或%s取缓冲区数据的时候,如果遇到空格、回车、tab键,会跳过去。这里的跳过是指:释放掉了。
     *   也就是说,scanf用%d或%s取缓冲区数据,碰到空格、回车、tab键,就会释放掉,不会再存在于缓存区中。
     * - 所以加入有三个scanf给int型变量赋值,那么第一个把\n留在了缓冲区,第二个scanf取值时会释放掉第一个scanf遗留的回车。
     *   第三个scanf取值时,会释放掉第二个scanf遗留的回车。而第三个遗留的回车,我们用一个getchar()就可以释放掉。
     *   也就是说:混充去中永远不可能遗留多个回车。
     *
     * 结论:
     * 当我们输入一串数据:有字符、数字、空格
     * - scanf用%d获取其中的数据,只会取其中的数字。
     *   如果遇到其中的空格、回车、tab键,则会将其当成分隔符。
     *   如果遇到其中的字符,则会直接退出,不再取数据。
     * - scanf用%c取数据
     *   任何数据都被当成一个字符。
     * - 所以如果要从输入流中取一个字符,但是在之前我们使用过scanf,那么此时就必须先使用getchar()吸收回车。
     *   否则取到的就不是我们需要的字符了,而是scanf遗留在输入流中的回车。
     * - 如果你要从输入流中取的不是字符,就不需要getchar()吸收回车了。
     * - 但是在实际编程中,程序往往很长。我们很难预测到下一次到缓存区中取数据是%d、%c、gets()或是fgets()
     *   所以为了避免忘记吸收回车,习惯上scanf后面都加上getchar()。
     */
    
    /*  - 运行程序,输入数据:123a456
     *    scanf以%d取数据,取到a发现如果输入的是字符,则会直接退出,不取数据。
     *    a被赋值123,而b、c没有取下值,则会赋值为0
     *  - 剩下的一串数据(a456以及scanf遗留的'\n')仍然会存储在缓存区中。
     *    这时剩下的数据以5个getchar()进行回收
     */
    
    //#include <stdio.h>
    //int main()
    //{
    //    int a = 0;
    //    int b = 0;
    //    int c = 0;
    //    scanf("%d %d %d",&a,&b,&c);
    //    printf("%d %d %d\n",a,b,c);
    //    int ch = 0;
    //    while ((ch=getchar()) != EOF)
    //    {
    //        printf("%d——",ch);
    //        putchar(ch);
    //        printf("----\t");
    //    }
    //    return 0;
    //}
    
    /*
     * fflush(stdin)方法
     * - 前面介绍了使用 getchar() 吸收回车的方法,而fflush()方法,作用就是直接将输入缓冲区全部清空。
     * - 清空缓冲区只需加一句 fflush(stdin) 即可。fflush 是包含在文件 stdio.h 中的函数。stdin 是“标准输入”的意思。
     *   std 即 standard(标准),in 即 input(输入),合起来就是标准输入。fflush(stdin) 的功能是:清空输入缓冲区。
     *
     *   fflush 一般用于清除用户前面遗留的垃圾数据,提高代码的健壮性。因为如果是自己编程的话,一般都会按要求输入。
     *   但对于用户而言,难免会有一些误操作,多输入了一些其他没有用的字符,如果程序中不对此进行处理的话可能会导致程序瘫痪。
     *   所以编程时一定要考虑到各种情况,提高代码的健壮性和容错性。使用 fflush() 就可以将用户输入的垃圾数据全部清除。
     */
    //#include <stdio.h>
    //int main()
    //{
    //    int a = 0;
    //    printf("请输入一串字符和数字(请以数字开头):");
    //    scanf("%d",&a);
    //    printf("您输入的字符中,已存储的有效数字为:%d\n",a);
    //    fflush(stdin);
    //    printf("已经调用ffluh方法清空缓存区,请输入一个字符:");
    //    int ch = getchar();
    //    printf("%c",ch);
    //
    //    return 0;
    //}
    
    /*
     * - getchar()的高级用法 ———— while (getchar() != '\n');
     *   它可以完全代替 fflush(stdion) 来清空缓冲区。不管用户输入多少个没用的字符,他最后都得按回车,而且只能按一次。
     *   只要他按了回车那么回车之前的字符就都会被 getchar() 取出来。只要 getchar() 取出来的不是回车('\n') 那么就会一直取,直到将用户输入的垃圾字符全部取完为止。
     *
     * - while (getchar() != '\n');语句执行
     *   循环执行getchar语句,会依次读取缓冲区的字符,这样所有缓冲区的字符都读入程序并依次被getchar()给吸收了,条件成立,执行空语句; 然后一直循环。
     *   直到读取了缓冲区中的'\n'后,条件不成立,循环终止。虽然条件不成立,但是getchar()函数已经调用了,已经取走了其中'\n',这样就达到了清空缓冲区的效果。
     *
    
     */
    
    //#include <stdio.h>
    //int main()
    //{
    //    int a = 0;
    //    printf("请输入一串字符和数字(请以数字开头):");
    //    scanf("%d",&a);
    //    printf("您输入的字符中,已存储的有效数字为:%d\n",a);
    //    while (getchar() != '\n');
    //    printf("高级运用getchar() 清空缓存区,请输入一个字符:");
    //    int ch = getchar();
    //    printf("%c",ch);
    //    return 0;
    //}
    

do…while循环

  • do…while循环的语法结构

    do
    {
    	循环体;
    }while(表达式);
    
  • do…while循环的执行原理

    循环体执行的次数:1~N次,至少执行一次。

    注意do…while循环语句结尾有一个 ;

    先执行循环体
        *判断表达式的结果:
            *非0
                -执行循环体
                    *判断表达式的结果:
                        ·······
            *0
                -循环结束
    

for循环

  • for循环的语法结构

    for(表达式1;表达式2;表达式3)
    {
    	语句块;
    }
    
  • for循环的执行原理

    • 表达式1、2、3都不是必须的,但是两个分号是必须写的

    • 初始化表达式最先执行,并且在整个for循环中只执行一次

    • 执行过程

      先执行表达式1(初始化表达式),并且该表达式只执行一次
      执行表达式2,判断表达式结果是真还是假(0为假,非0为真)
      - 结果为真
        - 执行循环体
        - 执行表达式3(更新表达式)
        - 执行表达式2,判断表达式结果是真还是假(0为假,非0为真)
      	- 结果为真
      	  - 执行循环体
      	  - 执行表达式3(更新表达式)
      	  - 执行表达式2,判断表达式结果是真还是假(0为假,非0为真)
      	    - 结果为真
      	      - 执行循环体
      		  - 执行表达式3(更新表达式)
      	      - 执行表达式2,判断表达式结果是真还是假(0为假,非0为真)
          	    ......
      	    - 结果为假
      		   循环结束
      	    - 结果为假
      	      循环结束
      - 结果为假
        循环结束
      
  • 三个表达式

    /* 
     * 表达式1一般是:初始化语句  
     * 表达式2一般是:关系表达式,决定是否还要继续下次循环,称为“循环条件”。
     * 表达式3一般是:更新表达式(自增或自减)
     */
    
    • 省略表达式1,在外部初始化。

      结论:一般不要省略更新表达式。特别是嵌套循环时,尤其是内层循环的变量初始化。

      /*
       * 在外部定义好变量之后,省略其初始化表达式。
       * 以下程序我们在其中嵌套了一个for循环。程序运行,只打印了3个“haha”
       * 原因:
       *   - 因为i和j是在循环外部定义的,而在循环时也省略了初始化。说明i和j的作用域是在整个main方法中
       *     程序执行,i=0<3,外层循环成立,执行其内层循环,内层循环打印3次后之后,j变成了3,不再<3,执行i++
       *     i=1<3,外层循环成立,执行内层循环,因为没有初始化变量,而j=3,循环条件不成立,所以不打印,内层循环不再执行。i=2时也是如此。
       *   - 所以一般不要省略更新表达式。特别是嵌套循环时,尤其是内层循环的变量初始化。
       *
       */
      #include <stdio.h>
      
      int main()
      {
          int i = 0;
          int j = 0;
          for(;i < 3 ;i++){
              for (; j <3 ; j++) {
                  printf("haha\n");
              }
          }
          printf("%d\n",i);//3
          printf("%d\n",j);//3
          return 0;
      }
      
    • 省略表达式2,如果不做其他处理,程序就会成为死循环

      for(i = 0;;i++)
      {
      	sum=sum+i;
      }
      
    • 省略表达式3,可以在循环中修改变量的值

      for(i=0;i<100;)
      {
          //i++    //写这里也行
      	printf("haha");
          i++
      }
      
    • 三个表达式可以同时省略

      for(;;)
      {
          printf("我是一个死循环\n");
      }
      
    • 表达式1和表达式3,也可以是一个逗号表达式。此时就可以使用多个变量控制循环。

      #include <stdio.h>
      
      int main()
      {
          int x,y;
          //输出两个hehe
          //逗号表达式:从左向右依次执行,只返回最后一个表达式的结果。而表达式1只执行一次,表达式3只要执行,并不需要返回,所以可以直接使用。
          //而如果是要使用都好表达式作为表达式2使用,那么就需要注意其中最后一个表达式的结果,以免造成 循环不执行/死循环。
          for(x=0,y=0;x<2 && y<5;++x,y++){
              printf("hehe\n");
          }
          return 0 ;
      }
      
    • 笔试题

      /*
       * 此循环一次都不执行。
       * 原因:
       *   - 程序运行,执行表达式1之后,执行表达式2。
       *   - 我们用%d的方式打印k=0,发现表达式2的结果是0
       *     条件不成立,循环不执行。
       */
      #include <stdio.h>
      int main()
      {
          int i = 0;
          int k = 0;
      
          for(i=0,k=0;k=0;i++,k++)
          {
              k++;
          }
          printf("%d",k=0);//0
      }
      
    • 表达式2一般是关系表达式或逻辑表达式,但也可以是数值或字符,只要其值是非0,就执行循环体

      for( i=0; (c=getchar())!='\n'; i+=c );
      

      for( ; (c=getchar())!='\n' ; )
      {
          printf("%c",c);
      }
      

循环语句的练习

  1. 计算n的阶乘

    #include <stdio.h>
    
    int main()
    {
        printf("请输入要进行阶乘的数:");
        int i = 0;
        int fac = 1;
        int j = 0;
        scanf("%d",&j);
        for (i=1; i <= j; i++)
        {
            fac *= i;
        }
        printf("%d的阶乘为:%d\n",j,fac);
        return 0;
    }
    
  2. 计算 1~n的阶乘和

    //计算1~n的阶乘和
    #include <stdio.h>
    
    int main()
    {
        printf("1~n的阶乘和,请输入n:");
        int i = 0;
        int j = 0;
        int n =0;
        int fac = 1;
        int sum =0;
        scanf("%d",&n);
        //外层
        for(i = 1;i <= n;i++,fac=1)
        {
            for(j = 1; j <= i; j++)
            {
                fac *= j;
                //每个数的阶乘。
            }
            sum += fac;//阶乘和
            //fac = 1;  //加上之后,重置阶乘和 // 或写在阶乘的外层循环的更新表达式中:表示外层每循环一次,fac都重置为1。
        }
        printf("1~%d的阶乘和为:%d\n",n,sum);
        return 0;
    }
    
    
    
    //更精简的方法:
    #include <stdio.h>
    int main()
    {
        printf("1~n的阶乘和,请输入n:");
        int i = 0;
        int n =0;
        int fac = 1;
        int sum =0;
        scanf("%d",&n);
        /*
         * 如数字5的阶乘
         * 第一次——1*1,也就是1的阶乘;第二次——1*2,是2的阶乘;第三次——2!*3,是3的阶乘
         * 第四次——3!*4,是4的阶乘,第五次——4!*5,也就是5的继承
         * 所以我们只需要在每次乘完之后,把他们加在一起,就是1~n的阶乘和
         */
        for(i = 1;i <= n;i++)
        {
                fac *= i;
                sum += fac;//阶乘和
            }
        printf("1~%d的阶乘和为:%d\n",n,sum);
        return 0;
    }
    
  3. 二分法查找

    /*
     * 二分法查找:
     *   - 建立在排序的基础上
     *   - 二分法查找效率高于”一个挨着一个“的这种查找方式
     *   - 二分法原理。如:需要找到数组中,元素600的下标 10 15 56 89 110 188 222 333 444 600
     *      1. 计算出中间元素下标
     *         (0+9)/2 ————————————> 中间元素下标为:4
     *      2. arr[4] = 110 <600
     *         说明被查找的元素在100的右边,那么此时的开始下标就变成了4+1
     *         (5+9)/2 ————————————> 中间元素下标为:7
     *      3. arr[7] = 333 <600
     *         说明被查找的元素在333的右边,那么此时的开始下标就变成了7+1
     *      4. arr[8] = 444 <600
     *         说明被查找的元素在333的右边,那么此时的开始下标就变成了8+1
     *         (9+9)/2 ————————————> 中间元素下标为:9
     *      5. arr[9] = 600 = 600 。此时返回该元素下标。
     *
     *      如果找出的这个元素下标对应的元素,大于我们要查找的元素,则中间元素下标作为终止下标,起始下标不变。
     *
     *  查找一个不存在的数时是什么情况?
     *  - 如查找33
     *    1. 计算出中间元素下标
     *         (0+9)/2 ————————————> 中间元素下标为:4
     *    2. arr[4] = 110 > 33
     *       说明被查找的元素在100的左边,那么此时的结束下标:4-1
     *       (0+3)/2 ————————————> 中间元素下标为:1
     *    3. arr[1] = 15 < 33
     *       说明被查找的元素在15的右边,那么此时的开始下标:1+1
     *       (2+3)/2 ————————————> 中间元素下标为:2
     *    3. arr[2] = 56 >33
     *       说明被查找的元素在56的左边,那么此时的结束下标:2-1
     *    4. 此时,开始下标:2,结束下标:1
     *       开始下标在结束下标的右边了,所以此时,这个数是不存在的。
     *
     *    结论:
     *    - 当begin <= end时,存在我们要查找的数
     *    - 当begin > end时, 就输出:这个数不存在。
     *
     */
    #include <stdio.h>
    
    int main()
    {
        int arr[] = {10,15,56,89,110,188,222,333,444,600};
        int num = 222; //要查找的数字
        //起始元素下标
        int begin = 0;
        //终止元素下标。数组总长度/一个元素的长度:数组元素个数。数组中最后一个元素的下标:数组元素个数-1。
        int end = sizeof(arr)/sizeof(int) -1;
    
        //使用二分法。循环条件:起始元素下标 只要一直在 终止元素下标 的左边,就一直循环。
        while(begin <= end) {
            //中间元素下标
            int mid = (begin + end) / 2;
    
            if (arr[mid] == num) {
                //查找到之后,输出该元素下标并退出
                printf("该元素下标为:%d\n", mid);
                break;
            }
            else if (arr[mid] < num)
            {//如果中间下标对应的元素,小于我们要查找的数。说明还要继续向右查找。arr[mid] < num
                //起始坐标就变为中间坐标+1。
                begin = mid + 1;
            }
            else
            {//如果中间元素下标对应的元素,大于我们要查找的数。说明要向左查找。arr[mid] > num
                //结束坐标就变为中间坐标-1
                end = mid - 1;
            }
        }
        //如果循环没有结果,也就是说并没有这个数字。则出现的情况就是:begin>end,此时我门输出:
        if(begin > end)
        {
            printf("起始:%d\n",begin);
            printf("结束:%d\n",end);
            printf("该数组中没有这个数");
        }
        return 0 ;
    }
    
  4. 多个字符从两端向中间汇聚

    //演示多个字符从两端向中间移动
    #include <string.h>
    #include <stdio.h>
    #include <synchapi.h>
    
    int main()
    {
        //准备两个数组,一个存放我们的字符串,一个是相同长度空格字符串
        char arr1[] ="hello world!";
        char arr2[] ="            ";
        int left = 0;
        //最右边的字符下标:字符串长度-1//求一下字符串的长度,使用函数strlen。不计算结束标志\0,只计算字符串长度。
        int right = strlen(arr1) -1;
        //在这个字符数组中,还存储了\n,sizeof(arr1)是计算数组的长度,size(char)是计算每个char所占的长度。
        //int rights = sizeof(arr2)/sizeof(char) ;//所以这个结果最后算出来是数组内元素的个数,而不是字符串长度。
    
        while(left <= right)
        {
            //循环:每次将arr1中未打印出来的的首尾两个元素赋给arr2中对应的下标。
            arr2[left] = arr1[left];
            arr2[right] = arr1[right];
            //打印arr2
            printf("%s\n",arr2);
            //打印完停顿1秒,单位:毫秒
            Sleep(500);
            //打印之后清空屏幕
            system("cls");
            //左加,右减——》向中间汇聚。左下标向右移动,右下标向左移动
            left++;
            right--;
        }
        return 0;
    }
    
    
    //for循环形式
    #include <string.h>
    #include <stdio.h>
    #include <synchapi.h>
    
    int main()
    {
        char arr1[] ="Hello World! Day Day Study C >>>> Lei Die L";
        char arr2[] ="                                          ";
        int left,right;
        for(left = 0 , right = strlen(arr1) -1;left <= right; left++,right--)
        {
            arr2[left] = arr1[left];
            arr2[right] = arr1[right];
            //打印arr2
            printf("%s\n",arr2);
            //打印完停顿1秒,单位:毫秒
            Sleep(500);
            //打印之后清空屏幕
            system("cls");
        }
    
        return 0;
    }
    
  5. 模拟用户登录,如果用户三次输入密码错误,则退出程序。如果密码正确则提示登录成功。

    /*
     * strcmp()函数
     * - 用于对两个字符串进行比较
     * - 语法: int strcmp(const char* str1 , const char* str2);
     *   参数str1与参数str2是参与比较的两个字符串
     * - strcmp()会根据ASCII编码依次比较str1和str2中的每一个字符,直到出现不到的字符,或者达到字符串末尾(遇到\0)
     * - 返回值:
     *     ——如果返回值 < 0 ,则表示str1 < str2
     *     ——如果返回值 > 0 ,则表示str1 > str2
     *     ——如果返回值 = 0 ,则表示str1 = str2
     */
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        int i = 0;
    
        //假设正确的密码是字符串”123456“
        char password[20] = {0};
    
        for(i=0 ; i < 3 ;i++)
        {
            printf("请输入密码:");
            scanf("%s",password);
            //字符串的比较,使用strcmp()函数
            if(strcmp(password,"123456") == 0)
            {
                printf("登陆成功!\n");
                break;
            }
            else
            {
                if (i < 2)
                    printf("密码错误,请重新输入\n");
            }
        }
        if(i == 3)
        {
            printf("密码错误3次,程序退出!");
        }
        return 0;
    }
    
  6. 随机数rand()、srand()、tim()函数详解

    /*
     * int rand(void); 随机数函数 ,void表示不需要传递参数
     * - rand()函数会生成一个位于0~RAND_MAX之间的整数。stdlib头文件中有宏 #define RAND_MAX 0x7fff,也就是说rand产生一个0~0x7fff的随机数,即最大是32767的一个数。
     *   但C语言标准并没有规定 RAND_MAX 的具体数值,只是规定它的值至少为 32767。在实际编程中,我们也不需要知道 RAND_MAX 的具体值,把它当做一个很大的数来对待即可。
     *
     * - rand函数的调用
     *   rand()函数每次调用都会查询是否调用过srand(seed),是否给seed设定了一个值,如果有,那么会自动调用srand(seed)一次来初始化他的起始值
     *   若之前没有调用srand(seed),那么系统会自动给seed赋初始值,即自动调用srand(1)一次。
     *
     * 随机数的本质:
     * - rand()函数产生的随机数是伪随机数,是根据一个数值按照某个公式推算出来的,这个数值我们称之为种子。
     *   也就是说,只要种子相同,那么产生的随机数就是固定的一串数。这时就需要使用srand()函数来重新播种。
     *
     * time()函数
     *   函数原型: time_t time(time_t *timer)
     *   参数说明: timer=NULL时得到当前日历时间(从1970-01-01 00:00:00到现在的秒数),time_t是一个long long类型。
     *            timer=时间数值时,用于设置日历时间,如果 timer不为空,则返回值也存储在变量 timer中。
     *   函数功能: 得到当前日历时间或者设置日历时间。函数返回: 当前日历时间
     *   alt+鼠标左键点击time_t,发现time函数的返回值类型实际上是:time_t ——> __time64_t ——> __int64 ——> long long
     *   time()函数的两种使用方式:
     *   - time1 = time(NULL)或time1 = time(0) 。表示不以参数的方式获取返回值
     *     将空指针传递给time()函数,并将time()返回值赋给变量time1
     *   - time(&time2)   ,以参数的方式获得返回值
     *     将变量time2的地址作为参数传递给time()函数,函数将返回值传递给time2,不需要额外的赋值语句
     *
     * srand()函数
     *   void srand(unsigned int seed);   srand函数是随机数发生器的初始化函数
     *   - srand()需要一个unsigned int类型的参数。实际开发中,我们可以使用时间作为参数。每次播种的时间不同,那么种子就不同,最终生成的随机数一定就是随机的。
     *     使用time()函数来获取系统时间,得到的时间是一个时间戳,即从1970年1月1日00:00:00到现在时间的秒数,然后得到的time_t类型数据。
     *     因为srand()需要传递的是一个unsigned int类型的数,所以要进行强制类型转换
     *     - srand((unsigned int)time(Null))  或  srand((unsigned int)time(0))
     *     - 多次运行程序,发现虽然数随机了。但是这些随机数会有逐渐增大/减小的趋势,这是因为我们以时间为种子,时间是逐渐增大的。
     *       为了使随机数间隔变大,可以在stand中传递的数乘上一个合适的整数。如:
     *       srand((unsigned int)time(Null)*10)
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int main()
    {
        int i = 0;
        //使用时间戳初始化种子,*5增大时间间隔
        srand((unsigned int)time(NULL) *5);
        while (i < 6)
        {
            //循环获取随机数
            int r = rand();
            //输出
            printf("%d\n",r);
            i++;
        }
        return 0;
    }
    
  7. 猜数字游戏。

    /*  取一定范围内的随机数
     *  取到100之间的随机数:用随机数%100+1,随机数%100,得到余数0~99。再加1,就是1~100。
     *  如果是取1~50之间的随机数,就是随机数%50+1,随机数%50,得到余数0~49。再加1,就是1~50 —— rand()%50+1。
     *  int num = rand()%100+1;
     */
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    void menu()
    {
        printf("——————————猜数字游戏———————————\n");
        printf("—————————输入1开始游戏—————————\n");
        printf("—————————输入0退出游戏—————————\n");
        printf("—————————···········—————————\n");
        printf("请选择:");
    }
    
    void game() {
        int r_num = rand()%100+1;
        int n = 0;
        while (1)
        {
            printf("请输入猜测的数字:");
            scanf("%d",&n);
            if(n > r_num)
            {
                printf("猜大了\n");
            }
            else if(n < r_num)
            {
                printf("猜小了\n");
            }
            else
            {
                printf("恭喜你,猜对了\n");
                break;
            }
        }
    }
    
    int main()
    {
        //输入的数字
        int input = 0;
        //使用时间戳初始化种子,并加大时间间隔
        srand((unsigned int) time(NULL)*5);
        do
        {
            //调用menu()函数打印菜单
            menu();
            scanf("%d",&input);
            if(input != 0)
            {
                game();
            }
        }while(input);
        return 0;
    }
    
  8. 三个整数从大到小输出

    #include <stdio.h>
    
    int main()
    {
        int a,b,c ;
        int mid = 0;
        //输入
        printf("请输入三个数:");
        scanf("%d %d %d",&a,&b,&c);
        //如果a比b小,那么a与b交换
        if(a < b){
            mid =a;
            a = b;
            b = mid;
        }
        //以上执行,则a>b。
        //如果a比c小,那么a与c交换
        if(a < c)
        {
            mid = a;
            a = c;
            c = mid;
        }
        //执行到这里,a>b并且a>c
        //如果b<c,那么b与c交换
        if(b < c)
        {
            mid = b;
            b = c;
            c = mid;
        }
        //此时a>b>c
        printf("三个数从大到小:%d %d %d",a,b,c);
    }
    
  9. 求两个数的最大公约数

    如果是求最小公倍数:最小公倍数 = m*n/最大公约数

    #include <stdio.h>
    
    int main()
    {
        int m,n;
        printf("请输入要求最大公约数的两个数字:");
        scanf("%d %d",&m,&n);
        //思路:以两个数中比较小的那个数作为除数,每次-1,直到比较大的那个数可以整除这个数。
        int i = m>n?n:m;
        while (i> 0)
        {
            if( m%i==0 && n%i==0)
            {
                printf("%d",i);
                break;
            }
            i--;
        }
        return 0;
    }
    
    /*
     * 辗转相除法
     * - 如两个数:24 18求最大公约数
     *   24%18=6   再用18%6=0,6就是24和18的最大公约数
     * - 再如:17和13
     *   17%13=4    再用13%4=1  再用4%1=0  ,1就是17和13的最大公约数
     */
    int main()
    {
        int m , n;
        int mid = 0;
        printf("输入要求最大公约数的连个数字:");
        scanf("%d %d",&m,&n);
        /*
         * 这里如果m<n 呢?
         * 例如:4和9,就是:4%9 =0···4,然后9%4=2···1
         * 所以这里我们可以不做操作,只是程序多循环一次而已。
         */
        while(mid = m%n)
        {
            m = n;
            n = mid;
        }
        printf("这两个数的最大公约数是:%d\n",n);
        return 0;
    }
    
  10. 最小公倍数

    最小公倍数:两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就叫做这几个整数的最小公倍数。

    //穷举法
    #include <stdio.h>
    
    int main()
    {
        int a = 0;
        int b = 0;
        scanf("%d %d",&a,&b);
        //将两个数中较大的那个数作为公倍数
        int m = a>b?a:b;  //表示最小公倍数
        do
        {
            //如果m可以同时整除a与b,则m是他们的最小公倍数
            if(m%a == 0 && m%b == 0)
            {
                printf("%d\n",m);
                break;
            }
        }while(m++);
        return 0;
    }
    

    扩大法

    #include <stdio.h>
    
    int main()
    {
        int a = 0;
        int b = 0;
        scanf("%d %d",&a,&b);
        int i = 0;
        while(++i)
        {
            //扩大法:将其中一个数扩大2倍、3倍....,看是否能整除另一个数
            if(a*i%b == 0)
            {
                printf("%d\n",a*i);
                break;
            }
        }
        return 0;
    }
    
  11. 打印1000~2000之间的闰年

    int main()
    {
        int y = 0;
        int count = 0;
        printf("1000到2000之间的闰年:");
        for(y=1000; y <= 2000; y++)
        {
            /*
             * 判断是不是闰年的条件
             * - 被4整除,不能被100整除是闰年
             * - 能被400整除的是闰年
             */
            if(y%4==0 && y%100!=0 || y%400 == 0)
            {
                printf("%d ",y);
                count++;
            }
        }
        printf("\n一共有:%d个闰年",count);//243
        return 0;
    }
    
  12. 100~200之间的素数

    //100~200之间的素数
    #include <stdio.h>
    int main()
    {
        //素数就是质数:只能被1和它本身整数的数叫素数。
        int i,j,n;
        int count = 0;
        for(i = 100;i<=200;i++)
        {
            //判断i是否为素数
            for(j=2;j<i;j++)
            {
                if(i%j==0){
                    //如果有能整除的数,说明这个数不是素数
                    n = 0;
                    break;
                }
            }
            //如果n不是0,说明i是素数,就输出。如果n是0,则让n+1,达到重置n的效果。
            //如果需要统计个数,则使用逗号表达式。逗号表达式以其中最后一个表达式的值作为结果。
            n? count++,printf("%d ",i):n++;
        }
        printf("\n100~200之间的素数个数:%d",count);
        return 0;
    }
    

    使用sqrt()函数减少循环次数

    /*
     * double sqrt(double x);
     * 作用:计算一个非负实数的平方根。 返回值:返回x的平方根
     *
     * ai = m*n
     * 在m和n中,一定有一个数字是<= i开平方的。 <= sqrt(i)
     * 如36=4*9 ,36=6*6  ,4<6,也就是说我们只需要判断6之前的这些数,判断到36%4=0,就不用一直判断到9。
     * 所以我们如果要判断i是不是质数,判断到sqrt(i),就可以了。
     *
     * 为什么这里还有等于的情况?
     * 如11*11 = 121,要一直判断到11。而如果是 j<sqrt(121),那么当j=11的时候,循环就会停止了。
     * 所以这里一定要是j <= sqrt(i)
     *
     */
    #include <stdio.h>
    #include <math.h>
    
    int main()
    {
        int i,j,n;
        int count = 0;
        //因为偶数肯定不是质数,所以这里从101开始,i每次+2。
        for(i = 101;i<=200;i+=2)
        {
            for(j=2; j<=sqrt(i); j++)
            {
                if(i%j==0){
                    n = 0;
                    break;
                }
            }
            n? count++,printf("%d ",i):n++;
        }
        printf("\n100~200之间的素数个数:%d",count);
        return 0;
    }
    
  13. 整数逆序

    #include <stdio.h>
    int main()
    {
        int n;
        printf("请输入一个整数:");
        scanf("%d",&n);
        int nn = 0;
    //    while (n>0)
    //    {
    //        nn = nn*10 + n%10;
    //        n /= 10;
    //    }
        //使用do..while循环简化程序。使用do..while是因为要先让程序执行一次。
        do
        {
            //nn为我们逆序的数。
            /*
             * 如输入的是456。
             * 第一次:nn = 0*10 + 456%10 = 6 ,取出了个位数字。n/10=45,因为是int类型,小数点直接省掉。
             * 第二次:nn= 6*10 + 45%10 = 65,取出十位数字,n/10 = 4。
             * 第三次 nn = 65*10 + 4%10 = 654,取出了百位数字,4/10=0,0为假,循环结束。
             * 每次的nn*10,使得已经取出的低位变高位,然后加上刚取出的高位,就完成了逆序。
             */
            nn = nn*10 + n%10;
        }while(n /= 10);
        printf("该整数逆序为:%d\n",nn);
        return 0;
    }
    
  14. 九九乘法表

    int main()
    {
        int i,j;
        for (i=1;i<10;i++)
        {
            for (j=1;j<=i;j++)
            {
                printf("%d*%d=%d\t",i,j,i*j);
            }
            printf("\n");
        }
        return 0 ;
    }
    
  15. 求自幂数

    /*
     * 水仙花数:一个三位数=个位的立方+十位的立方+百位的立方  例如:153=1³+5³+3³=1+125+27
     * 水仙花数只是自幂数的一种,严格来说3位数的3次幂数才称为水仙花数。
     * 自幂数:一个数的每位数的位数幂次方和=这个数
     */
    
    int main()
    {
        int input,chgIn,scope,m,n,lastNum,sum,total;
        //所求的自幂数范围,乘法,初始化值1
        scope = 1;
    
        //sum是用于计算某个数中每个数的幂次方,因为是乘法,所以初始化值为1
        sum=1;
        //total用于计算某个数的全部数字的幂次方和,加法,初始化为0
        total = 0;
    
        //获取输入值:
        printf("你要查看几位数的自幂数:");
        scanf("%d",&input);
        //chgIn是chang input的简写。
        //位数并不能随意改变。定义另一个变量,赋给它input的值,改变之后,还可以恢复其值,反复使用。
        chgIn = input;
    
        //计算出当前位数的自幂数范围:
        //当输入的是4时,应该是从1000开始,所以循环三次。--在变量后,所以先赋值后运算。
        while((chgIn--) > 1)
        {
            scope *= 10;
        }
        if(input <=9)
        {
            printf("%d位数范围是:%d~%d\n",input,scope,scope*10-1);
        }
        else if(input == 10)
        {
            printf("10位数的范围是:1000000000~999999999\n");
        }
        //恢复chgIn的值,以供下一次使用
        chgIn = input;
        switch (input) {
            case 1:
                printf("一位自幂数,称为独身数:");
                break;
            case 2:
                printf("没有二位自幂数!请重新运行程序");
                break;
            case 3:
                printf("三位自幂数,称为水仙花数:");
                break;
            case 4:
                printf("四位自幂数,称为四叶玫瑰数:");
                break;
            case 5:
                printf("五位自幂数,称为五角星数:");
                break;
            case 6:
                printf("六位自幂数,称为六合数:");
                break;
            case 7:
                printf("七位自幂数,称为北斗七星数:");
                break;
            case 8:
                printf("八位自幂数,称为八仙数:");
                break;
            case 9:
                printf("九位自幂数,称为九九重阳数:");
                break;
            case 10:
                printf("十位自幂数,称为十全十美数:4679307774。(程序算的太慢,直接告诉你)");
                return 0;
            default:
                printf("为了环保起见,10位以上的自幂数省略。最大的水仙花数有39位,十进制自然数中的水仙花数有88个");
                //如果是11位以上的数,则直接退出方法
                return 0;
        }
        //当scope是1000的时候,范围应该是1000~9999,而9999=scope*10-1,因为这里是<,所以不用-1。
        for(m=scope;m<scope*10;total=0,m++)
        {
            //因为不知道是几位数,所以采用逆序的方法从后往前取。
            //因为m是用于循环的数,并不能直接操作,为n赋m的值,这样就可以操作了。
            n = m;
    
            //取出每一位数,进行其对应的幂次运算,
            do{
                //取出当前数字的最后一位数字
                lastNum = n%10;
    
                //计算当前数的次方:如果是4位数,就是4次幂。
                while((chgIn--) > 0){//该循环用于求出,每个数字对应的位数幂次方。
                    sum *= lastNum;
                }
                //每个数的,每位数的幂次方,加起来。
                total += sum;
            //sum是一位数字的幂次方,chgIn用于一位数字的相乘次数,所以每次循环应该重置。
            //每一个数字的幂次方算完,加到total之后,就要算下一个数字(上一位数),这里使用/10的方式,来循环。
            //采用逗号表达式,只输出最后一个表达式的结果,当n/10=0,也就是当前数之后没有数字了,循环停止。
            }while(sum=1,chgIn=input,n/=10);
    
            //判断这个数每位数的幂次方和,是不是与这个数本身一样。
            if(total == m)
            {
                //如果一样,就说明这个数,是自幂数,输出这个数。
                printf("%d ",m);
            }
            //如果不是,则自动进入下一次循环
            //因为total是每个数字的幂次方和,所以每次循环完之后需要重置。
            //我们采用逗号表达式的方式,写入循环。
        }
        return 0;
    }
    

    无注释版

    #include <stdio.h>
    int main()
    {
        int input,chgIn,scope,m,n,lastNum,sum,total;
        scope = 1;
        sum=1;
        total = 0;
        printf("你要查看几位数的自幂数:");
        scanf("%d",&input);
        chgIn = input;
        while((chgIn--) > 1)
        {
            scope *= 10;
        }
        if(input <= 9)
        {
            printf("%d位数范围是:%d~%d\n",input,scope,scope*10-1);
        }
        else if(input == 10)
        {
            printf("10位数的范围是:1000000000~999999999\n");
        }
        chgIn = input;
        switch (input) {
            case 1:
                printf("一位自幂数,称为独身数:");
                break;
            case 2:
                printf("没有二位自幂数!请重新运行程序");
                break;
            case 3:
                printf("三位自幂数,称为水仙花数:");
                break;
            case 4:
                printf("四位自幂数,称为四叶玫瑰数:");
                break;
            case 5:
                printf("五位自幂数,称为五角星数:");
                break;
            case 6:
                printf("六位自幂数,称为六合数:");
                break;
            case 7:
                printf("七位自幂数,称为北斗七星数:");
                break;
            case 8:
                printf("八位自幂数,称为八仙数:");
                break;
            case 9:
                printf("九位自幂数,称为九九重阳数:");
                break;
            case 10:
                printf("十位自幂数,称为十全十美数:4679307774。(程序算的太慢,直接告诉你)");
                return 0;
            default:
                printf("为了环保起见,10位以上的自幂数省略。最大的水仙花数有39位,十进制自然数中的水仙花数有88个");
                return 0;
        }
        for(m=scope;m<scope*10;total=0,m++)
        {
            n = m;
            do{
                lastNum = n%10;
                while((chgIn--) > 0){
                    sum *= lastNum;
                }
                total += sum;
            }while(sum=1,chgIn=input,n/=10);
            if(total == m)
            {
                printf("%d ",m);
            }
        }
        return 0;
    }
    

    使用库函数pow

    #include <math.h>
    #include <stdio.h>
    
    //求自幂数
    int main()
    {
        int i;
        printf("0~100000之内的自幂数有:");
        for(i=0; i<=100000; i++)
        {
        //计算i的位数
        int n = 1;
        int tmp=i;
        while(tmp/10)
        {//只要还有余数,就位数+1。
            n++;
            tmp /= 10;
        }
    
        //计算i的每一位的n次方之和
        tmp = i;
        int sum = 0;
        while(tmp) //只要tmp不为0就一直循环。
        {
            //pow函数用于计算某个数的n次方。
            sum += pow(tmp %10,n);
            tmp = tmp/10;//计算完之后%10,就可以计算下一位。
        }
    
        //判断是否相同,如果相同,则是自幂数,然后输出
        if(i == sum)
        {
            printf("%d ",i);
        }
        }
        return 0;
    }
    
  16. 编写程序,数一下1~100之间所有整数中出现了多少个9

    #include <stdio.h>
    
    int main()
    {
        int i;
        int count = 0;
        for(i=i; i<=100 ; i++)
        {
            //个位数是9的
            if(i%10 == 9)
                count++;
            //十位数是9的
            if(i/10 == 9)
                count++;
        }
        printf("%d",count);
    }
    
  17. 计算1/1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 + …+ 1/99 - 1/100

    #include <stdio.h>
    int main()
    {
        int i;
        double sum;
        for (i=1 ; i <=100 ; ++i) {
            //因为int型的/,会省略小数点,所以这里写1.0,并且将sum变量定义为double类型
            if(i%2 == 0)
                sum -= 1.0/i;
            else
                sum += 1.0/i;
        }
        printf("%lf",sum);//0.688172
        return 0;
    }
    

    取反

    #include <stdio.h>
    
    int main()
    {
        int i;
        int flag = 1;
        double sum;
    
        //flag用于符号翻转
        for (i=1 ; i <=100 ; ++i) {
            sum += flag*1.0/i;
            //奇数运算完之后,符号取反。 偶数运算时,与sum运算就成了-,与算完之后再次取反,奇数运算时就是+了
            flag *= -1;
        }
        printf("%lf",sum);//0.688172
        return 0;
    
    
  18. 求十个数中的最大值

    #include <stdio.h>
    
    int main()
    {
        int arr[10] = { 134,15,48,154,12,451,2474,131,45,41};
        //这里不能定义为0,因为如果十个数都是负数,就会出错
        int max = arr[0];
        int i;
        for (i=0;  i<10 ; i++) {
            if(arr[i] > max)
            {
                max = arr[i];
            }
        }
        printf("%d",max);//2474
        return 0;
    }
    
  19. 打印*

    #include <stdio.h>
    
    int main()
    {
        //打印的行数
        int line = 0;
        scanf("%d",&line);
    
        //上
        int i,j;
        for (i = 0; i <line ; i++) {
            //打印空格
            for(j=0 ; j<line-1-i ; j++)
            {
                printf(" ");
            }
            //打印*:*的个数是1、3、5、7、9,也就是i*2+1
            for(j=0 ; j<2*i+1 ; j++)
            {
                printf("*");
            }
            //换行
            printf("\n");
        }
    
        //下
        for (i = 0; i <line-1 ; i++) {
            //打印空格,空格个数从1递增,逐行+1。
            for(j=0 ; j<=i ; j++)
            {
                printf(" ");
            }
            //打印*:*的个数是11、9、7,也就是2*6-1、2*5-1、2*4-1。也就是2*(行数-1-i)-1
            for(j=0 ; j<2*(line-1-i)-1 ; j++)
            {
                printf("*");
            }
            //换行
            printf("\n");
        }
    
        return 0;
    }
    
  20. 一瓶汽水1元,两个空瓶可以换一瓶汽水,给你20元,你可以喝多少瓶汽水?

    #include <stdio.h>
    
    int main()
    {
        //有20元
        int money = 0;
        printf("你有多少钱:");
        scanf("%d",&money);
        //一瓶一元,有多少元就有多少瓶,并且有多少个空瓶。
        int total = money;
        int empty = money;
        //每两个空瓶,就可以换一瓶。
        while(empty>=2)
        {
            total += empty/2;
            //当empty=5时,empty/2=2,多余的1个瓶子就被丢掉了。所以要再加上empty%2的结果,这样就不会有空瓶丢失了。
            //empty = empty/2;
            empty = empty/2 + empty%2;
        }
        printf("%d元可购买的汽水:%d",money,total);
    
        return 0;
    }
    

    另一种方法

    #include <stdio.h>
    
    int main()
    {
        int money = 0;
        int total = 0;
        printf("你有多少钱:");
        scanf("%d",&money);
        //我们发现只要买了一瓶之后,再买一瓶就是买一赠一。所以我们有多少钱就可以到到:2*money-1瓶汽水
        //但是要注意money要大于0。避免出现没钱去买汽水,还欠一个瓶子的情况。
        if(money>0)
        {
            total = 2*money-1;
        }
        printf("%d元可购买的汽水:%d",money,total);
    
        return 0;
    }
    
  21. 打印X图案

    //打印由*组成的X图案:输入多行,一个整数(2~20),表示输出的函数,也表示X反斜线和正斜线的长度。
    /*
     * 思路:
     * - 正斜线:第一行第一个,第二行第二个,第三行第三个,第n行第n个
     * - 反斜线:看元素下标。比如行数是5,
     *   第一行的*:0,4   第二行:1,3   第三行:2,2   第四行:3,1   第五行:4,0
     * - 规律:假设行数是i,列数是j。
     *   正斜线:i=j时打印*        反斜线:i+j=n-1时打印*     其他情况打印空格
     *   第三行的时候会不会重叠呢? 不会,正斜线:i=2,j=2时打印。反斜线:i=2,j=2时,2+2=5-1
     *   只要打印了一个,就不看后面了,也就是要使用if..else if..else
     */
    
    /*
          输入5:
          *   *
           * *
            *
           * *
          *   *
     */
    
    #include <stdio.h>
    
    int main()
    {
        int n = 0;
        //scanf函数返回值:如果达到文件末尾或发生读写错误,则返回EOF
        while(scanf("%d",&n) != EOF)
        {
            int i,j;
            for(i=0 ; i<n ; i++)
            {
                for(j=0 ; j<n ; j++)
                {
                    if(i == j)
                    {
                        printf("*");
                    }else if(i+j == n-1)
                    {
                        printf("*");
                    }
                    else
                    {
                        printf(" ");
                    }
                }
                printf("\n");
            }
        }
    }
    
  22. 7个数,去掉一个最高的和一个最低的,求平均数

    /*
     * 公务员面试现场打分,有7位考官,从键盘输入若干成绩,每组7个分数(满分100分),去掉一个最高分和一个最低分。输出每组的平均成绩。
     * 输入:一行输入7个数,代表7个成绩,用空格分割。
     * 输出:一行,去掉最高分和最低分之后的平均成绩,输出后换行。
     */
    
    int main()
    {
        int score,i;
        int sum = 0;
        int max = 0;
        int min = 100;
        for(i=0 ; i<7 ; i++)
        {
            scanf("%d",&score);
            sum += score;
            if(score > max)
            {
                max = score;
            }
            if(score < min)
            {
                min = score;
            }
        }
        //%f打印浮点数  .2表示:保留2位小数位。
        printf("%.2f",(sum-max-min)/5.0);
    
        return 0;
    }
    

转向语句

goto语句

  • C语言中提供了可以随意使用的goto语句和标记跳转的标号

    从理论上goto语句是没有必要的,实践中没有goto语句也可以很容易写出代码

  • 但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深层嵌套结构的处理过程

    例如:一次跳出两层或多层循环。多层循环这种情况使用break是达不到目的的,break只能推出一次循环。

  • goto只能在函数内进行跳转,不能跨函数跳转。

  • goto语句真正适合的情况

    for(...)
    {
    	for(...)
        {
            for(...)
            {
                if(disaster)
                {
                    goto error;
                }
            }
        }
    }
    error:
    	if(disaster)
        {
            //处理错误情况。
        }
    
  • 使用goto语句,制作关机程序。

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    //goto语句
    int main()
    {
        char input[30]={0};//存放我们输入的字符串
        //C语言提供了一个函数:system(),用于执行系统命令的
        system("shutdown -s -t 120");
        again:
        printf("电脑将在2分钟内关机,输入:我是香香猪。 就取消关机!\n请输入:");
        scanf("%s",input);
        if(strcmp(input,"我是香香猪") == 0)
        {
            system("shutdown -a");
        }
        else
        {
            printf("输入错误,请重新输入,马上就要关机了请看清楚呦。\n");
            goto again;
        }
    }
    

    使用while循环代替

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char input[30]={0};
        system("shutdown -s -t 120");
        while(1)
        {
            printf("电脑将在2分钟内关机,输入:我是香香猪。 就取消关机!\n请输入:");
            scanf("%s",input);
            if(strcmp(input,"我是香香猪") == 0)
            {
                system("shutdown -a");
                break;
            }
            else
            {
                printf("输入错误,请重新输入,马上就要关机了请看清楚呦。\n");
            }
        }
        return 0;
    }
    

break语句

  • break是C语言中的一个关键字,被译为“中断”

    break;是一个完整的语句

  • break; 使用在循环语句/switch分支语句中,用来中止循环的执行。

  • break; 终止哪个循环呢?

    默认情况下:break;语句终止离它最近的循环语句。只能终止一层循环,如果时嵌套的循环,则无法影响到外层循环。

    break;语句使用在for、while、do..while循环语句中,用来跳出循环,终止循环的执行。当程序循环到某个条件时,后续的循环没必要再执行了,再执行也是浪费资源,所以可以终止循环,这样可以提高程序的执行效率。
    

continue语句

  • continue表示:继续/下一个

  • continue; 是一个完整的语句,主要出现在循环语句中用来控制循环的执行

  • break; 与 continue; 的区别:

    - break表示循环不执行了,跳出循环,终止循环
    - continue表示终止当前的这次循环,跳入下一次循环继续执行
    
  • continue使用

    #include <stdio.h>
    
    int main()
    {
        int i;
        for(i=0 ; i<10 ; i++)
        {
            if(i==5)
            {
                continue;//只要条件符合整个语句执行,当前循环停止,直接进入下一次循环“继续”执行
            }
            printf("%d ",i);//0 1 2 3 4 6 7 8 9
        }
        return 0;
    }
    

return语句

  • return; 语句,用来终止当前方法。

    注意是return; 而不是return 值;。

    #include <stdio.h>
    
    void menu()
    {
        printf("11111");
        return;//终止当前方法
        printf("22222");
    }
    
    int main()
    {
        menu(); //输出11111
        return 0;
    }
    
  • return; 与 break;的区别

    - break;    终止switch和离他最近的循环
    - return;   用来终止离他最近的一个方法。
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值