C语言集训-电气213殷俊峰-第三次作业

118 阅读8分钟

第三次集训

如何使用scanf编写出高质量代码

  1. 使用scanf之前先使用printf提示用户以什么样的方式输出
  2. scanf中尽量不要使用非输出控制符,尤其是不要使用\n
  3. 应该编写代码对用户的非法输入做适当处理。
`while ((ch=getchar()) !='\n')` 
​
    `continue;`

运算符

  • 算术运算符

    | +(加) -(减) *(乘) /(除) %(取余)

  • 关系运算符

    | >(大于) >=(大于等于) <(小于) <=(小于等于) !=(不等于) ==(等于)

  • 逻辑运算符

    | !(非) &&(并且) ||(或)

  • 赋值运算符

    | = += *= /= -=

优先级别:算数 > 关系 > 逻辑 > 赋值

除法与取模运算符:

  • 除法/的运算结果和运算对象的数据类型有关,两个数都是int,则商就是int,若商为小数,则截取小数部分;被除数和除数中只要有一个或两个都是浮点型数据,则商也是浮点型,不截取小数部分。

    • 如:16/5 == 3 16/5.0 == 3.20000 -13/4 == -4
    • -13/-3 == -4 3/5 == 0 5/3 == 1
    • 最典型的例题就是求 s =1+1/2+1/3+1/4+1/5......+1/100的值
  • 取余%的运算对象必须是整数,结果是整数后的余数,其余数的符号只与被除数相同。

    • 如: 13%3 == 1 13%-3 == 1 -13%3 == -1
    • -13%23 == -13 3%5 == 3

逻辑运算符

C语言对真假的处理:非零既为真,零为假;

&&运算符:当左边的表达式为假时,右边的表达式不执行。

||运算符:当左边的表达式为真时,右边的表达式不执行。

一些琐碎的运算符知识:

自增 自减 三目运算符 逗号运算符

1.自增 [ 或者自减 ]

  • 分类:

前自增 —— ++i

后自增 —— i++

  • 前自增和后自增的异同:

相同:最终都使i的值加1

不同:前自增整体表达式的值是 i 加 1 之后的值、后自增整体表达式的值是 i 加 1 之前的值

  • 为什么会出现自增

1.代码更精炼 。2.自增的速度更快。

  • 学习自增要明白的一些问题

  1. 我们编程时应该尽量屏蔽掉前自增和后自增的差别。

  2. 自增表达式最好作为一个单独语句使用,不要作为一个完整复合语句的一部分来使用。

    如: int m = i++ + ++i + i + i++; //这样写不但是不规范的代码,而且是不可移植的代码。此处涉及到顺序点: ' ( ) ' 和 ' , ' 和 ' ; '。此时不知道i++是否立即生效。

2.三目运算符

格式:

A?B:C

等价于

if (A)
    B;
else
    C;

3.逗号表达式

格式: (A, B ,C , D)

功能: 从左到右执行,最终表达式的值是最后一项的值。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

