C# 零基础到精通教程 - 第三章:运算符与表达式——让程序真正“算“起来
3.1 什么是运算符和表达式?
3.1.1 基本概念
运算符:告诉计算机要对数据做什么操作(比如加法、比较、赋值)
表达式:由运算符和操作数组成的式子(比如a + b)
csharp
int a = 5; int b = 3; int sum = a + b; // a + b 是表达式,+ 是运算符,a 和 b 是操作数
3.1.2 C# 运算符分类总览
| 分类 | 运算符 | 优先级 | 结合性 |
|---|---|---|---|
| 算术运算符 | + - * / % ++ -- |
高 | 从左到右 |
| 赋值运算符 | = += -= *= /= %= |
低 | 从右到左 |
| 比较运算符 | == != > < >= <= |
中 | 从左到右 |
| 逻辑运算符 | && || ! |
中 | 从左到右 |
| 位运算符 | & | ^ ~ << >> |
中 | 从左到右 |
| 条件运算符 | ? : |
低 | 从右到左 |
| 其他 | typeof sizeof is as ?? |
各异 | 各异 |
本章重点学习:算术、赋值、比较、逻辑运算符,这些是日常最常用的。
3.2 算术运算符(做数学计算)
3.2.1 基本算术运算符
| 运算符 | 名称 | 示例 | 结果 |
|---|---|---|---|
+ |
加法 | 5 + 3 |
8 |
- |
减法 | 5 - 3 |
2 |
* |
乘法 | 5 * 3 |
15 |
/ |
除法 | 5 / 2 |
2(整数除法) |
% |
取余(模运算) | 5 % 2 |
1 |
3.2.2 加法运算符 +
csharp
// 数值加法
int a = 10 + 5; // 15
double b = 3.14 + 2.86; // 6.0
// 字符串拼接(当其中一个操作数是字符串时)
string name = "张" + "三"; // "张三"
string message = "年龄:" + 25; // "年龄:25"
// 注意:从左到右执行,类型决定行为
int result1 = 1 + 2 + "3"; // "33"(先1+2=3,再拼"3")
string result2 = "1" + 2 + 3; // "123"(字符串开头,全部变拼接)
int result3 = 1 + 2 + int.Parse("3"); // 6(全部数值计算)
3.2.3 减法运算符 -
csharp
int x = 20 - 5; // 15 double y = 10.5 - 3.2; // 7.3 // 负号用法 int negative = -10; // 负10 int positive = -(-10); // 10(负负得正)
3.2.4 乘法运算符 *
csharp
int area = 5 * 4; // 20 double product = 2.5 * 4; // 10.0 // 连续运算 int result = 2 * 3 * 4; // 24
3.2.5 除法运算符 /(重点!重点!重点!)
这是初学者最容易出错的地方!
csharp
// 整数除法:结果只保留整数部分(截断,不是四舍五入) int a = 10 / 3; // 结果:3(不是 3.333...) int b = 5 / 2; // 结果:2(不是 2.5) int c = 1 / 2; // 结果:0(不是 0.5) // 浮点数除法:得到小数结果 double d = 10.0 / 3; // 3.33333333333333 double e = 5.0 / 2; // 2.5 double f = 1.0 / 2; // 0.5 // 混合类型:只要有一个是浮点数,结果就是浮点数 double g = 10 / 3.0; // 3.333... double h = 10.0 / 3; // 3.333... double i = (double)10 / 3; // 3.333...(强制转换) // 特别注意 int total = 7; int count = 2; double average = total / count; // 结果:3.0(不是 3.5!) double correctAvg = (double)total / count; // 3.5 ✅
记忆口诀:
整数除整数,结果还是整数,小数部分直接扔。
3.2.6 取余运算符 %(模运算)
取余 = 除法后的余数
csharp
int result1 = 10 % 3; // 1(10 ÷ 3 = 3 余 1) int result2 = 15 % 4; // 3(15 ÷ 4 = 3 余 3) int result3 = 20 % 5; // 0(整除) int result4 = 7 % 10; // 7(7 ÷ 10 = 0 余 7) // 判断奇偶数 bool isEven = number % 2 == 0; // 偶数 bool isOdd = number % 2 == 1; // 奇数 // 判断能否整除 bool isDivisible = a % b == 0; // 获取数字的个位数 int num = 123; int lastDigit = num % 10; // 3 // 获取数字的十位数 int tensDigit = (num / 10) % 10; // 2
3.2.7 自增自减运算符 ++ --
自增:变量加1;自减:变量减1
csharp
int count = 5; // 后置自增:先使用变量的值,再自增 int a = count++; // a = 5, count = 6 // 前置自增:先自增,再使用 int b = ++count; // count 现在是 7,然后 b = 7 // 同理,自减 int x = 10; int y = x--; // y = 10, x = 9 int z = --x; // x 变成 8,z = 8
前置 vs 后置对比表:
| 代码 | 等效步骤 | 结果 |
|---|---|---|
int b = ++a; |
a = a + 1; b = a; |
a 和 b 都自增后的值 |
int b = a++; |
b = a; a = a + 1; |
b 是旧值,a 是新值 |
实际应用场景:
csharp
// 循环计数器(最常见,第四章详细讲)
for (int i = 0; i < 10; i++) // 后置自增
{
// 循环体
}
// 独立使用时,前后置没有区别
int counter = 0;
counter++; // 推荐写法
++counter; // 效果一样
建议:独立使用时尽量用
counter++,简洁明了。
3.3 赋值运算符
3.3.1 简单赋值 =
把右边的值赋给左边的变量
csharp
int x = 5; // 把 5 赋给 x string name = "张三"; // 链式赋值(从右向左执行) int a, b, c; a = b = c = 10; // 相当于 c=10; b=c; a=b;
3.3.2 复合赋值运算符
对变量自身进行运算的简写
| 运算符 | 全写 | 示例 | 效果 |
|---|---|---|---|
+= |
a = a + b |
a += 5 |
a = a + 5 |
-= |
a = a - b |
a -= 3 |
a = a - 3 |
*= |
a = a * b |
a *= 2 |
a = a * 2 |
/= |
a = a / b |
a /= 4 |
a = a / 4 |
%= |
a = a % b |
a %= 3 |
a = a % 3 |
csharp
int score = 100; score += 10; // score = 110 score -= 20; // score = 90 score *= 2; // score = 180 score /= 3; // score = 60 score %= 7; // score = 4(60 % 7 = 4) // 字符串也有 += string message = "Hello"; message += " World"; // "Hello World"
3.4 比较运算符(关系运算符)
比较两个值,返回 bool 类型(true 或 false)
| 运算符 | 名称 | 示例 | 结果 |
|---|---|---|---|
== |
等于 | 5 == 5 |
true |
!= |
不等于 | 5 != 3 |
true |
> |
大于 | 5 > 3 |
true |
< |
小于 | 5 < 3 |
false |
>= |
大于等于 | 5 >= 5 |
true |
<= |
小于等于 | 5 <= 3 |
false |
csharp
int age = 18; bool isAdult = age >= 18; // true bool isTeenager = age > 12 && age < 20; // true bool isEqual = age == 18; // true bool isNotEqual = age != 18; // false // 注意:== 和 = 的区别 if (age = 18) // ❌ 编译错误!= 是赋值,== 才是比较 if (age == 18) // ✅ 正确 // 比较浮点数时注意精度问题 double x = 0.1 + 0.2; double y = 0.3; bool equal = x == y; // false!(因为 0.1+0.2 不等于 0.3 精确值) bool nearlyEqual = Math.Abs(x - y) < 0.000001; // true ✅
3.5 逻辑运算符
处理布尔值之间的逻辑关系
| 运算符 | 名称 | 示例 | 结果 |
|---|---|---|---|
&& |
逻辑与(AND) | true && true |
true |
|| |
逻辑或(OR) | true || false |
true |
! |
逻辑非(NOT) | !true |
false |
3.5.1 逻辑与 &&
所有条件都为 true,结果才为 true
csharp
bool hasID = true; bool hasTicket = true; bool canEnter = hasID && hasTicket; // true // 真值表 true && true = true true && false = false false && true = false false && false = false // 实际应用:判断某数是否在范围内 int score = 85; bool isBGrade = score >= 80 && score < 90; // true
3.5.2 逻辑或 ||
只要有一个条件为 true,结果就为 true
csharp
bool isWeekend = true; bool isHoliday = false; bool canSleepIn = isWeekend || isHoliday; // true // 真值表 true || true = true true || false = true false || true = true false || false = false // 实际应用 bool isVowel = c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
3.5.3 逻辑非 !
取反
csharp
bool isRaining = true; bool isGoodWeather = !isRaining; // false bool isLoggedIn = false; bool needLogin = !isLoggedIn; // true
3.5.4 短路求值(重要!)
&& 和 || 会"偷懒":如果能提前确定结果,后面的表达式不会执行
csharp
// && 短路:第一个是 false,后面的就不看了
int a = 10;
bool result = (a > 20) && (++a > 5); // (false) && (anything) = false
Console.WriteLine(a); // 还是 10,++a 没有执行!
// || 短路:第一个是 true,后面的就不看了
int b = 10;
bool result2 = (b < 20) || (++b > 5); // (true) || (anything) = true
Console.WriteLine(b); // 还是 10,++b 没有执行!
// 如果没有短路,可能会出问题
string name = null;
// if (name.Length > 0 && name != null) // ❌ 会报错!先判断 Length 会空引用
if (name != null && name.Length > 0) // ✅ 先判断 null,安全
{
Console.WriteLine("有名字");
}
3.5.5 逻辑运算符优先级
text
! (最高) && || (最低)
csharp
// 示例 bool result = true || false && false; // 相当于 true || (false && false) // = true || false // = true // 使用括号明确优先级 bool result2 = (true || false) && false; // false
3.6 运算符优先级
当表达式中有多个运算符时,优先级决定了谁先计算
完整优先级表(从高到低)
| 优先级 | 运算符 | 说明 |
|---|---|---|
| 1 | () |
括号(最高优先级) |
| 2 | ++ --(前置) + -(正负) ! ~ |
一元运算符 |
| 3 | * / % |
乘除取余 |
| 4 | + - |
加减 |
| 5 | << >> |
移位 |
| 6 | < > <= >= |
比较 |
| 7 | == != |
等于/不等于 |
| 8 | && |
逻辑与 |
| 9 | || |
逻辑或 |
| 10 | = += -= ... |
赋值(最低) |
优先级示例
csharp
// 数学规则 int result = 5 + 3 * 2; // 11(先乘后加) // 用括号改变优先级 int result2 = (5 + 3) * 2; // 16 // 混合运算 bool result3 = 5 + 3 > 2 * 3; // 步骤:5+3=8,2*3=6,8>6=true // 复杂示例 bool result4 = !true && false || 5 > 3; // 步骤1:!true = false // 步骤2:false && false = false // 步骤3:5>3 = true // 步骤4:false || true = true
黄金法则:不确定优先级就用括号
(),既清晰又安全。
3.7 其他常用运算符
3.7.1 条件运算符 ? :(三元运算符)
根据条件返回两个值之一
csharp
// 语法:条件 ? 为真时的值 : 为假时的值
int age = 18;
string status = age >= 18 ? "成年人" : "未成年人";
// 等效于 if-else(第四章讲)
string status2;
if (age >= 18)
{
status2 = "成年人";
}
else
{
status2 = "未成年人";
}
// 嵌套使用(不推荐过度嵌套)
int score = 85;
string grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "D";
3.7.2 空合并运算符 ??
如果左边为 null,返回右边;否则返回左边
csharp
string name = null; string displayName = name ?? "匿名用户"; // "匿名用户" string nickName = "小明"; string display = nickName ?? "匿名用户"; // "小明" // 等价写法 string result = (name != null) ? name : "匿名用户";
3.7.3 typeof 和 sizeof
csharp
// typeof:获取类型的 System.Type 对象 Type intType = typeof(int); Console.WriteLine(intType.Name); // "Int32" // sizeof:获取类型占用内存大小(字节) int byteSize = sizeof(int); // 4 int longSize = sizeof(long); // 8 int charSize = sizeof(char); // 2
3.7.4 is 运算符
检查对象是否是指定类型
csharp
object obj = "Hello"; bool isString = obj is string; // true bool isInt = obj is int; // false
3.8 类型转换与运算符(回顾与深入)
3.8.1 隐式转换在表达式中的发生
csharp
int a = 10; double b = 3.5; double c = a + b; // a 自动转为 double,结果是 double byte small = 100; int bigger = small + 1000; // small 自动转为 int
3.8.2 溢出检查运算符 checked / unchecked
csharp
// 默认情况下,整数溢出不会报错
int max = 2147483647;
int overflow = max + 1; // -2147483648(悄悄溢出)
// checked 检测溢出,会抛异常
checked
{
int willError = max + 1; // OverflowException
}
// unchecked 明确允许溢出(默认行为)
unchecked
{
int allowOverflow = max + 1; // -2147483648
}
3.9 综合示例
示例1:计算器(支持多种运算)
csharp
using System;
Console.WriteLine("=== 简单计算器 ===");
Console.Write("请输入第一个数字:");
double num1 = Convert.ToDouble(Console.ReadLine());
Console.Write("请输入运算符(+、-、*、/、%):");
string op = Console.ReadLine();
Console.Write("请输入第二个数字:");
double num2 = Convert.ToDouble(Console.ReadLine());
double result = 0;
bool isValid = true;
// 使用条件运算符
string opName = op == "+" ? "加法" :
op == "-" ? "减法" :
op == "*" ? "乘法" :
op == "/" ? "除法" :
op == "%" ? "取余" : "未知";
if (op == "+")
{
result = num1 + num2;
}
else if (op == "-")
{
result = num1 - num2;
}
else if (op == "*")
{
result = num1 * num2;
}
else if (op == "/")
{
if (num2 != 0)
{
result = num1 / num2;
}
else
{
Console.WriteLine("错误:除数不能为0!");
isValid = false;
}
}
else if (op == "%")
{
if (num2 != 0)
{
result = num1 % num2;
}
else
{
Console.WriteLine("错误:取余的除数不能为0!");
isValid = false;
}
}
else
{
Console.WriteLine("错误:不支持的运算符!");
isValid = false;
}
if (isValid)
{
string equation = $"{num1} {op} {num2} = {result}";
Console.WriteLine($"\n{opName}结果:{equation}");
}
示例2:判断闰年
csharp
using System;
Console.Write("请输入年份:");
int year = Convert.ToInt32(Console.ReadLine());
// 闰年规则:能被4整除但不能被100整除,或者能被400整除
bool isLeapYear = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
string result = isLeapYear ? "是闰年" : "不是闰年";
Console.WriteLine($"{year}年{result}");
// 附加信息
int days = isLeapYear ? 366 : 365;
Console.WriteLine($"{year}年共有{days}天");
示例3:数字特性检测
csharp
using System;
Console.Write("请输入一个整数:");
int num = Convert.ToInt32(Console.ReadLine());
bool isPositive = num > 0;
bool isNegative = num < 0;
bool isZero = num == 0;
bool isEven = num % 2 == 0;
bool isOdd = num % 2 != 0;
bool isDivisibleBy3 = num % 3 == 0;
bool isDivisibleBy5 = num % 5 == 0;
bool isDivisibleBy3And5 = isDivisibleBy3 && isDivisibleBy5;
Console.WriteLine($"\n数字 {num} 的特性:");
Console.WriteLine($"正数:{isPositive}");
Console.WriteLine($"负数:{isNegative}");
Console.WriteLine($"零:{isZero}");
Console.WriteLine($"偶数:{isEven}");
Console.WriteLine($"奇数:{isOdd}");
Console.WriteLine($"能被3整除:{isDivisibleBy3}");
Console.WriteLine($"能被5整除:{isDivisibleBy5}");
Console.WriteLine($"能被15整除:{isDivisibleBy3And5}");
3.10 常见错误与陷阱
错误1:= 和 == 混淆
csharp
if (x = 5) // ❌ 赋值表达式,结果是5,不是bool,编译错误 if (x == 5) // ✅ 正确
错误2:整数除法陷阱
csharp
double avg = sum / count; // 如果 sum 和 count 都是 int,结果错误 double avg = (double)sum / count; // ✅ 正确
错误3:浮点数比较
csharp
double x = 0.1 + 0.2; if (x == 0.3) // false! if (Math.Abs(x - 0.3) < 0.0000001) // ✅ 正确
错误4:除法除以零
csharp
int x = 10 / 0; // 抛出 DivideByZeroException double y = 10.0 / 0; // Infinity(不抛异常,但要注意)
错误5:短路求值误用
csharp
int i = 0;
if (i != 0 && 10 / i > 5) // 安全,因为 i != 0 是 false,后面不执行
{
// 不会进入
}
if (10 / i > 5 && i != 0) // ❌ 危险!先判断 10/0 直接崩
错误6:运算符优先级误解
csharp
bool result = a > b && c > d; // 实际上是 (a > b) && (c > d) bool result2 = a > b || c > d; // (a > b) || (c > d) ✅ 没问题 int x = 5 + 3 * 2; // 11,不是16 int y = (5 + 3) * 2; // 16
3.11 本章总结
核心知识导图
text
运算符 ├── 算术运算符:+ - * / % ++ -- ├── 赋值运算符:= += -= *= /= %= ├── 比较运算符:== != > < >= <= ├── 逻辑运算符:&& || ! └── 其他:? : ?? typeof sizeof is
优先级速记口诀
括号最优先,单目高于乘除,乘除高于加减,比较高于逻辑,赋值最后做。
类型转换要点
| 场景 | 方法 |
|---|---|
| 小转大(安全) | 隐式转换自动 |
| 大转小(可能丢数据) | 强制转换 (类型) |
| 字符串转数字 | Convert.ToInt32() 或 int.Parse() |
| 数字转字符串 | .ToString() 或 Convert.ToString() |
| 安全转换(不抛异常) | int.TryParse() |
3.12 练习题
基础题
-
计算下列表达式的值(写出计算步骤):
-
15 + 3 * 2 -
(15 + 3) * 2 -
20 / 4 * 2 -
20 / (4 * 2) -
17 % 5 -
7 + 3 > 5 && 2 * 3 == 6
-
-
写出程序的输出:
csharp
int a = 10;
int b = a++;
int c = ++a;
Console.WriteLine($"a={a}, b={b}, c={c}");
-
判断以下哪些变量名是合法的:
-
int 1stPlace; -
double my-score; -
bool _isValid; -
string class; -
int 中国;
-
应用题
-
编写程序,输入一个三位数,输出它的:
-
各位数字之和
-
是否是回文数(如 121、454)
-
提示:用
/和%获取各位数字
-
-
编写程序,输入两个整数和一个运算符(+、-、*、/),输出计算结果。注意判断除数为0的情况。
-
编写程序,判断一个数字:
-
是否是质数(简单的质数判断,用
%检查是否能被2到平方根之间的数整除) -
提示:质数是指大于1且只能被1和自身整除
-
挑战题
-
在不使用
Math.Pow的情况下,计算一个整数的三次方,并使用复合赋值运算符验证结果。 -
使用条件运算符
?:,实现一个简单的"成绩评级"程序:-
90分以上:A
-
80-89分:B
-
70-79分:C
-
60-69分:D
-
60分以下:F
-
-
模拟一个简单的"找零程序":
-
输入商品价格和付款金额
-
输出应找零金额
-
输出最少需要多少张纸币(100、50、20、10、5、1元)
-
更多推荐
所有评论(0)