Skip to Content
Week 01Day 4 - 运算符、字符串与控制台交互

Day 4 - 运算符、字符串与控制台交互

建议用时:180-210 分钟

你将学会什么

  • 表达式和运算符分别是什么
  • +-*/% 怎么计算
  • 整数除法为什么会丢掉小数部分
  • ===!=>>= 的区别
  • &&||! 怎么组合多个条件
  • 字符串怎么拼接、插值、裁剪、查找、替换
  • 控制台输入为什么要先清洗再转换
  • 如何写一个完整的“输入 -> 清洗 -> 转换 -> 计算 -> 输出”程序

本页只讲 C# 控制台基础,不讲任何界面框架。今天的重点是把“数据怎么处理”讲清楚。

本页固定顺序

  1. 先学第一部分:弄懂今天最小、最重要的知识,并运行短例子。
  2. 再学第二部分:把刚学的知识组合成一个完整例子。
  3. 然后做第三部分:自己跟着敲,再完成重复训练和每日小测。
  4. 最后做第四部分:先独立完成作业,再用完整答案检查。

从 Day 3 走到 Day 4

Day 3 学的是“程序根据条件决定走哪条路”,Day 4 学的是“条件里的数据到底怎么计算和整理”。

把两天连起来看:

Day 3:如果总价大于 100,就打折 Day 4:总价怎么计算,折扣怎么计算,结果怎么显示

你已经见过下面这些旧知识:

  • Console.ReadLine():读取用户输入。
  • if:根据真假决定执行哪一段。
  • return:输入不正确时提前结束。
  • TryParse:尝试把文本转成数字。

今天真正新增的重点只有四组:

  1. + - * / % 计算。
  2. 用比较和逻辑运算符得到 truefalse
  3. 用字符串插值和少量字符串方法整理文本。
  4. F2P0 控制输出格式。

第一次学习时,不要求记住所有字符串方法。先掌握 Trim()LengthToUpper()Contains(),其余方法知道“以后可以查”就够了。

今天的最低通过线

如果今天学完只能做到下面四件事,也算合格:

  • 能解释 10 / 3 为什么是 310 % 3 为什么是 1
  • 能分清 = 是赋值,== 是比较。
  • 能把 " keyboard " 整理成 "KEYBOARD"
  • 能算出 单价 * 数量,并用 F2 显示两位小数。

先达到最低通过线,再做折扣小票。不要一上来要求自己看懂整页。

第一部分:先学原理和最小知识

这一部分先解决“这是什么、为什么要这样写”。每看到一个短例子就亲手敲一遍并运行,不要先背完整程序。

今天先抓住什么

变量保存数据,运算符处理数据。程序真正有用的地方,往往就在“处理”这一步。

今天的主线是:

原始输入文本 -> Trim 清洗文本 -> TryParse 转成数字 -> 用运算符计算 -> 用条件判断保护边界 -> 格式化输出结果

名词先讲清楚

名词直接解释例子
表达式能算出结果的一段代码price * count
运算符执行计算、比较或逻辑判断的符号+==&&
操作数运算符两边参与运算的值pricecount
拼接把字符串连起来"Hello " + name
插值在字符串里放变量$"你好,{name}"
格式化控制输出显示格式{total:F2}
取余得到除法后的余数10 % 31
优先级决定哪个运算先算* 通常先于 +

表达式是什么

表达式就是能算出一个结果的代码。

decimal price = 20m; int count = 3; decimal total = price * count; bool expensive = total >= 50m; string line = $"总价: {total:F2}"; Console.WriteLine(total); Console.WriteLine(expensive); Console.WriteLine(line);

这里有三种表达式:

表达式结果类型结果
price * countdecimal60
total >= 50mbooltrue
$"总价: {total:F2}"string一段文本

算术运算符

运算符作用例子结果
+加法10 + 313
-减法10 - 37
*乘法10 * 330
/除法10 / 3整数除法结果是 3
%取余10 % 31

完整例子:

int a = 10; int b = 3; Console.WriteLine(a + b); Console.WriteLine(a - b); Console.WriteLine(a * b); Console.WriteLine(a / b); Console.WriteLine(a % b);

输出:

13 7 30 3 1

整数除法为什么是 3

10 / 3 如果两边都是 int,C# 会做整数除法,结果只保留整数部分。

int a = 10; int b = 3; Console.WriteLine(a / b); Console.WriteLine((decimal)a / b);

输出:

3 3.3333333333333333333333333333