流程控制【重点1】:

  1. 什么是流程控制

    程序代码执行的顺序

  2. 流程控制的分类

    • 顺序

    • 选择

      • 定义

        某些代码可能执行,也可能不执行,有选择的执行某些代码。

      • 分类

        if

        1. if最简单的用法

          格式:

          if(表达式)
          语句;
          

          功能:

          如果表达式为真,执行语句

          如果表达式为假,语句不执行 if最简单的用法.pngIF最简单的用法2.png

        2. if的范围问题

          1).

          if(表达式)
              语句A;
          语句B;
          

          解释:if默认只能控制语句A的执行或不执行

          if无法控制语句B的执行与否,既语句B一定会执行。

          2).

          if(表达式)
          {
              语句A;
              语句B;
          }
          

          此时if可以控制语句A语句B

          由此可见: if默认只能控制一个语句的执行或不执行,如果想要控制多个语句的执行 或不执行,就必须把这些语句用{}括起来。if的范围问题.png

        3. if..else...的用法

        if_else.png

        1. if..else if...else...的用法

          格式:

          if(表达式1)
              语句A;
          else if (表达式2)
              语句B;
          else if (表达式3)
              语句C;
          else
              语句D;
          
        2. C语言对真假的处理

          非零为真,零为假

          真用以表示,假用零表示

        3. if举例--求分数的等级

          数学中的表达式:(90<=score<=100)不能在C语言中表示,因为首先会对(90<=score)进行运算,结果为0或1然后再将0或1与100比较。 90小于等于score的测试.png 程序=算法+语言

        4. 看懂一个程序的三步

          1.流程 2.每个语句的功能 3.试数

          如何学习一些需要算法的程序(郝老师的学习方法)
          1. 尝试自己去解决它,大部分人都自己无法解决。
          2. 如果解决不了,就看答案。 关键是把答案看懂,这个要花很大的精力,也是学习的重点。
          3. 看懂之后尝试自己去修改程序,并且知道修改之后程序的不同输出结果的意思。
          4. 照着答案去敲代码。
          5. 调试错误。
          6. 不看答案,自己单独把答案敲出来。
          7. 如果彻底无法彻底理解,就把它背会。
        5. if的常见问题解析

          1. 空语句的问题
            if (3 > 2);
            //等价于
            if (3 > 2)
                ;//这是一个空语句
            
          2. if(表达式1);
                语句A;
            else    
                语句B;//这是错误的
            
            if(表达式1)
                语句A;
            else ;
                语句B;//这是正确的
            //等价于
            else 
                ;
            语句B;
            
          3. if(表达式1)
                语句A;
            else if (表达式2)
                语句B;
            
          4. if(表达式1)
                语句A;
            else if (表达式2)
                语句B;
            else (表达式3)
                语句C;//错误,正确写法为去掉 (表达式3)或在else (表达式3)之间加if
            
          5. if(表达式1)
                语句A;
            else if (表达式2)
                语句B;
            else (表达式3);
                语句C;// 语法正确,但逻辑上是错误的。   
            

        switch

        格式:

      switch.png 常变量:const int i;//i只能被赋一个值switch2.png switch3.png 楼层程序:

    #include<stdio.h>
    
    int main (void)
    {
        int val;
    
        printf ("输入您想进入的楼层:");
        scanf ("%d",&val);
    
        switch (val)
        {
        case 1:
            printf ("1层开!\n");
            break;
    
        case 2:
            printf ("2层开!\n");
            break;
    
        case 3:
            printf ("3层开!\n");
            break;
        
        default:
            printf ("没有盖到这层\n");
            break;
        }
    
    return 0;
    }
    
    • 循环

    1. 定义

      某些代码会被重复执行

    2. 分类

      for

      1.格式:

        for(1;2;3)
        A;
      

      2.执行的流程【重点】

      (1) for,if的嵌套使用

      forif嵌套.png 求1到100之间的奇数和.png 运行结果:

      屏幕截图 2021-11-24 225944.png

      (2)多个for循环的嵌套使用

           for(1;2;3)
               for(4;5;6)
                   A;
           B;
      

      image.png

    3.范围问题

    4.举例

    1 + 2 + 3……+ 100

    1 +1/2+1/3……+ 1/100

    <强制类型转换>

    格式:(数据类型)(表达式)

    功能:将表达式的值强制转化为前面所执行的数据类型

    例子:(int)(4.5+2.2) 最终值为6 (float)(5) 最终值为 5.000000

        #include <stdio.h>
        
        int main(void)
        {
            int i;
            float sum = 0;
        ​
            for ( i = 1; i <=100; i++)
            {  
                sum = sum + 1/float(i);//强制转换
                //更简单的写法为   sum = sum + 1.0/i;
            }
            
            printf("1+1/2+1/3……+1/100=%f\n",sum);//float必须用%f输出
        ​
            return 0;
        }
    

    <浮点数的存储带来的问题>

    循环中更新的变量不能定义为浮点型

    float和double都不能保证可以精确的存储一个小数

    举例:

    有一个浮点型变量x,如何判断x的值是否为0

    if(|x-0.000001|<0.000001)
        是零;
    else
        不是零;
    

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    while

    1. 执行顺序 格式:

      while(表达式) 语句;

    2. 与for的比较

    while和for之间可以相互转换,但for的逻辑性更强,更不易出错(推荐多使用)。

    while的一加到一百.png

    1. 举例 (1)从键盘输入一个数字,如果该数字是回文数,则返回yes,否则返回no。 判断回文数.png

