c语言集训-刘佳雨-第三次作业

317 阅读8分钟

学习笔记

运算符
|运算符| | | | | | |
-|-|-|-|-|-|- |算数运算符|+(加)|-(减)| *(乘)|/(除)|%(取余数)
|关系运算符|>|>=(大于或等于)|<|<=(小于或等于)|!=(不等于)|==(等于) |逻辑运算符|!(非)|&&(并且)|||(或)
|赋值运算符|=|+=|*=|/=|-=| |自增 / 自减|前自增 -- ++i|后自增 -- i++|--i|i--|

  • 除法与取余数运算符:

    • 除法的算法结果和运算对象的数据类型有关,两个数都是int时,则商为int,若商有小数,则将截取整数部分;被除数和除数中有一个及以上是浮点型数据时,则商为浮点型,且会保留小数部分。
      如: 16 / 5 == 3 , 16 / 5.0 == 3.20000 , -13 / 4 == -4
      -13 / -3 == 4 , 3 / 5 == 0 , 5 / 3 == 1
    • 取余数%的运算对象必须是整数,结果是整除后的余数,且符号与被除数相同
      如: 13 % 3 == 1 , 13 % -3 == 1 , -13 % 3 == -1 , -13 % 23 == -13 , 3 % 5 ==3
  • 逻辑运算符:
    !真 -- 假 , !假 -- 真
    真&&真 -- 真 , 真&&假 -- 假
    假&&真 -- 假 , 假&&假 -- 假
    真 || 假 -- 真 , 假 || 真 -- 真
    真 || 真 -- 真 , 假 || 假 -- 假

    • c语言对真假的处理:
      • 非零是真,零是假
      • 真用1表示,假用0表示
      • &&左边的表达式为时,右边的表达式将不会执行
      • ||左边的表达式为时,右边的表达式也将不会执行
  • 赋值运算符:
    a += 3 -- a = a + 3 ; a /= 3 -- a = a / 3

  • 自增 / 自减:

    • 前自增与后自增的异同点:
      • 相同:最终都使i加1
      • 不同:前自增整体表达式的值是i加1之后的值,后自增整体表达式的值是i加1之前的值
    • 为什么会出现自增:
      • 代码更精炼
      • 自增的速度更快
    • 学习自增须知:
      • 编程时应尽量屏蔽前后自增的差别
      • i++ 与 ++i 单独成一个语句,不要把它作为一个完整复合语句的一部分来使用
        如:int m = i++ + ++i + i + i++; 这样写不但是不规范的,而且不可移植,所运行可能会出错(设计到顺序点的知识) (自减与自增同理
  • 三目运算符:
    格式:A ? B : C
    等价于
    if(A)
    B;
    else
    C;

  • 逗号表达式:

    • 格式:(A,B,C,D)
    • 功能: 从左到右运行;最终表达式是最后一项的值

运算符的优先级别:算术运算符>关系运算符>逻辑运算符>赋值运算符

遇到优先级问题时,为提高代码的可读性,尽量使用括号,不要写出有歧义的代码。一行代码不要出现多个自增自减符号,这会被视作垃圾代码。  

流程控制

  • 什么是流程控制:
    流程控制是指程序代码执行的程序
  • 流程控制的分类:
  1. 顺序执行
  2. 选择执行
    • 定义:某些代码可能执行,也可能不执行,有选择的执行某些代码
    • 分类:
      if
      • if最简单的用法 格式:
        if(表达式)
        语句;
        功能:如果表达式为真,则执行语句,为假则不执行。
      • if的范围问题
        if默认只能控制一个语句的执行或不执行
        如果要控制多个语句,则需用{}将需要控制的语句括起来
      • if...else...
      • if...else if...else...
        在运行if...else...或者if...else if...else语句时,若if与else之间有多个语句,一定要用括号将这些括起来,否则将会出错
      • c语言对真假的处理
        1. 非零是真,0是假
        2. 真用1表示,假用0表示
      • if的常见问题解析
        1. 空语句的问题:
          if (3 > 2); 等价于:
          if (3 > 2)
          ; 这是一个空语句
        2. if与else后均不需添加分号; else后面添加分号或者if语句以else if结尾,语法不会出错,但是逻辑上是错误的。
        3. if(表达式)
          A;
          else if (表达式)
          B; else
          C;
          即便表达式1,2都成立,也只会执行A语句。 switch
      • 格式:
        switch
        {
        case 常量表达式1: 语句1;
        case 常量表达式2: 语句2;
        default : 语句3;
        }
      • 所有case后面的常量表达式为便于描述我们姑且称之为标签,这些标签只能是枚举变量数值变量字符变量常变量宏名中的一种
      • switch后面括号里的表达式允许是任何类型(vc++中只允许为int或char)
      • switch中不能出现continue,除非其属于for或while的一部分
  3. 循环执行 定义:某些代码会被重复执行
    分类:

1.for语句

  • 格式:
    for(1;2;3)
    语句A;
    for语句中循环条件用分号;隔开,而不用逗号
  • 执行的流程:123A32A3循环运行
  • 范围与if相近,默认只控制一个语句的执行或不执行,控制多个语句需用{}将所需控制语句括起来
  • 多个for循环的嵌套使用:
    for(1;2;3) //1
    for(4;5;6) //2
    A; //3
    B; //4
    整体是两个语句,1 2 3是第一个语句 , 4是第二个语句

2.while语句

  • while和for可以相互转化,但for的逻辑性更强,更不容易出错,推荐多使用for

3.do while语句

  • 格式:
    do
    {
    .....
    }while(表达式);
  • do...while不等价于for以及while
  • 主要用于人机的交互

*break语句

  • break如果用于循环则用来终止循环;如果用于switch则用来终止switch
  • break不能直接用于if,除非if属于循环内部的一个子句
  • break只能终止距离它最近的一个循环

continue语句

  • 用于跳过本次循环余下的语句,转去判断是否需要执行下次循环
    for (1;2;3)
    {
    A;
    B;
    continue; //如果执行该语句,则执行完该语句后,将会执行语句3,C和D都会被跳过,不会被执行
    C;
    D;
    }
    *浮点数的存储所带来的问题
  • float和double都不能保证可以精确的存储一个小数
    举例:有一个浮点型变量x,如何判断x的值是否为0?
    if (x和一个非常小的值差的绝对值小于这个数)
    是0;
    else
    不是0;

*看懂并掌握一个程序: image.png
*强制类型转化

  • 格式:(数据类型)(表达式)如:1 / (float)(i)
  • 功能:把表达式的值强制转化为前面所执行的数据类型
  • 举例: (int)(4.5+2.2),最终值为6
    (float)(5.0),最终值为5.000000

代码实操

测试取余数运算符:

#include<stdio.h>

int main()
{
    printf("%d %d %d %d %d %d\n", 3%3, 13%-3, -13%3, -13%-3, -13%23, 3%5);
    return 0;
}

运行结果:

image.png

由输出结果易知:取余%的运算对象必须为整数,结果是整除后的余数,且符号与被除数相同

&&的使用:

#include<stdio.h>

int main()
{   
    int i = 10;
    int k = 20;
    int m;
    int n;
    m = (1>2) && (k=5);
    n = (3>2) || (i=8);
    printf("m = %d, n = %d, i = %d, k = %d\n", m, n, i, k);
    
    return 0;
}

运行结果:

image.png 结论: 0表示假,1表示真
&&左边的表达式为时,右边的表达式将不会执行
||左边的表达式为时,右边的表达式也将不会执行

前自增与后自增的比较:

#include<stdio.h>

int main()
{   
    int i;
    int j;
    int k;
    int m;
    
    i = j = 3;
    k = i++;
    m = ++j;
    
    printf("i = %d, j = %d, k = %d, m = %d\n", i, j, k, m);
    
    return 0;
}

image.png

结论:前自增整体表达式的值是i加1之后的值,后自增整体表达式的值是i加1之前的值

三目运算符:

#include<stdio.h>

int main()
{   
    int i;
   
    i = (3>2 ? 5 : 1);
    printf("%d\n",i);

    return 0;
}
//i = (3>2 ? 5 : 1);等价于  if(3>2)  
//                              i = 5;
//                          else 
//                              i = 1;

运行结果:

image.png

逗号表达式:

#include<stdio.h>

int main()
{   
    int i;
    int j = 2;
    
    i = (j++, ++j, j+2, j-3);//j+2不等价j = j+2
    printf("%d\n",i);

    return 0;
}

运行结果:

image.png

结论:逗号表达式从左到右运行;最终表达式是最后一项的值

if最简单的用法:

#include<stdio.h>

int main()
{   
   if (1)
       printf("a\n");
   if (0)
       printf("b\n");
   if (0 == 0)
       printf("c\n");

    return 0;
}

运行结果:

image.png

结论:if语句中,如果表达式为真,则执行语句,为假则不执行。

if举例 -- 求分数的等级:

#include<stdio.h>

int main()
{   
    float score;

    printf("请输入你的成绩:");
    scanf ("%f", &score);

    if (score > 100)
        printf("这是做梦!\n");  
    else if (score <= 100 && score >= 90)//不能写成90<=score<=100
        printf("优秀!\n");
    else if (score <= 90 && score >= 80)
        printf("良好\n");  
    else if (score <= 80 && score >= 60)
        printf("及格\n");  
    else  
        printf("不及格,继续努力\n");

    return 0;
}

运行结果

image.png

互换两个数字&比较三个数字的大小:

#include<stdio.h>

int main()
{   
    int a, b, c;
    int t;       //定义一个临时变量
    
    printf("请输入三个整数(中间以空格分隔)");
    scanf("%d %d %d",&a, &b, &c);

    if (a < b)
    {
       t = a;
       a = b;
       b = t;      //互换a b
    }
    else if (a < c)
      {
       t = a;
       a = c;
       c = t;
      }
       else if (b < c)
    {
       t = b;
       b = c;
       c = t;
    }
    printf("%d %d %d", a, b, c);
    return 0;
}

运行结果
image.png

for语句循环:

#include<stdio.h>

int main()
{   
    int i;
    int sum = 0;

    for (i = 1; i <= 10; i++)
        sum = sum + i;

    printf("sum = %d\n",sum);
    return 0;
}

运行结果image.png

选择循环语句程序设计:

#include<stdio.h>

int main()
{   
    int i;
    int sum1 = 0;  
    int sum2 = 0;               //sum1表示奇数之和,sum2表示偶数之和
    float avg1,avg2;

    for (i = 1; i <= 100; i++)
        {
             if (i%2 == 1)
            sum1 = sum1 + i;  
        else if (i%2 == 0)
            sum2 = sum2 + i;
        }   
    avg1 = 2*sum1 / (i + 1);     
    avg2 = 2*sum2 / i;           //avg1表示100以内奇数的平均数,avg2表示100以内偶数的平均数
    printf("sum1 = %d, sum2 = %d, avg1 = %f, avg2 = %f\n", sum1, sum2, avg1, avg2);

    return 0;
}

运行结果

image.png

判断回文数

#include<stdio.h>
int main()
{
    int m;
    int sum = 0;
    int val;
    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;
}

运行结果

image.png
原理:利用while语句(括号中不为0时循环进行,为0时停止输出)依步运行进行取余等运算将所需判断数倒过来,再与原来的数对比是否相等从而判断是否为回文数。

用do...while语句实现多个一元二次方程的运算

# include<stdio.h>
# include<math.h>
int main(void)
{
   double a, b, c;
   double delta;
   double x1,x2;
   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;
      
      if (delta > 0)
     {
          x1 = (-b + sqrt(delta)) / (2*a);
          x2 = (-b - sqrt(delta)) / (2*a);
          printf("该一元二次方程有两个解,x1 = %lf,x2 = %lf\n",x1,x2);
     }
      else if (delta == 0)
     {
          x1 = (-b + sqrt(delta)) / (2*a);
          x2 = x1;
          printf("该一元二次方程有唯一解,x1 = x2 = %lf\n",x1);
     }
      else
     {
           printf("无解\n");
     }
      printf("是否继续(Y/N):"); 
      scanf(" %c", &ch);           //%c前面必须加一个空格
   }while('y' == ch || 'Y' == ch);
               
   return 0;
}