如果需要小数结果,至少要把其中一个数变成 decimaldouble

取余 % 有什么用

取余常用来判断能不能整除、分页、奇偶数。

int number = 17; if (number % 2 == 0) { Console.WriteLine("偶数"); } else { Console.WriteLine("奇数"); }

17 % 2 等于 1,说明不能被 2 整除,所以是奇数。

运算优先级和括号

C# 会先算乘除,再算加减。

Console.WriteLine(2 + 3 * 4); Console.WriteLine((2 + 3) * 4);

输出:

14 20

不要依赖别人猜你的优先级。业务计算里,想强调先算哪一段,就加括号。

复合赋值和自增

下面这些写法经常在循环和累计里出现:

int count = 0; count = count + 1; count += 1; count++; Console.WriteLine(count);

输出:

3

三次都让 count 加了 1。count++ 是最短写法,常用于计数。

比较运算符

比较运算符的结果一定是 bool

int stock = 8; Console.WriteLine(stock == 0); Console.WriteLine(stock != 0); Console.WriteLine(stock < 10); Console.WriteLine(stock >= 10);

输出:

False True True False

注意:= 是赋值,== 是比较。

逻辑运算符

多个条件要组合时,用逻辑运算符。

decimal price = 80m; int count = 3; decimal discount = 0.9m; bool priceOk = price >= 0; bool countOk = count > 0; bool discountOk = discount > 0 && discount <= 1; Console.WriteLine(priceOk && countOk && discountOk);

输出:

True

&& 表示所有条件都成立,|| 表示至少一个条件成立,! 表示取反。

字符串拼接和插值

拼接写法:

string name = "Tom"; int age = 18; Console.WriteLine("姓名: " + name + ", 年龄: " + age);

插值写法:

string name = "Tom"; int age = 18; Console.WriteLine($"姓名: {name}, 年龄: {age}");

两段输出一样,但插值更容易读。后面优先使用字符串插值。

字符串常用操作

字符串方法很多,但第一遍只练前四个。后面的写法先当作查询表,不要求背诵。

需求写法作用
去掉前后空格text.Trim()清理输入
获取字符数量text.Length检查输入长度
统一成大写text.ToUpper()统一显示或比较
判断是否包含text.Contains("Key")搜索
判断开头text.StartsWith("P-")判断编号前缀
判断结尾text.EndsWith(".csv")判断文件类型
替换内容text.Replace(" ", "-")替换空格、符号
转小写text.ToLower()搜索时统一比较
string text = " Keyboard "; string clean = text.Trim(); Console.WriteLine(clean); Console.WriteLine(clean.Length); Console.WriteLine(clean.Contains("Key")); Console.WriteLine(clean.StartsWith("Key")); Console.WriteLine(clean.ToUpper()); Console.WriteLine(clean.Replace("Key", "Board"));

输出:

Keyboard 8 True True KEYBOARD Boardboard

这些方法不会把原来的 text 直接改掉,它们会返回一个新的结果。要继续使用整理后的值,就用新变量接住。

再看一个“检查商品编号”的例子:

string rawCode = " P-2026-0001 "; string code = rawCode.Trim().ToUpper(); if (!code.StartsWith("P-")) { Console.WriteLine("商品编号必须以 P- 开头"); return; } if (code.Length < 5) { Console.WriteLine("商品编号太短"); return; } Console.WriteLine($"整理后的编号: {code}"); Console.WriteLine($"编号长度: {code.Length}");

输出:

整理后的编号: P-2026-0001 编号长度: 11

这里的重点是:

  • Trim() 先清理前后空格。
  • ToUpper() 统一大小写。
  • StartsWith("P-") 判断编号前缀。
  • Length 检查编号是不是明显太短。

把文本按横线拆成多段需要数组知识,安排在 Day 6 学完以后再练。今天不要提前背 Split 和下标。

格式化输出

金额常用两位小数:

decimal total = 59.7m; Console.WriteLine($"{total:F2}");

输出:

59.70

百分比常用 P0

decimal discount = 0.8m; Console.WriteLine($"{discount:P0}");

输出:

80%

今天写代码时按这个顺序

  1. 原始输入变量用 xxxText,例如 priceText
  2. 文本先判断空值或格式。
  3. 需要计算时,用 TryParse 转成数字。
  4. 金额用 decimal,数量用 int
  5. 用括号明确复杂计算顺序。
  6. F2 输出金额,用 P0 输出百分比。
  7. 输出前把字符串 Trim()