代码如下:


int main(void)
{
    int val;//存放需要判断的数字
    int m;
    int sum = 0;

    printf("请输入您需要判断的数字:");
    scanf("%d",&val);

    m=val;
    while (m)
    {
        sum = sum * 10 + m%10;
        m /=10; 
    }
    
    if(sum == val)
    {
        printf("Yes!\n");
    }
    else
    {
        printf("No!\n");
    }
    
    return 0;
}

缺点:该代码无法判断过长的数是否为回文数。

(2)斐波那契数列

屏幕截图 2021-11-25 175528.png

斐波那契序列.png

结果如下:

斐波那契序列结果.png

代码如下:

#include <stdio.h>

int main(void)
{
    int n,i;
    int f1, f2, f3;

    f1 = 1;
    f2 = 1;

    printf("请输入您想要求的序列:");
    scanf("%d",&n);

    if (1 == n)
    {
        f3 = 1;    
    }
    else if (2 == n)
    {
        f3 = 1;
    }
    else
    {
        for (i = 3; i<=n; i++)
        {
            f3 = f1 + f2;
            f1 = f2;
            f2 = f3;
        }
    }

    printf("%d",f3);
    return 0;
}
  1. 什么时候使用while什么时候使用for(自行体会)

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

do……while

格式:

do
{
    语句A;
}while(表达式); 

并不等价于while,也不等价于for

主要用于人机交互

一元二次方程

一元二次1.png 屏幕截图 2021-11-25 213551.png

运行结果: 一元二次运行.png

代码如下:

#include <stdio.h>
#include <math.h>

int main(void)
{
    double a,b,c;
    double x1,x2;
    double delta;
    char ch;

    do
    {
        printf("请依次输入一元二次方程的三个系数:\n");
        printf("a = ");
        scanf("%lf",&a);

        printf("b = ");
        scanf("%lf",&b);

        printf("c = ");
        scanf("%lf",&c);

        delta=b*b-4*a*c;
        printf("delta=%lf\n",delta);
    
        if(delta > 0)
        {
            x1 = (-b + sqrt(delta))/( a * 2);
            x2 = (-b - sqrt(delta))/( a * 2);
            printf("该方程有两个解, x1 = %lf,x2 = %lf\n",x1,x2);
        }
        else if(delta==0)
        {
            x1=(-b)/(2*a);
            x2=x1;
            printf("该方程有唯一解, x1 = x2 =%lf\n",x1);
        }
        else 
        {
            printf("无解\n");
        }

        printf("继续请输入Y,退出请输入其他值:");
        scanf(" %c", &ch);//%c之前要加空格(暂不讨论)

    }while('y'==ch || 'Y'==ch);
    
    return 0;
}

break和continue

break

1.break如果用于循环是用来终止循环

2.break如果用于switch,则是用于终止switch

3.break不能直接用于if,除非if属于循环内部的语句

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

    switch (2)
    {
    case 2:
        printf("哈哈哈!\n");
        break;
    }

    for (i=0; i<3; ++i)
    {
        if (3 > 2)
            break;//break虽然是if内部语句,但break终止的是外部for的循环
        printf("嘿嘿!\n"); //永远不会输出
    }
    return 0;
}

4.break用于多个for循环

在多层循环中,break只能终止距离最近的循环。

例子:

#include <stdio.h>

int main(void)
{
    int i,j;

    for (i=0; i<300; ++i)
    {
        for ( j = 0; j <4; ++j)
        {
            break;
        }
        printf("看网课累啊!\n"); 
    }

    return 0;
}

