2-基本语句

114 阅读14分钟

知识点一:数据类型转换

1、自动类型转换

自动类型转换关系图

//有符号 和无符号的转换
void test02()
{
    int data1 = ‐20;
    unsigned int data2 = 10;
    //有符号data1和无符号data2参加计算的时候
    //会先将data1转换成无符号(‐20的补码很大的正数)
    //很大的数 + 10 必然 >0
    if(data1+data2 > 0)
    {
    	printf(">0\n");	//>0
    }
    else if(data1+data2<0)
    {
    	printf("<0\n");
    }
}

//int double的转换
void test03()
{
    int data1 = 10;
    printf("%d\n",sizeof(data1+3.14));	//8字节
}

//char 和 short的类型转换
void test04()
{
    char ch = 'a';
    short data = 20;

    //由于char short自身字节数 过小 很容易溢出
    //所以 只要char short参加运算 都会将自身转换成int
    printf("%d\n", sizeof(ch + ch));//4
    printf("%d\n", sizeof(ch + data));//4
	printf("%d\n", sizeof(data + data));//4
}

2、强制类型转换    

形式:
   (类型说明符)(表达式)

例:(int)(x+y);	// 把x+y的结果值转换为整型
#include <stdio.h>
int test04()
{
    float x = 3.14f;
    int j = 0;
    //强制类型转换 只是临时的转换 当前语句有效,在后面的语句中不会更改x的值
    j = (int)x;
    printf("j = %d,x = %f\n",j,x);	//j = 3,x = 3.140000
    return 0;
}
int main(int argc,char *argv[])
{
    test04();
    return 0;
}

知识点二:运算符

1、运算符

算术运算符

+:加-:减
*:乘/ :取整(a/b a,b必须都为整数)(如果是浮点数是:除)
%:取余(a%b a,b必须都为整数)
#include <stdio.h>
int test05()
{
    printf("%d\n",5/2);  //取整,2
    printf("%d\n",5%2);  //取余,1
    printf("%d\n",5/2);	//2
    printf("%f\n",5/2.0f);	//2.500000
    return 0;
}
int main(int argc,char *argv[])
{
    test05();
    return 0;
}

复合运算符

+=:变量 = 左边加右边-=:变量 = 左边减右边*=: 变量 = 左边乘右边
/=:变量 = 左边取整右边%=:变量 = 左边取余右边
#include <stdio.h>
int test13()
{
    int data = 3;
    data *= 3+5;  //data = data *(3+5);
    printf("data = %d\n",data);	//data = 24
    return 0;
}
int main(int argc,char *argv[])
{
    test13();
    return 0;
}

2、关系运算符

>:大于<:小于= =:等于
>=:大于等于<=:小于等于!=:不等于

3、逻辑运算符

    &&:逻辑与

         A && B

         A B同时为真整个表达式结果为真, A B只要有一个为假整个表达式为假

         短路特性:如果第一个 A 就为假则后面不再执行 B

    ||:逻辑或

         A || B 只要A B任意一个为真,整个表达式结果为真,A B同时为假时结果才为假

         短路特性:如果表达式 A 为真,则表达式 B 不会进行运算

    !:逻辑非

        含义:如果原本表达式为真,则为假,原本表达式为假,则为真

4、位运算(二进制位操作)

&:按位与     语法:全1为1,其他为0

    例      1010 1010

    &       1111 0000

————————————————————————

             1010 0000

    特点:和1 相与 保持不变,和0 相与 全清零

    应用场景:将固定位清零

|: 按位或     语法:有1就为1,全0才为0

    例:     1010 1010

    |        1111 0000

————————————————————————————

             1111 1010

    特点:和0 相或 保持不变,和1 相或 全变1

    应用场景:将固定为1

~:按位取反

    语法:0变1,1变0

    ~ 1010 1010 == 0101 0101

    应用场景:配合&|操作

^:按位异或

    语法:相同为0不同为1

    例:     1010 1010

    ^        0000 1111