第二部分:把知识组合成完整例子

前面已经学过最小知识。现在把它们组合起来,先读懂执行顺序,再完整敲一遍。今天最终要写一个更完整的小票程序:输入商品、单价、数量、折扣,再输出计算结果。

第一次看这段程序时,只做两件事:

  1. 看它向用户读取了哪四项数据。
  2. 看最后输出了哪三个计算结果。

中间暂时看不懂的判断可以先跳过。第三部分会从短代码开始,一段一段把它拼出来。

代码部分属于哪天第一次是否必须看懂
Console.ReadLine()Day 2 旧知识
ifreturnDay 3 旧知识
TryParse(..., out ...)Day 2 旧知识知道它在转换即可
price * countDay 4 新知识
originalTotal * discountDay 4 新知识
{value:F2}{value:P0}Day 4 新知识

最终你要写出这个程序

Console.Write("商品名称: "); string? nameText = Console.ReadLine(); Console.Write("单价: "); string? priceText = Console.ReadLine(); Console.Write("数量: "); string? countText = Console.ReadLine(); Console.Write("折扣,例如 0.9 表示九折: "); string? discountText = Console.ReadLine(); if (string.IsNullOrWhiteSpace(nameText)) { Console.WriteLine("商品名称不能为空"); return; } if (!decimal.TryParse(priceText, out decimal price)) { Console.WriteLine("单价必须是数字"); return; } if (!int.TryParse(countText, out int count)) { Console.WriteLine("数量必须是整数"); return; } if (!decimal.TryParse(discountText, out decimal discount)) { Console.WriteLine("折扣必须是数字"); return; } if (price < 0 || count <= 0 || discount <= 0 || discount > 1) { Console.WriteLine("单价、数量或折扣范围不正确"); return; } string name = nameText.Trim(); decimal originalTotal = price * count; decimal finalTotal = originalTotal * discount; decimal saved = originalTotal - finalTotal; Console.WriteLine("----- 小票 -----"); Console.WriteLine($"商品: {name}"); Console.WriteLine($"单价: {price:F2}"); Console.WriteLine($"数量: {count}"); Console.WriteLine($"折扣: {discount:P0}"); Console.WriteLine($"原价合计: {originalTotal:F2}"); Console.WriteLine($"优惠金额: {saved:F2}"); Console.WriteLine($"应付金额: {finalTotal:F2}");

正常输入:

商品名称: Keyboard 单价: 100 数量: 3 折扣,例如 0.9 表示九折: 0.8 ----- 小票 ----- 商品: Keyboard 单价: 100.00 数量: 3 折扣: 80% 原价合计: 300.00 优惠金额: 60.00 应付金额: 240.00

今天要理解的是:这些计算和判断不是凭感觉写的,每个符号都有明确含义。

第三部分:跟着敲代码

从这里开始动手。每个例子都可以直接放进 Program.cs 运行。

每个例子按三遍练:第一遍照着敲并运行;第二遍只看标题重新写;第三遍改一个数字、条件或输入,再预测结果。不要复制粘贴。

动手前先做这 3 件事

  1. 打开控制台项目,确认 dotnet run 能运行。
  2. 每做一个例子,就把 Program.cs 旧内容替换掉。
  3. 每次只改一个数字或一行输入,看结果怎么变。

例子 1:数字运算和取余

int total = 23; int pageSize = 5; int fullPages = total / pageSize; int remaining = total % pageSize; Console.WriteLine($"完整页数: {fullPages}"); Console.WriteLine($"剩余数量: {remaining}");

预期输出:

完整页数: 4 剩余数量: 3

例子 2:整数除法和小数除法

int a = 10; int b = 3; Console.WriteLine(a / b); Console.WriteLine((decimal)a / b);

预期输出:

3 3.3333333333333333333333333333

例子 3:字符串整理

Console.Write("请输入商品名称: "); string? input = Console.ReadLine(); if (string.IsNullOrWhiteSpace(input)) { Console.WriteLine("商品名称不能为空"); return; } string name = input.Trim(); Console.WriteLine($"整理后的名称: {name}"); Console.WriteLine($"字符数量: {name.Length}"); Console.WriteLine($"大写名称: {name.ToUpper()}");

输入 keyboard 时,会输出整理后的名称和长度。

例子 4:比较库存状态

