一、格式化IO函数
scanf、printf分别是输入和输出。
1)作用:
printf:用于在屏幕(标准输出)上输出各种类型的数据
scanf:用于获取键盘(标准输入)输入的各种类型数据
2)原理:
scanf和printf共用一个缓冲区
scanf工作原理:
读取单个变量:scanf("%d",a);
读取多个变量:scanf("%d%c",&a,&c);//scanf("输入数据类型",输入到存储方式)
printf工作原理:
先将数据存放在缓冲区中,当遇到回车时,return exit()缓冲满了,scanf和printf切换使用的时候就会刷新缓冲区,达到在液晶屏上显示的目的。
printf("%d\n",a);//将a以%d的形式输出在屏幕上,\n为换行符
printf("%d %f %lf %s",a,b,c,d)//分别输出整型,float型,double型,字符串
3)使用scanf可能遇到的问题和解决方法
1、输入一个完整数,然后输入一个字符
输入一个完整数后,回车会被当成字符读取,导致没办法输入新的字符
解决方法:调用C语言库的getchar()
int getchar(void);//作用是从缓冲区读取一个字符
返回值:读取到的字符的ASCII码值
2、scanf("%d"),输入123hello只读取123
输入123.456只读取123
解决方法:使用getchar()读取一下看123后面跟着的是不是\n
3、读取字符串时,遇到空格会结束读取
解决方法:scanf("%[\n]",buf);//这里的意思是读取到\n才结束,[^\n]是正则表达
4)查看linux的帮助手册
man man
1 Executable programs of shell commands
//linux系统中可以使用的所有命令
2 System calls (functions provided by the kernel)
//linux系统提供的函数
3 Library calls (functions within program libraries)
//C语言库函数
例如:man 3 _exit //在第三本手册中查询_exit介绍
man 3 printf //在第三本手册中查询printf介绍
------------------------------------------------------------------------------------------
二、运算符
1)运算符分类
1、算术运算符
+ - * / %(取余)
除法:
整数除以整数--》结果取整(不四舍五入)
小数和整数相除--》结果是小数
1/2 = 0
1.0/2 = 0.5
1/2.0 = 0.5
1.0/2.0 = 0.5
取余数:
只能针对整数
10%3 = 1
实际应用:
例子1:取余和除法配合,求出一个整数的个位数
例子2:
for(int i = 0;i < n;i++) //n为循环次数
{
if(i%4 == 3) //每过四个元素就换行
{
printf("\n");
}
}
2、逻辑运算符(多个条件的真假)
逻辑与&&(并且) 逻辑或||(或者) 逻辑非!
使用方法:跟条件判断配合使用,表示复杂的条件
if(a>1&&a<10&&.....)
逻辑与
从左到右(结合性),只要有一个条件为假,后面的表达式不需要判断,整个条件判断为假
比如:int a = 99;
int b = 65;
//if((a>b) && (a+=10) && (b=a+1))
if((a<b) && (a+=10) && (b=a+1))
if((a>b) && (a+=10) && (b=a+1))
printf("a b is:%d %d\n",a,b);
else
printf("a b is:%d %d\n",a,b);
逻辑非
真--》假
假--》真
例:
int a = 99;
int b = 65;
if(!(a>b))
重难点:把逻辑与跟逻辑或混在一起。
逻辑与跟逻辑或混在一起整体看成是逻辑或运算(原因是逻辑与优先级高)
把逻辑与括起来作为一个整体先不理会,然后其余部分(只剩下逻辑或)从左到右计算
表达式1&&表达式2||表达式3 --》(表达式1&&表达式2)||表达式3
表达式1||表达式2&&表达式3 --》表达式1||(表达式2&&表达式3)
情况1:条件1 || 条件2&&条件3 || 条件4
例:if((a>b) || (a = a+10) && (b = b - a) || (a - b < 3))
整体看成逻辑或,从左到右计算,中间的条件2和条件3看成整体
情况2:条件1 && 条件2 || 条件3 || 条件4
例:if((a > b) && (a = a + 10) || (b = b - a) && (a - b < 3))
情况3:条件1 || 条件2 || 条件3 && 条件4
if((a > b) || (a = a + 10) || (b = b - a) && (a - b<3))
混合计算,由于&&优先级高,所以先用括号把&&括起来作为一个整体,其它部分(其他部分都是逻辑或)按照从左到右的顺序计算。
优先级:逻辑非>逻辑与>逻辑或
3、关系运算符
> < >= <= != ==
易错点:
(1)
10<x<100 数学这样写没有错,但是意思发生改变了,先判断x是否大于10,结果要么真,要
么假,然后判断真假是否小于100
if(x>10&&x<100) C语言正确写法
(2)
==和=区分开
==是判断相等
=是赋值运算
if(a = 100)//这里会将100赋值给a
if(a == 100)//这里是判断a的值与100是否相等
语法错误和逻辑错误:
语法错误:通过编译器能直接识别出来的错误;
逻辑错误:编译器无法识别,只能程序员自己去调试寻找错误原因。
左值和右值:
左值:赋值运算左边的式子
右值:赋值运算右边的式子
函数调用的返回值
左值不能是表达式,只能是变量,不能是常量
区分左值和右值的方法:左值可以取地址,右值不行
C语言:
int x,y;
x + y = 10;//错误,左值不能是表达式
x + 1 = 10;//错误,左值不能是表达式
x = 10 - 1;//正确,右值可以是表达式
4、位运算符
(1)背景知识
C语言去操作访问硬件寄存器的地址,会经常用到位运算
(2)位运算,针对数据的二进制位进行运算
位于& 位或| 位取反~ 异或^
注意:在进行位运算的时候,如果位数不够,在高位补0对齐,然后再计算
(3)位与&
15&12 结果
15--》二进制 1111
12--》二进制 1100 按位与/位与
1100
有一个为0,结果就是0
任何数跟0位与,结果都是0
位或|
有一个为1,结果就是1
15 | 5 结果
15 --》 二进制 1111
5 --》 二进制 0101 位或
1111
位取反~
0--1 1--0
~5
5 --》二进制 101
010
异或^
相同为0,相异为1
15^5 结果
15 --》二进制 1111
5 --》二进制 0101 异或
1010
5、三目运算符
表达式1?表达式2:表达式3
先判断表达式1是否为真
为真:执行表达式2
为假:执行表达式3
(a > b)?a:b //求a和b的最大值
6、其他运算符
组合运算符,左移右移,自增自减,sizeof,成员运算符,取地址,解引用
组合运算符:
+= -= *= /= %= <<= >>= &= |= ~= ^=
a += b;//等价于a = a + b;
a &= b;//等价于a = a & b;
......
左移右移:
左移:数据本身向高位移动,高位被舍弃,地位补0
左移n位相当于数据乘以2的n次方(不严谨)
例: int 12<<2 --》求出12的二进制 0000......1100<<2 -->结果000......110000
2^3+2^2 2^5+2^4
右移:算数右移和逻辑右移
算数右移:数据本身向低位移动,舍弃低位,高位补符号位
逻辑右移:数据本身向低位移动,舍弃低位,高位补0
不同的操作系统采用的右移方式是不同的
例:ubuntu采用的是算数右移
例:int -12 >> 2
-12的二进制补码:1111111111...0100
算数右移:1111111111...01
逻辑右移:0011111111...01
自增和自减:
int a = 88;
int b = a++;//后置的++,先赋值b = a,再对a进行+1操作
int c = ++a;//前置的++,先对a进行+1操作,再将a赋值给c
int b = a--;//后置的--,先赋值b = a,再对a进行-1操作
int c = --a;//前置的--,先对a进行-1操作,再赋值c = a;
难点:
int a = 10;
printf("%d %d %d %d\n",a++,a++,++a,++a);
知识点1:printf连续打印多个变量,值是从右到左计算的(涉及出入栈知识点,把栈看成羽毛球筒,先放进去的羽毛球后出,后放进去的羽毛球先出,即先打印的后计算,后打印的先计算);
知识点2:连续打印a++和++a的区别(++a是先自增,用新值,a++是用旧值再自增)
求数据类型,变量大小
sizeof(int);//求数据类型int的大小
sizeof(a);//求变量a的大小
//sizeof括号里面的表达式不参与计算
成员运算符:
例:struct student{};//定义一个结构体,成员包括name、age等;
则有student.name、student->age//这里的.和->就是成员运算符用于结构体和共用体
取地址符& 解引用符*//这个后面写到指针的时候会提到
逗号表达式:
变量 = (表达式1,表达式2,表达式3......);
运算规则,从左到右,最终的结果由最后一个表达式来决定。
============================================================
三、循环
1)三种循环
for while do-while
for循环和while循环:入口循环(先判断条件真假,为真才进行循环)
do-while循环:出口循环(先执行了,然后再判断条件)
return 0;//函数没有问题就返回0
return -1;//函数有问题就返回-1
复合语句(语句块)
用花括号括起来的一段代码称之为复合代码
2)分别介绍三种循环
for(表达式1;表达式2;表达式3)
{
循环体
}
表达式1:初始化
表达式2:条件判断
表达式3:循环变量的更新
//写法一:
int i;
for(i = 0;i < 5;i++) //递增循环
for(i = 5;i > 0;i--) //递减循环
//写法二:
for(int i = 0;i < 5;i++)//循环里定义i,这个i只能在定义的循环里使用
//写法三:
for(;i<5;i++)//必须在for循环里面定义好i,并且给i赋值
//写法四:
for(;i<5;)//表达式3必须写在循环里面
//写法五:
for(;;)//死循环
//写法六:
for(i = 0,j = 1;i < 5,j < 10;i++,j++)//表达式2用了逗号表达式,由最右边来决定循环条件即j<10;
for(i = 0,j = 1;i < 5&&j < 10;i++,j++)//此时表达式2用了逻辑与
循环的嵌套:
先判断外层循环,再判断里面的循环
for(i = 0;i < 5;i++) //外层循环
{
for(j = 0;j < 6;j++)//内层循环
{
}
if(...)//其他语句
{
break;//退出这层循环
}
}
循环的语法细节:
//细节一:循环的花括号什么样的情况下可以省略
for(i = 0;i < 5;i++)
printf("i is :%d\n",i);
printf("循环执行中!\n");//由于没有使用花括号,编译器只会把上一句打印i值的语句作为循环语句
for(i = 0;i < 5;i++)
for(j = 0;j < 6;j++)
{
//循环语句
}
//会执行这个循环
//细节二:在循环里面重复定义同一个变量,行不行?
可以,在循环里面重复定义的变量,都是同一个变量