算术运算符
计算机的核心任务简单描述就是读取输入的数据,然后进行相应的计算后输出。
C语言提供了丰富的运算符来实现数据的运算,常用的运算符有算术运算符、赋值运算符、自增自减运算符、逗号运算符、三目运算符、关系运算符和位运算符。
各个运算符都有优先级和结合性,所谓的优先级指的就是在多种运算符参与运算时先执行哪种运算,而结合性指的是只有在优先级相等时表达式运算的方向,也就是是从右向左,还是从左向右依次计算。
多个运算符和操作数在一起构成了表达式。
所谓的算术运算符就是数学意义上的加减乘除,然后在某些业务计算时还可能会用到求余数,C语言提供了取模运算符(%)来实现求余数。
优先级:C语言的算术运算符是先执行乘除运算,后执行加减运算。
结合性:如果是优先级相等的情况下是从左向右开始运算。
如果想更改运算符的优先级,可以通过使用()来实现,如下应用案例所示:
#include <stdio.h>
#include <stdlib.h>
/*
算术运算符的案例
@author tony [email protected]
@date 2017/11/26 13:26
@website www.ittimeline.net
*/
void operator_operator_num_expression() {
int num = 3 + 5; //+是运算符 3,5是操作符
int sum = 3 + (2 * 5);//表达式
int value = (1 + 2) * 3; //先乘除后加减,通过()提高优先级
value = ((1 + 2 + 3)*(9 - 5)) / (12 - 8); //()可以嵌套
int result = 1 + 2 - 3 + 4 - 5; //结合性 优先级相等的情况下 从左到右执行运算
//运算符不能相邻
//result = 1 + *3;
//乘号不能省略
//result = 6num;
system("pause");
}
只有整数才能求模运算,求模运算结果的符号和被除数相同,如下程序案例所示:
#include <stdio.h>
#include <stdlib.h>
/*
算术 操作符(取模)
@author tony [email protected]
@date 2017/11/26 13:28
@website www.ittimeline.net
*/
void alg_operator() {
int result = 1 + 3;//4
result = -3;//-3
result = 5 / 2; //2
double val = 3.5 * 2;
//整数才能取模
int remainder = 5 % 2;
remainder = -5 % 2; // -(5%2) 取模的结果的符号和被除数一样
int tmp = -5 % 3;//-2 被除数为正,取模结果为正,被除数为负,取模结果为负
tmp = -3 % 5; //-3
tmp = 5 % -3; //2
tmp = 3 % -5; //3
system("pause");
}
求模运算符可以实现数据的反转,如下应用案例所示:
#include <stdio.h>
#include <stdlib.h>
/*
使用取模运算符实现整数反转
@author tony [email protected]
@date 2017/11/26 13:32
@website www.ittimeline.net
*/
void reverse_num() {
int num = 87;
int unit = num % 10;
int tens_place = num / 10;
int reverse_val = unit * 10 + tens_place;
printf("%d反转之后的结果是%d\n",num,reverse_val);
system("pause");
}
在使用算术运算符执行数学运算时,需要注意参与运算的数据类型,运算结果的类型是参与运算的数据中占据内存空间最大的类型。
也就意味着数据类型在运算时会执行自动类型转换,例如两个整数执行算术运算,结果一定是整数。浮点数和整数执行算术运算,结果一定是浮点数。
取模运算常常用于大数据分割,游戏中修改数据的场景。
使用算术运算符实现5位数的整数反转
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdilib.h>
/*
使用取模运算符实现5位整数反转
@author tony [email protected]
@date 2017/11/29 23:26
@website www.ittimeline.net
*/
void reverse_num_extends() {
int num = 0;
printf("请输入你需要反转的五位正整数\n");
scanf("%d",&num);
printf("你输入需要反转的正整数是%d\n",num);
/*
实现思路,以12345为例
12345
个位: 12345%10=5;
十位: 12345%100=45/10=4
百位: 12345/100=123%10=3
千位: 12345/1000=12%10=2
万位: 12345/10000=1
*/
int unit = num % 10;
int tens_place = num % 100 / 10;
int hundred = num / 100 % 10;
int thousand = num / 1000 % 10;
int ten_thousand = num / 10000;
int reverse_result = unit * 10000 + tens_place * 1000 + hundred * 100 + thousand * 10 + ten_thousand;
printf("反转的结果是%d\n", reverse_result);
system("pause");
}
赋值运算符
赋值运算符就是将赋值号右边的表达式或者变量值赋值给左边的变量名(内存实体),在赋值运算符中涉及到两个概念:
左值:有内存实体的变量被赋值的称为左值。左值可以赋值给右值。
右值:能放在赋值号右边给其他变量赋值的值。
而且赋值时会完成自动类型转换。
优先级:赋值预算的优先级低于算术运算符
结合性:从右向左
赋值运算符还可以和算术运算符和位运算符结合使用,组合成复合赋值运算符,常用的复合赋值运算符有如下几种:
组合算术运算符 +=、-=、*=、/=、%=、
组合位运算符 <<=、>>= 、&=、 ^= 、|=
赋值运算符的综合案例如下应用案例所示:
#include <stdio.h>
#include <stdlib.h>
/*
赋值运算符 运算的顺序是从右向左开始运算
赋值号会执行类型转换
@author tony [email protected]
@date 2017/11/26 14:14
@website www.ittimeline.net
*/
void assignment() {
int num = 5;
num = 3;
//3 =num ; //编译错误 赋值左边必须是内存实体(变量)
int one, two, three; //声明多个整数变量
one = num; //右值num作为左值变量在这里可以赋值给左值变量one
printf("num=%d",num=4);//赋值表达式的结果就是num被赋值的变量
printf("%d\n",one=two=three=num=4);//结合性是从右边向左
//左值和右值
//左值:有内存实体的变量才能够赋值的值称为左值
//右值: 能放在赋值号右边,给其他变量赋值的值
int val = 10;
// 10 = val; 编译错误,
int target = val; //左值可以替换右值
target += 2; //等价于target=target+2
target -= 4; //等价于target=target-4;
const int height = 636.88; //赋值会完成制动类型转换
printf("height=%d\n",height);
//num+=12 ===>num=num +12
int intVal = 12;
int calcResult = intVal += intVal -= intVal*intVal; //等价于intVal=intVal+(intVal=intVal-(intVal*intVal))
printf("calcResult =%d\n",calcResult);
system("pause");
}
自增自减运算符
自增自减运算符是让变量自增1或者自减1,只能作用于变量,不能作用于常量或者表达式。
优先级:自增自减运算符的优先级高于算术运算符
结合性:从左向右
如下应用程序所示,说明了自增运算符的特性。
#include <stdio.h>
#include <stdlib.h>
/*
自增自减运算符的基本使用及其特性
@author tony [email protected]
@date 2017/11/26 14:48
@website www.ittimeline.net
*/
void auto_increment() {
int count = 10;
//count++;
++count;
//count++或者++count作为一个单独的语句存在,都是让count变量自增1
printf("count=%d", count);
int num = 10;
printf("num++ = %d\n", num++); //先赋值后自增1 打印结果num++=10 最终num=11
printf("++num = %d\n", ++num);//先自增1后赋值,打印结果++num=12 最终num=12
//自增运算符只能作用于变量,不能用在表达式和常量
//10++;
//(12+4)++
int height = 628;
int auto_increment_height = height++ + 3; //631 自增自减运算的优先级符高于算术运算符
printf("auto_increment_height = %d\n", auto_increment_height);
system("pause");
}
当自增(自减)运算符作为单独一行语句时,前置++和后置++没有区别。
需要注意的是如果自增自减运算符只是作用于变量,无论是前置++(–)或者后置++(–)的最终目的都是让变量的值自增1,但是一旦自增的变量参与其他数据参与运算时,前置++(–)会先自增(自减)1后再参与运算,而后置++(–)会先参与运算后再自增(自减)1。
它们通常用于控制循环变量的场景,如下应用程序所示:
#include <stdio.h>
#include <stdlib.h>
/*
自增运算符的案例
@author tony [email protected]
@date 2017/11/26 14:59
@website www.ittimeline.net
*/
void auto_increment_sample_loop() {
for (int i = 1; i < 100;i++) {
if (i%5==0) {
printf("1-100以内能被5整除的数字是i=%d\n",i);
}
}
system("pause");
}
自增自减运算符的综合案例如下应用所示:
#include <stdio.h>
#include <stdlib.h>
/*
自增运算符的案例
@author tony [email protected]
@date 2017/11/26 14:48
@website www.ittimeline.net
*/
void auto_increment_sample() {
int j = 3;
printf("j =%d\n", j);//3
int k = ++j; //4;
printf("k=%d\n", k);//3
k = j++;//5
printf(" j = %d\n",j);
printf("++j = %d\n",++j); //6
printf("j++ = %d\n", j++); //6
int a = 3, b = 5;
int c = (++a)*b;//20
printf("c= %d\n", c); //
c = (a++)*b;//20
printf("c= %d\n", c); //
system("pause");
}
逗号运算符
用逗号将多个表达式连接起来,又称为“顺序求值运算符”,整个表达式的值是最后那个逗号之后的表达式的值,而且每个逗号分割的表达式都会去执行。
优先级:所有运算符中优先级最低的
结合性:自左向右
逗号运算符的综合案例如下应用程序所示:
define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
/*
逗号运算符也叫顺序求值运算符,计算结果是最后一个逗号的表达式的值
逗号运算符可以串联多条语句,按照从左到右的顺序执行运算,逗号运算符是所有运算符中的优先级最低的
@author tony [email protected]
@date 2017/11/26 15:21
@website www.ittimeline.net
*/
void comma_alg() {
int val = (1, 2, 3); //逗号运算符的结果是最后一个值
printf("val=%d\n", val);
system("pause");
//当逗号之间有多个表达式时从左向右开始依次执行
system("calc"), system("notepad"), system("tasklist"), system("pause");
//运算结果是最后一个值
printf("%d\n", (3 + 4, 6)); //6
int a = 0;
printf("result= %d\n", (a = (a = 3, 6 * 3))); //18
printf("result= %d\n", (a = a = 3, 6 * 3)); //18
printf("result= %d\n", (a = 3, a += 2, a + 3));//8
printf("result= %d\n", (a = 3 * 5, a * 4)); //60
printf("result = %d\n", ((a = 3 * 5, a * 4), a + 5));//((a=15,60),15+5)=20
system("pause");
}
三目运算符
三目运算符是简单版的if/else语句,其语法结构为表达式1?表达式2:表达式3,如果表达式1的结果为非0,那么执行表达式2的语句,否则就去执行表达式3的语句,C语言中以非0和0来区分真和假。
优先级:三目运算符的优先级高于赋值运算符
结合性:自右向左
三目运算符的综合案例如下应用程序所示:
#include <stdio.h>
#include <stdlib.h>
/*
三目运算符 :表达式1?表达式2:表达式3
如果表达式1的运算结果为非0,三目运算符的结果为表达式2,否则为表达式3
优先级:高于赋值运算符
结合性:从右向左开始执行运算
@author tony [email protected]
@date 2017/11/26 15:35
@website www.ittimeline.net
*/
void ternary_sample() {
0 ? system("calc") : system("notepad"); //表达式1的结果为0 执行打开记事本
int left = 100;
int right = 88;
int max = left > right ? 100 : 99; //取两个数中的最大值
printf("max = %d\n", max);
//复杂的三目运算符
int one = 5, two = 6, three = 7, four = 8;
printf("result = %d\n", one>two ? one : three>four ? three : four); //根据优先级和结合性(自右向左)的计算结果为8
system("pause");
}
根据三目算符获取四个整数中的最大值的应用案例,如下所示:
#include <stdio.h>
#include <stdlib.h>
/*
获取四个整数中的最大值
@author tony [email protected]
@date 2017/11/26 15:35
@website www.ittimeline.net
*/
void get_max_num() {
//声明并初始化赋值四个整数变量
int one = 79;
int two = 214;
int three = 100;
int four = 1;
//分解步骤
int get_max_from_one_two= one > two ? one : two;
int get_max_from_three_four = three > four ? three : four;
int max = get_max_from_one_two > get_max_from_three_four ? get_max_from_one_two : get_max_from_three_four;
//组合表达式
max = (one > two ? one : two) > (three > four ? three : four) ? (one > two ? one : two) : (three > four ? three : four);
printf("max =%d\n",max);
system("pause");
}
关系运算符
关系运算就是两个操作数进行比较,例如在选择投资平台时,通常会考虑该平台的成立时间、以及累计交易的金额等因素作为比较的依据。而程序实际上就是对现实生活中的业务逻辑进行仿真。
常用的关系运算符有大于(>),大于等于(>=),小于(<),小于等于<=,相等(==),不相等!=,而对两个操作数进行关系运算后的结果为1(逻辑真)或者是0(逻辑假)
优先级:算术运算符和逻辑运算符之间
结合性:自左向右
关系运算符的应用案例如下所示:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define 技术分 80
/*
关系运算符的案例
@author tony [email protected]
@date 2017/11/26 15:35
@website www.ittimeline.net
*/
void relation_sample() {
int num;
printf("请输入你的技术分\n");
scanf("%d",&num);
num >= 80 ? system("echo 欢迎你加入") : system("echo 回家等电话");
system("pause");
}
关系运算符通常是结合逻辑运算符使用,如下应用程序所示:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define 经营年限 8
#define 交易金额 20000000000 //以元为单位
/*
关系运算符结合逻辑运算符
@author tony [email protected]
@date 2017/11/28 15:35
@website www.ittimeline.net
*/
void relation_sample_extends() {
int year = 0;
unsigned long long money = 0;
printf("请输入你期待的投资平台的经营年限\n");
scanf("%d",&year);
printf("请输入你期待的投资平台的交易金额\n");
scanf("%llu", &money);
year >= 经营年限 && money >= 交易金额 ? system("echo 我打算投资你们平台") : system("echo 我不打算投资你们平台");
system("pause");
}
关于相等性判断时,浮点数需要考虑精度问题,而同一个字符串常量通常是相等的,但是变量就不相等了,因为此时判断的是内存地址,如下应用程序所示:
#include <stdio.h>
#include <stdlib.h>
/*
常用数据类型在关系运算符的相等性判断
@author tony [email protected]
@date 2017/11/28 15:35
@website www.ittimeline.net
*/
void releation_calc() {
printf("3>4的结果是%d\n",(3>4));//不成立 运算结果为0
printf("3>2的结果是%d\n", (3>2));//成立 结果为1
printf("3>2>1的结果是%d\n",(3>2>1));//从左向右开始运算 3>2的结果是1 但是1>1的结果是0 因此结果是0
//浮点数的相等性判断
double dbVal1 = 1.00000000000000000000000000000000000000000000000000000000000092;
double dbVal2 = 1.00000000000000000000000000000000000000000000000000000000000103;
//在使用浮点型的数据进行相等性比较时需要注意精度问题
printf("dbVal1 == dbVal2 %d\n",(dbVal1==dbVal2));
"刘光磊" == "刘光磊" ? printf("相等\n"):printf("不相等\n");//字符串常量值得地址是同一份
char str1[100] = "刘光磊";
char str2[100] = "刘光磊";
printf("str1 == str2 %d\n",str1==str2); //这里比较的是内存地址, str1和str2属于不同的内存地址
system("pause");
}
逻辑运算符
逻辑运算符用来做表达式的逻辑判断,主要有逻辑与(&&),逻辑或(||)和逻辑非(!)三种逻辑运算,它们的特性如下所示:
逻辑与:&&运算符左右两边的表达式(或者多个表达式)运算结果都为真,逻辑与的运算结果就为真,否则结果就为假
逻辑或:||运算符左右两边的表达式(或者多个表达式)中有一个表达式的运算结果为真,逻辑或的运算结果就为真,否则就为假
逻辑非:用于表达式取反,真变成假,假变成真
优先级(从高到低):!->算术运算符->关系运算符->&&->||->赋值运算符
结合性:自左向右
逻辑与的应用案例如下所示:
三个科目的分数必须大于等于145分,才能被清华大学录取,只要有一门不满足,就不能录取
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
/*定义三个常量 三门成绩的录取分数*/
#define 语文 145
#define 数学 145
#define 英语 145
/*
逻辑与运算符
@author tony [email protected]
@date 2017/11/28 12:32
@website www.ittimeline.net
*/
void logic_and() {
int chinese = 145;
int math = 145;
int english = 145;
chinese >= 语文&&math >= 数学&&english >= 英语 ? printf("你被清华录取了\n"):system("echo 记录努力吧");
chinese = 140; //修改分数
printf("修改语文成绩为140分之后判断是否考取清华大学的结果为");
//只要有一个条件不满足,结果为假
chinese >= 语文&&math >= 数学&&english >= 英语 ? printf("你被清华录取了\n") : system("echo 记录努力吧");
system("pause");
}
逻辑或的应用案例如下所示:
即使三科的成绩没有都大于等于145分,但是总分大于等于435,满足逻辑或,因此可以被录取
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
/*定义三个常量 三门成绩的录取分数*/
#define 语文 145
#define 数学 145
#define 英语 145
/*
逻辑或运算符
@author tony [email protected]
@date 2017/11/28 12:32
@website www.ittimeline.net
*/
void logic_or() {
int chinese = 145;
int math = 142;
int english = 148;
int total = chinese + math + english;
(chinese >= 语文&&math >= 数学&&english >= 英语) ||(total>=435)? printf("你被清华录取了\n") : system("echo 记录努力吧");//
system("pause");
}
逻辑非的应用案例如下所示:
10>20的关系运算结果为0,但是加上逻辑非运算后结果变成了1
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
/*
逻辑非运算符
@author tony [email protected]
@date 2017/11/28 12:32
@website www.ittimeline.net
*/
void logic_not() {
int num = 10;
int val = 20;
printf("10 >20 逻辑非的运算结果是%d\n",!(num>val));
system("pause");
}
逻辑与和逻辑或在运算时还存在着短路特性:当明确整体的表达式的运算结果以后,余下的表达式将不会再执行,如下应用程序所示:
#include <stdio.h>
#include <stdlib.h>
/*
逻辑与和逻辑或的短路效应
@author tony [email protected]
@date 2017/11/29 22:24
@website www.ittimeline.net
*/
void logic_short_circuit() {
int num = 10;
0 && ++num;
printf("逻辑与的短路特性 num = %d\n",num); //输出结果为num=10 ,因为&&左边的表达式结果为0,因此整个表达式的结果就是0,因此后面的++num不会再执行
1 || ++num;
printf("逻辑或的短路特性 num = %d\n", num);//输出结果依然为num=10,因为||左边的表达式结果为非0,,因此整个表达式的结果就是非0,因此后面的++num不会再执行
system("pause");
}