Console.Write("请输入库存数量: "); string? input = Console.ReadLine(); if (!int.TryParse(input, out int stock)) { Console.WriteLine("库存必须是整数"); return; } if (stock == 0) { Console.WriteLine("缺货"); } else if (stock < 10) { Console.WriteLine("库存偏低"); } else { Console.WriteLine("库存充足"); }

分别输入 0520,观察三个分支。

例子 5:金额和折扣计算

decimal price = 100m; int count = 3; decimal discount = 0.8m; decimal originalTotal = price * count; decimal finalTotal = originalTotal * discount; decimal saved = originalTotal - finalTotal; Console.WriteLine($"原价合计: {originalTotal:F2}"); Console.WriteLine($"折扣: {discount:P0}"); Console.WriteLine($"优惠金额: {saved:F2}"); Console.WriteLine($"应付金额: {finalTotal:F2}");

预期输出:

原价合计: 300.00 折扣: 80% 优惠金额: 60.00 应付金额: 240.00

例子 6:完整输入、清洗、转换、计算

Console.Write("商品名称: "); string? nameText = Console.ReadLine(); Console.Write("单价: "); string? priceText = Console.ReadLine(); Console.Write("数量: "); string? countText = Console.ReadLine(); if (string.IsNullOrWhiteSpace(nameText)) { Console.WriteLine("商品名称不能为空"); return; } if (!decimal.TryParse(priceText, out decimal price)) { Console.WriteLine("单价必须是数字"); return; } if (!int.TryParse(countText, out int count)) { Console.WriteLine("数量必须是整数"); return; } string name = nameText.Trim(); decimal total = price * count; Console.WriteLine($"{name} x {count} = {total:F2}");

输入 Keyboard19.93,输出:

Keyboard x 3 = 59.70

例子 7:整理并检查商品编号

Console.Write("商品编号,例如 P-2026-0001: "); string? codeText = Console.ReadLine(); if (string.IsNullOrWhiteSpace(codeText)) { Console.WriteLine("商品编号不能为空"); return; } string code = codeText.Trim().ToUpper(); if (!code.StartsWith("P-")) { Console.WriteLine("商品编号必须以 P- 开头"); return; } if (code.Length < 5) { Console.WriteLine("商品编号太短"); return; } Console.WriteLine($"整理后的编号: {code}"); Console.WriteLine($"编号长度: {code.Length}");

输入:

p-2026-0001

输出:

整理后的编号: P-2026-0001 编号长度: 11

常见错误和修法

错误为什么错修法
字符串拼接时漏空格输出结果不易读用插值字符串 $"名称: {name}"
调用 Trim() 后仍输出旧变量字符串方法返回新字符串用变量接住 Trim() 的结果
忘记区分 ===一个是赋值,一个是比较读成“放进去”和“是不是”
搜索时大小写不一致同一文本可能匹配失败比较前统一 ToLower()
没有处理 ReadLine() 的空值后续调用方法可能出错先用空合并或空白判断

每日小测

先把答案写在纸上或注释里,再看下面的参考答案。

1. 预测输出

下面两行分别输出什么?

Console.WriteLine(17 / 5); Console.WriteLine(17 % 5);

2. 分清赋值和比较

下面哪一行是“把 10 放进 stock”,哪一行是“判断 stock 是否等于 10”?

stock = 10; stock == 10;

3. 用人话读条件

请用中文读出这个条件:

price >= 0 && count > 0

4. 找出字符串问题

下面代码为什么仍然输出前后带空格的原文本?

string text = " mouse "; text.Trim(); Console.WriteLine(text);

5. 排处理顺序

把下面五步按正确顺序排列:

计算总价 读取文本 输出结果 TryParse 转换 检查数据范围

参考答案

  1. 输出 32。整数除法保留整数部分,取余得到余数。
  2. stock = 10 是赋值;stock == 10 是比较,比较结果是 bool
  3. 单价大于等于 0,并且数量大于 0。
  4. 字符串不会被 Trim() 原地修改。应该写 string clean = text.Trim();,再输出 clean
  5. 读取文本 -> TryParse 转换 -> 检查数据范围 -> 计算总价 -> 输出结果。

如果第 1、2、5 题答错,先不要做作业,回看“算术运算符”“比较运算符”和“今天写代码时按这个顺序”。

上位机专项练习

设备原始值经常需要换算、比较、格式化和拼接成界面文字。运算符和字符串就是最基础的数据处理工具。

下面 3 个例子都要亲手敲。先运行原代码,再完成每个例子后面的改动任务。

专项例子 1:把原始值换算成工程值