——————————————————————

             1010 0101

     特点:和0 异或 保持不变,和1 异或 取反

     应用场景:将固定的为发生高低电频翻转

5、左移和右移运算符

左移:左边丢弃,右边补0(1010 1100 << 2 == 1011 0000)

注意:移动的位数不要超过自身长度

右移分类:

    逻辑右移:右边丢弃,左边补0

    算术右移:

        符号数:右边丢弃,左边补0

        符号数:

            正数:右边丢弃,左边补0

            负数:右边丟弃,左边补1

总结:右移基本上是右边丢弃左边补0,只有负数且算术右移左边才会补1

逻辑右移和算术右移是编译器决定,但是我们可以检测

位数:从右到左数

综合例:将data的第1、5清0,第3, 4位 置1其他为保持不变 data:1010 1010

将data的第1、5清0:

    data = data & 1101 1101;

    1101 1101 = ~ (0010 0010) = ~ (0010 0000 | 0000 0010)

    0010 0000 = 0000 0001 << 5

    0000 0010 = 0000 0001 << 1

    1101 1101 = ~(0x01 <<5| 0x01<<1)

    data = data & ~(0x01<<5 | 0x01<<1)

清零:& ~(0x01<< 清零的位数(大) | 0x01<<清零的位数(小))

第3, 4位置1:

    data = data | 0001 1 000;

    0001 1000 = 0001 0000 | 0000 1000

              = 0x01<<4 | 0x01<<3

    data = data | (0x01<<4 | 0x01<<3);

    置1: | (0x01<< 置1的位数(大) | 0x01<< 置1的位数(小) )

6、条件运算符

形式:
    (表达式1)?(值1):(值2)	//(如果有嵌套看准 ? 分别)
    
//语法:如果表达式1为真,整个表达式的值为“值1”,否则为“值2"
void test01()
{
    int ret = 0;
    ret = 3 > 2 ? 5 : 6;
    printf("ret = %d\n", ret);	//5
}

7、逗号运算符

形式:
	(..., ..., ...)

//从左向右依次执行,最后的表达式的值是整个运算的结果
void test02()
{
    int data1 = 0;
    int data2 = 0;

    data1 = 3,4,5,6;
    data2 = (3,4,5,6);
    printf("data1 = %d\n", data1);	//3
    printf("data2 = %d\n", data2);	//6
}

8、自增自减运算符(++ --)

++i 或 - -i 先加、减,后使用

i++ 或 i- - 先使用,后加、减

注意: i++ 或 ++i 作为单独的指令没有区别

#include <stdio.h>
int test14()
{
    //++i
    int i = 3;
    int j = 0;
    j = ++i;   //++i == i=i+1     j=i
    printf("j=%d,i=%d\n",j,i);	//j=4,i=4
    //i++
    int i = 3;
    int j = 0;
    j = i++;   //j=i  i++ == i=i+1
    printf("j=%d,i=%d\n",j,i);	//j=3,i=4
    
    //i++ 或 ++i 作为单独的指令 没有区别
    int j = 3;
    int i = 3;
    i++;
    printf("i = %d\n",i);	//i = 4
    ++j;
    printf("j = %d\n",j);	//j = 4
    return 0;
}
int main(int argc,char *argv[])
{
    test14();
    return 0;
}

知识点三:优先级

优先级 高 先执行,同级别的优先级要看结合性

自己写代码时尽量用 ()

优先级别运算符运算形式结合方向名称或含义
1( )(e)自左至右圆括号
1[ ]a[e]自左至右数组下标
1.x.y自左至右成员运算符
1->p->x自左至右指针访问成员的指向运算符
2- +-e自右至左负号和正号
2++ --++x或x++自右至左自增和自减运算
2!!e自右至左逻辑非
2~~e自右至左按位取反
2(t)(t)e自右至左类型转换
2**p自右至左指针运算,由地址求内容
2&&x自右至左求变量地址
2sizeofsizeof(t)自右至左求某类型变量长度
3* / %e1 * e2自左至右乘、除、求余
4+ -e1 + e2自左至右加和减
5<< >>e1 << e2自左至右左移和右移
6< <= > >=e1<e2自左至右关系运算符(比较)
7== !=e1 == e2自左至右等于、不等于
8&e1 & e2自左至右按位与
9e1 ^ e2自左至右按位异或
10|e1 | e2自左至右按位或
11&&e1 && e2自左至右逻辑与(并且)
12||e1 || e2自左至右逻辑或(或者)
13()?():()e1 ? e2 : e3自右至左条件运算
14=x=e自右至左赋值运算
14+= -= *=自右至左复合赋值运算
14/= %= >>=x += e自右至左复合赋值运算
14<<= &= ^= |=自右至左复合赋值运算
15,e1,e2自左至右顺序求值运算

