运算符
% 是算术运算符的重点,一般将某个数值控制在一定范围内,还有数据解析上
// 产生随机数,控制在5以内
int ret = rand() % 5;
printf("%d\n",ret);
return 0;
取模运算要求左右两边操作数必须是整型数据
例如: 1.5 % 0.5 (错误)
自加自减运算不仅可以对整型操作,也可以对浮点数、指针操作
1)单目运算符 目:目标操作数
++ -- +(正号) -(负号)
编译出现的常见错误:error: multiple unsequenced modifications to [-Werror,-Wunsequenced]//多次非顺序修改
总结就是不要将自增或自减运算符与赋值运算符等其他运算符复合使用。
2)双目运算符:+ - * /
printf("%d\n",3/2);// 一个整数除以另一个整数,小数被舍弃
printf("%f\n",3*1.0/2);// 如果想要小数,那么可以*1.0,隐式类型转换 1.500000
printf("%d\n",10%3);//%取余运算符的左右两边必须都是整数
// 一般取余运算符在我们编程开发中用于控制数据的大小范围
srand(time(NULL));// 获取随机数因子
int a9 = rand()%5;// rand()得到一个随机数0-4
printf("%d\n",a9);
2. 关系运算符
注意关系运算符的值为布尔值 也就是说要么关系成立(1) 要么不成立(0)
1 > 10 20 < 30
int a = 10; int b = 20;
a != b;// 1
a == b; // 0
3. 逻辑运算符
运算规则:
-
逻辑反:将逻辑真、假翻转,即真变假,假变真
-
逻辑与:将两个关系表达式串联起来,当且仅当左右两个表达式都为真时,结果为真。
-
逻辑或:将两个关系表达式并联起来,当且仅当左右两个表达式都为假时,结果为假。
-
特殊规则(惰性运算)
-
在逻辑与运算中,如果左边表达式的值为假,那么右边表达式将不被执行。
-
在逻辑或运算中,如果左边表达式的值为真,那么右边表达式将不被执行。
4. 位运算符(重点,对整个变量的某一位操作)
^ : 按位异或 --- 不同为1,相同为0
-
1 ^ 0 == 1
-
0 ^ 1 == 1
-
0 ^ 0 == 0
-
1 ^ 1 == 0
注意:%u无符号输出,直接以补码的方式输出,%d以补码还原的方式输出
unsigned char ret = ~0x05;// 0000 0101--> 1111 1010
//%u无符号输出,直接以补码的方式输出,%d以补码还原的方式输出
printf("%hhu\n",ret);// 250
printf("%hhd\n",ret);// -6
有符号左移 (注意步骤)
有符号右移 (注意补1,而不是补0)
例如: -96 >> 5 //-3
位运算符操作的对象是数据中的每一位
5. 特殊运算符
// 注意(从右往左)连续赋值
a = b = 50; // 先将 50 赋给 b,再将 b 的值赋给 a,正确
复合赋值符
除了下述10个复合运算符之外,生造别的复合运算符是非法的
// 加减乘除:
a += n; // 等价于 a = a+n;
a -= n; // 等价于 a = a-n;
a *= n; // 等价于 a = a*n;
a /= n; // 等价于 a = a/n;
// 求余:
a %= n; // 等价于 a = a%n;
// 位运算:
a &= n; // 等价于 a = a&n;
a |= n; // 等价于 a = a|n;
a ^= n; // 等价于 a = a^n;
a >>= n; // 等价于 a = a>>n;
a <<= n; // 等价于 a = a<<n;
6. 条件运算符(三目运算符,重点)
int a = 100;
int b = 200;
int m = (a>b) ? a : b; // 如果 a>b 为真,则 m 取 a 的值,否则取 b 的值
7. sizeof 运算符
含义:计算指定数据类型或者变量所占据内存的字节数
语法:sizeof(类型)、sizeof(变量),计算变量的字节数时圆括号可以省略
8. return运算符
9.逗号表达式:
10. 优先级与结合性
控制流
二路分支
形式:
-
if语句:表达一种 如果-则的条件执行关系
for(int i=1; i<=100; i++)
{
if(i%7 == 0)
continue; // 跳过所有能被7整除的数
printf("%d\n", i);
}
-
if-else语句:表达一种 如果-否则 的互斥分支关系
不管是if语句还是else语句,代码块都必须使用大括号{}括起来,否则只有首句有效
多路分支:switch...case
练习1:制作一个简单的打分系统(满分制:100),使用switch...case方法,分数需整数
60分以下:评级为D
60-80分 : 评级为C
80-90分 : 评级为B
90-100分: 评级为A
不在0-100范围内:错误
#include <stdio.h>
int main(int argc, char const *argv[])
{
int score;
printf("请输入成绩: ");
scanf("%d",&score);
switch (score)
{
case -1:
printf("卷子丢了\n");
break;
case 0 ... 60:
printf("D\n");
break;
case 61 ... 80:
printf("C\n");
break;
case 81 ... 90:
printf("B\n");
break;
case 91 ... 100:
printf("A\n");
break;
default:
printf("成绩输入有误");
}
return 0;
}
要点解析
-
switch(n)语句中的n必须是一个整型表达式,即switch判断的数据必须是整型或者字符
-
case语句只能带整型常量,包括普通整型或字符,不包括const型数据
-
break语句的作用是跳出整一个switch结构,没有break程序会略过case往下执行
-
default语句不是必须的,一般放在最后面(因此不需要break)
练习2:计算加盟费
小张加盟一家餐饮企业,在每个季度结束后,小张必须向总部缴纳加盟费,加盟费与营业额的提成关系如下:
营业额 提成系数
0<=n<10w 0.1
10<=n<20w 0.075
20<=n<40w 0.05
40<=n<60w 0.03
60<=n<100w 0.015
n >= 100w 0.01
请输入小张的营业额,然后求出它需要的提交的加盟费
/*
*解题思路:
1.使用二路分支来标记营业额
2.使用二路分支的标记作为多路分支的条件
*/
#include <stdio.h>
int main(int argc, char const *argv[])
{
float money; // 营业额
float val; // 提成
int flage; // 记录营业额范围
printf("请输入营业额(万元): ");
scanf("%f",&money);
// 营业额
if(money < 0)
{
printf("找个班上吧,别开了\n");
}
else if(0 <= money && money <= 10)
{
flage = 1;
}
else if(10 < money && money <= 20)
{
flage = 2;
}
else if(20 < money && money <= 40)
{
flage = 3;
}
else if(40 < money && money <= 60)
{
flage = 4;
}
else if(60 < money && money <= 100)
{
flage = 5;
}
else if(money > 100)
{
flage = 6;
}
// 提成
switch (flage)
{
case 1:
val = 0.1;
break;
case 2:
val = 0.075;
break;
case 3:
val = 0.05;
break;
case 4:
val = 0.03;
break;
case 5:
val = 0.015;
break;
case 6:
val = 0.01;
break;
default:
break;
}
// 输出加盟费
printf("加盟费: %.2f万元\n",money * val);
return 0;
}
const
逻辑:使一个变量不可修饰
while与do...while循环
do-while 循环中的 while 语句后面有分号;
for循环
for(初始表达式1;判断表达式2;循环操作表达式3)
{
循环体;
}
1. 如果我们不能确定程序什么时候能退出则使用while
2. 如果我们能确定程序什么时候能退出则使用for
3. while注重循环条件,for注重循环次数
break(退出)与continue(继续)
-
运用场景与特点
-
break关键字只能用于循环(while for do...while)和switch语句中,表示结束循环或者跳出switch语句
-
break关键字只能跳出最近一层的循环,也就是说,如果有多重循环,只能跳出最靠近break语句那层循环
-
break关键字 不能 单独用于 if语句中,除非if语句外面包含了循环
-
-
逻辑:
-
continue关键字只能用于循环体中(while do...while for),用于提前结束当前循环体后,又从最近一层循环体开始执行
-
continue关键字不能 单独用于 if语句或者switch 语句中,除非外面包含了循环
-
break:① 跳出 switch 语句; ② 跳出当层循环体while(1){while(1){break;}}
-
continue:结束当次循环,进入下次循环
-
#include <stdio.h>
int main(int argc, char const *argv[])
{
// 输入字母
char ch;
printf("请输入字母: ");
scanf("%c",&ch);
if(ch < 'A' || ch > 'Z')
{
printf("输入出错, 请重新输入大写字母\n");
return -1;
}
// 计算总行
int line = ch - 'A' + 1;
int i ,j;
for(i = 1; i <= line; i++)
{
// 计算空格
for(j = 0; j < line - i; j++)
{
printf(" ");
}
// 输出升序字母
for(j = 0; j < i; j++)
{
printf("%c",'A'+j);
}
// 输出降序字母
for(j-=2; j >= 0; j--)
{
printf("%c",'A'+ j);
}
printf("\n");
}
return 0;
}
goto语句
作用:
-
goto语句的无条件跳转不利于程序的可读性,一般不建议使用
-
goto语句常被用在程序的错误处理中
int main() { printf("%d\n", __LINE__); // 打印第3行 // 无条件跳转到label处 goto label; printf("%d\n", __LINE__); // 打印第7行,此处被略过 label: printf("%d\n", __LINE__); // 打印第9行 }
初识数组
格式
-
类型说明符 数组名[整型常量表达式];
-
类型说明符:指定数组元素的数据类型,任意c语言合法类型都可以
-
数组名 : c语言标识符,其值为该数组的首地址(常量)
-
整型常量表达式:指定数组元素的个数
// 循环给数组a赋值 for(int data = 10,i = 0; i < 5; i++,data+=10) { a[i] = data; } // 遍历输出 for(int i = 0; i < 5; i++) { printf("%d\n",a[i]); }
测量数组的总大小:sizeof(array)
测量数组元素个数:sizeof(array)/sizeof(array[0])#include <stdio.h> int main(int argc, char const *argv[]) { // 根据初始化的时候分配空间从而确定数组的大小 int Array[] = {10,20}; printf("%d\n",sizeof(Array)); // 计算数组的元素个数 int count = sizeof(Array) / sizeof(Array[0]); printf("数组空间个数: %d\n",count); return 0; }
练习
结果:
字符数组
概念:专门存放字符的数组,称为字符数组
#include <stdio.h>
int main(int argc, char const *argv[])
{
char Array[6] = {'D','A','V','I','D','\0'};
// 输出字符串用%s
printf("%s\n",&Array[0]);//DAVID
printf("%s\n",Array);//DAVID
注意,数组名(比如Array
)本身就是一个指向数组第一个元素的指针,因此&Array[0]
可以简化为Array
,即printf("%s\n", Array);
也是合法的,并且会产生相同的结果。
char Array1[6] = {"DBVID"};// ""表示字符串,字符串末尾有\0
printf("%s\n",Array1);
// 最常用的方法
char Array2[6] = "DAVD";
printf("%s\n",Array2);
return 0;
}
数组偏移量
数组元素地址解引用
通过对数组元素地址解引用,可以获取地址空间里面的数据
int a = 10;
printf("%d\n",a);
printf("%p\n",&a);
// * 表示将地址里面的内容取出,我们把它称为解引用
printf("%d\n",*(&a));
//--------------------------
char Array[5] = {'j','a','c','k'};
printf("%c\n",Array[0]);
printf("%c,%c\n",*(Array+0),*(&Array[0]));
printf("%c,%c\n",*(Array+1),*(&Array[1]));
printf("%c,%c\n",*(Array+2),*(&Array[2]));
printf("%c,%c\n",*(Array+3),*(&Array[3]));
字符串常量