运行结果image.png

课后习题

5.10

第7题: 输出结果如图

image.png
第13题:
a. x -= 1;
b. m = n % k;
c. p = q / (b - a);
d. x = (a + b) / (c * d);

5.11

第3题:

#include<stdio.h>  
int main()
{
    int a, b, c;
    
    do
    {
    printf("请输入天数:");
    scanf("%d",&a);
    b = a%7;  
    c = a/7;
    printf("%d days are %d weeks, %d days\n",a, c, b);
    }while (a > 0);
    
    return 0;
}

image.png
第8题:

#include<stdio.h>  
int main()
{
    int a, b, c, d;

    printf("请输入第一个整数:");
    scanf ("%d",&a);
    do
    {
        printf("请再次输入一个整数:");
        scanf ("%d",&b);
        c = b%a;  
        printf("%d\n",c);
    }while (b > 0);
    
    return 0;
}

image.png

6.16

第5题:实在是不会写,但是有对着答案敲了一遍

第12题:

#include<stdio.h>  
int main()
{
    double times, i;                          //times为项数
        
    printf("请输入项数:"); 
    `while ((scanf ("%lf",&times) == 1) && (times > 0))` //此句有参考答案
    {
        int a = 1;  
        double sum1 = 0, sum2 = 0;          //sum1为第一个序列的和,sum2为第二个序列的和
        for (i = 1.0; i <= times; i++,a = 0-a)
        {
            sum1 += 1.0 / i;
            sum2 += a*1.0 / i;   
        }
         printf("sum1 = %lf, sum2 = %lf", sum1, sum2);
    }
    printf("结束");
   
    return 0;
}

image.png
结论:第一个序列不收敛,第二个序列收敛于0.7
第18题:

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

image.png

7.11

第2题:
a. number >= 90 && number <100;
b. ch!='q' && ch!='k';
c. number >= 1 && number <= 9 && number != 5;
d. number < 1 || number >9
第10题:
***

#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;
}

image.png