知识点四:键盘输入语句

格式:
    scanf("%相对应的字符输出格式", 要输入对应变量的地址);
#include<stdio.h>
int main(int argc,char *argv[])
{
    char ch;
    printf("请输入一个字符:");
    //scanf中%c只能提取一个字符
	//scanf("%c",&ch);
    ch = getchar();  //获取一个字符
    printf("ch = %c\n",ch);	//ch = a
    printf("ch = %d\n",ch);	//ch = 97
    return 0;
}

知识点五:if条件语句

1、if

形式:
if(表达式)	//项目只有一个结果
{
    语句1;
}
//运行方式:表达式为真才会执行语句1;
#include <stdio.h>
void test16()
{
    int data = 0;
    printf("请输入一一个int数据:");
    scanf("%d",&data);
    //判断能被2整除
    if(data % 2 == 0)
    {
        printf("被2整除");
    }
}
int main(int argc,char *argv[])
{
    test16();
    return 0;
}

2、if......else.....

if(表达式)		//如果项目的只有两种结果 且不会同时出现
{
    语句1;
}
else
{
    语句2;
}
//运行方式:表达式为真,执行语句1,否则执行语句2
#include <stdio.h>
void test16()
{
    int data = 0;
    printf("请输入一一个int数据:");
    scanf("%d",&data);
    //判断data对2的余数 结果:1或0
    if(data % 2 == 0)
    {
        printf("余数为0\n");
    }
    else
    {
        printf("余数为1\n");
    }
}
int main(int argc,char *argv[])
{
    test16();
    return 0;
}

3、if....else if.....else if.....else....

if(表达式1)	//如果一个项目有多个结果且不同时出现
{
    语句1;
}
else if(表达式2)
{
    语句2;
}
......
else	//可省略
{
    语句n;
}

//运行方式:只有表达式1为真,执行语句1,只有表达式2为真,执行语句2,所有表达式都为假才执行语句n
//注意:只有前面的条件不满足才会判断后面的条件,如果前面的条件满足后面的条件不管真假都不会执行
#include <stdio.h>
void test16()
{
    int data = 0;
    printf("请输入一一个int数据:");
    scanf("%d",&data);
    //判断data对3的余数  结果:0 1 2
    if(data % 3 == 0)
    {
        printf("余数为0\n");
    }
    else if(data % 3 == 1)
    {
        printf("余数为1\n");
    }
    else if(data % 3 == 2)
    {
        printf("余数为2\n");
    }
}
int main(int argc,char *argv[])
{
    test16();
    return 0;
}

4、if单个重复使用

一个项目有多个结果,不确定是否同时出现,其中每个if语句是独立的

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

知识点六:switch 选择语句

运行方式:将case后的值与switch后面的表达式的值对比,如果表达式的值刚好等于case后面的某一个值,就会立即去执行case后的语句,如果都不是,则会执行default后面的语句

形式:
switch(表达式)
{
    case1:          //值不能是浮点型、字符串
        语句1;
        break ;      //break作用:跳出循环但只能跳出离它最近的一层循环
    case2:
        语句2;
        break ;
    case3:
        语句3;
        break;
        ......
    default:         //可以省略
        语句n;
        break;
}
#include <stdio.h>
void test18()
{
    char ch = 0;
    printf("请输入你的方向:wsda\n");
    ch = getchar();
    switch(ch)
    {
        case'w':	//break省略
        case'W':
            printf("向上移动\n");
        break;
        case'A':
        case'a':
            printf("向左移动\n");
        break;
        case'S':
        case's':
            printf("向下移动\n");
        break;
        case'd':
        case'D':
            printf("向右移动\n");
        break;
    }
}
int main(int argc,char *argv[])
{
    test18();
    return 0;
}