5.在多层switch嵌套中,break只能终止距离它最近的switch

r.png

输出结果:

i.png

continue

作用:跳过本次循环余下的语句,转去判断是否需要判断下次的循环

for ( 1; 2; 3)
{
   A;
   B;
   contine;//如果执行完该语句后,会执行语句3,C,D都会被跳过去。
   C;
   D;
}
while (表达式)
{
   A;
   B;
   contine;//如果执行完该语句后,会执行表达式,C,D都会被跳过去。
   C;
   D;
}

课后习题

C Primer Plus

  • 5.10 第七题 第十三题

第七题

屏幕截图 2021-11-25 230409.png

打印结果:

屏幕截图 2021-11-25 230444.png

第十三题:(该程序无实际意义)

13题.png

  • 5.11 第三题 第八题 第三题: 第三题.png

运行结果:

三运算.png

代码如下:

#include <stdio.h>

int main(void)
{
    int day,day_left;
    int week;

    printf("请输入天数:");
    scanf("%d",&day);
   
    week = day / 7;
    day_left = day % 7;
    
    printf("%d天 是 %d周, %d天",day,week,day_left);
    return 0;
}

第八题:

第八题.png

运行结果:

屏幕截图 2021-11-25 233623.png

代码如下:

#include<stdio.h>  
int main()
{
    int a, b, c, d;
    int i=0;
    
    do
    {
        printf("若要结束请输入非正数。\n");
        printf("请输入第%d个整数:",i+=1);
        scanf ("%d",&a);
        
        if(!(a > 0))
        {break;}
        
        printf("请再次输入1个整数:");
        scanf ("%d",&b);
        
        if(!(b > 0))
        {break;}
        
        c = b%a;  
        printf("求模运算的结果为:%d\n",c);
    
    }while (1);
    
    return 0;
}

  • 6.16 第五题 第十二题 (计算机二级内容) 第十八题

第五题没想出算法

暂时敲不出来。

第十二题: 12题目.png

12题目.png 代码如下:

#include<stdio.h>  
int main()
{
    double i,sum1=0,sum2=0,xiang;                          
    int a = 1;
    do
    {
        printf("请输入大于1的项数:"); 
        scanf ("%lf",&xiang) == 1;
        if(xiang<=1)
        {break;}
        for (i = 1.0; i <= xiang; i++,a = 0-a)
        {
            sum1 += 1.0 / i;
            sum2 += a*1.0 / i;   
        }
        printf("sum1 = %lf, sum2 = %lf\n", sum1, sum2);
        
    }while(1);
    printf("结束");
   
    return 0;
}

第18题 代码:

#include<stdio.h> 
int main()
{
    int you;
    int i = 1; 
    
    for (you = 5; 1; i++)
    {   
        
        you = 2 * (you - i);
        if(you > 150)
        {break;}
        printf("第 %d 周有 %d 个朋友\n", i, you);
    }
    
    return 0;
}

运行结果:

屏幕截图 2021-11-25 235909.png

  • 7.11 第二题 第十题 第二题语句:

a. number >= 90 && number <100;

b. ch!='q' && ch!='k';

c. number >= 1 && number <= 9 && number != 5;

d. number < 1 || number >9;

第十题(我一开始用了do...while和while的嵌套,频繁使用了break,然后感觉有点问题,所以不贴出了。)

但这里还是给出一个答案:

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

    while ((ch = getchar()) != '#')
    {
        if (ch != '\n')
        {
            printf("step 1\n");
            if (ch == 'b')  
               break;  
            else if (ch != 'c')
            {
                if (ch != 'h')
                printf("step 2\n");
                printf("step 3\n");
            }
        }
    }
    printf("Done\n");
    return 0;
}

图片来源视频:www.bilibili.com/video/BV1os… (如有侵权请在文章下留言。)

第十题代码来源:juejin.cn/post/703451… (以获得授权使用)