int rawValue = 2048; double engineeringValue = rawValue / 4095.0 * 100.0; Console.WriteLine($"工程值: {engineeringValue:F2}%");

运行结果或界面效果:

工程值: 50.01%

改动任务: 把 rawValue 改成 4095,结果应该接近 100%。

专项例子 2:组合报警条件

double pressure = 1.8; bool isOnline = true; bool hasAlarm = isOnline && pressure > 1.5; Console.WriteLine($"是否报警: {hasAlarm}");

运行结果或界面效果:

是否报警: True

改动任务: 把 isOnline 改成 false,理解 && 的作用。

专项例子 3:整理设备标签

string area = "A区"; int deviceNumber = 7; string tag = $"{area}-TEMP-{deviceNumber:D3}"; Console.WriteLine(tag);

运行结果或界面效果:

A区-TEMP-007

改动任务: 把编号改成 25,确认仍然显示三位。

第四部分:作业完整答案

这一部分给出当天作业的完整答案。先按第三部分做一遍,再用这里检查。

作业要求

写一个带折扣的小票程序,要求:

  1. 输入商品名称、单价、数量、折扣。
  2. 商品名称不能为空。
  3. 单价必须是数字,且不能小于 0。
  4. 数量必须是整数,且必须大于 0。
  5. 折扣必须是数字,范围是 0 < 折扣 <= 1
  6. 输出原价合计、优惠金额、应付金额。
  7. 金额保留两位小数,折扣显示为百分比。

作业拆解

按这个顺序写:

  1. ReadLine 读取四个原始文本。
  2. IsNullOrWhiteSpace 判断名称。
  3. decimal.TryParse 转换单价和折扣。
  4. int.TryParse 转换数量。
  5. || 判断错误范围。
  6. price * count 算原价合计。
  7. originalTotal * discount 算折后金额。
  8. originalTotal - finalTotal 算优惠金额。

完整代码

Console.Write("商品名称: "); string? nameText = Console.ReadLine(); Console.Write("单价: "); string? priceText = Console.ReadLine(); Console.Write("数量: "); string? countText = Console.ReadLine(); Console.Write("折扣,例如 0.9 表示九折: "); string? discountText = Console.ReadLine(); if (string.IsNullOrWhiteSpace(nameText)) { Console.WriteLine("商品名称不能为空"); return; } if (!decimal.TryParse(priceText, out decimal price)) { Console.WriteLine("单价必须是数字"); return; } if (!int.TryParse(countText, out int count)) { Console.WriteLine("数量必须是整数"); return; } if (!decimal.TryParse(discountText, out decimal discount)) { Console.WriteLine("折扣必须是数字"); return; } if (price < 0) { Console.WriteLine("单价不能小于 0"); return; } if (count <= 0) { Console.WriteLine("数量必须大于 0"); return; } if (discount <= 0 || discount > 1) { Console.WriteLine("折扣必须大于 0 且小于等于 1"); return; } string name = nameText.Trim(); decimal originalTotal = price * count; decimal finalTotal = originalTotal * discount; decimal saved = originalTotal - finalTotal; Console.WriteLine("----- 小票 -----"); Console.WriteLine($"商品: {name}"); Console.WriteLine($"单价: {price:F2}"); Console.WriteLine($"数量: {count}"); Console.WriteLine($"折扣: {discount:P0}"); Console.WriteLine($"原价合计: {originalTotal:F2}"); Console.WriteLine($"优惠金额: {saved:F2}"); Console.WriteLine($"应付金额: {finalTotal:F2}");

正确运行结果

正常输入:

商品名称: Keyboard 单价: 100 数量: 3 折扣,例如 0.9 表示九折: 0.8 ----- 小票 ----- 商品: Keyboard 单价: 100.00 数量: 3 折扣: 80% 原价合计: 300.00 优惠金额: 60.00 应付金额: 240.00

错误输入要分别测试:

商品名称为空:提示 商品名称不能为空 单价输入 abc:提示 单价必须是数字 数量输入 2.5:提示 数量必须是整数 折扣输入 2:提示 折扣必须大于 0 且小于等于 1

你要能说清楚这 7 件事

  • + 在数字上是加法,在字符串上是拼接。
  • / 用在两个整数上时是整数除法。
  • % 可以用来判断余数、分页和奇偶数。
  • = 是赋值,== 是比较。
  • && 是并且,|| 是或者,! 是取反。
  • Trim() 返回整理后的新字符串。
  • {value:F2} 输出两位小数,{value:P0} 输出百分比。