continue

结束本次循环,立即从当前位置,进入下一次循环

#include <stdio.h>
void test02()
{
    int i,sum = 0;
    for(i = 1;i<=100;i++)
    {
        if(i == 50)
            continue;  //结束本次循环,立即从当前位置,进入下一次循环 
        sum += i;
    }
    printf("sum = %d\n",sum);	//sum = 5000
}
int main(int argc,char *argv[])
{
    test02();
}

知识点七:for循环

执行顺序:先执行初始语句,然后执行循环条件,如果循环条件成立,则执行循环语句,当语句块执行完毕之后,接着步进条件,然后再执行循环条件,如果循环条件成立,则继续执行循环语句,以此类推,直到循环条件不成立,循环结束

for(初始语句;循环条件;步进条件)
{
    //循环语句
}
//初始语句:只在循环开始时执行一-次
//循环条件: 每次循环都要执行,如果循环条件为 真 进入循环体,如果为 假 退出循环
//步进条件:每次循环结束的时候要执行的语句
#include <stdio.h>
void test02()
{
    int i,sum = 0;
    for(i = 1;i<=100;i++)
    {
        sum = sum + i;
    }
    printf("sum = %d\n",sum);	//5050
}
int main(int argc,char *argv[])
{
    test02();
}

嵌套for循环:总结外层循环的次数 * 内层循环的次数 == 总循环次数

for(初始语句;循环条件;步进条件)
{
     for(初始语句;循环条件;步进条件)
    {
         //循环语句
    }
}
void test07()
{	
    int i=0;
    int j=0;

    //总结 外层循环的次数 * 内层循环的次数 == 总循环次数
    for(i=0;i<10;i++)//0~9 =10
    {
        for(j=0;j<10; j++)//0~9 =10
        {
        	printf("i=%d, j=%d\n", i,j);//循环100次
        }
    }
}

知识点八:whie循环

执行顺序:如果“循环条件”为真就进入循环体执行循环语句,直到循环条件为假,循环结束

while(循环条件)
{
    //循环语句
}
//如果“循环条件”为真就进入循环体执行循环语句

while没有初始化语句,用户提前初始化好

while没有步进语句,用户必须在循环语句中写好步进语句

#include <stdio.h>
void test04()
{
    int i = 0;	//提前初始化
    int sum = 0;	//局部变量如果不初始化 内容不确定
    while(i<=100)
    {
        sum += i;
        i++;   //步进条件 
    }
    printf("sum = %d\n",sum);	//sum = 5050
} 
int main(int argc,char *argv[])
{
    test04();
}

知识点九:do.....while()循环

do
{
    //循环语句;
}while(循环条件);

//先执行循环语句,再判断循环条件是否为真,如果为真进行下次循环,如果为假,直接退出循环
#include <stdio.h>
void test05()
{
    int num = 0;
    do
    {
        printf("ok\n");	//输出一次ok
    }while(num>0);
} 
int main(int argc,char *argv[])
{
    test05();
}

知识点十:goto 跳转

void test()
{
    ....
    goto 跳转名;    //在需要跳转的语句插入
    ....            //中间是被调过的部分
    跳转名:         //跳转结束的地方插入
    .....
}
#include <stdio.h>
void test6()
{
    printf("---001----\n");
    printf("---002----\n");
    goto here;
    printf("---003----\n");		//不输出
    printf("---004----\n");		//不输出
    here:
    printf("---005----\n");
    printf("---006----\n");
} 
int main(int argc,char *argv[])
{
    test6();
}

如果循环的次数是确定的,建议选择 for

如果循环的次数不确定,知道退出的条件建议选择 while