单元1 · Ruby 环境与基础语法
Ruby 安装、puts/print、变量、字符串插值
- 输出:puts 换行、print 不换行;脚本无需入口函数。
- 变量:动态类型;#{} 字符串插值。
- 常量:大写开头;Symbol 不可变唯一。
实训1.1 Hello World 与输出
编写第一个 Ruby 程序,用 puts 输出问候语。
Ruby 脚本无需入口函数;puts 输出并换行、print 不换行。
puts "Hello, Ruby!"
puts "Ruby 是优雅的动态语言"
print "这是 print 输出,不换行"
puts " 接着输出"
实训1.2 变量与字符串插值
声明字符串、整数、浮点、布尔变量,用 #{} 插值输出。
Ruby 动态类型;#{} 字符串插值;变量无需类型声明。
name = "Ruby"
version = 3.2
is_dynamic = true
puts "语言:#{name}"
puts "版本:#{version}"
puts "是否动态类型:#{is_dynamic}"
greeting = "你好"
puts "#{greeting},#{name} 开发者!"
实训1.3 常量与符号
定义常量与 Symbol(符号),输出并说明区别。
常量以大写字母开头;Symbol 以冒号开头,不可变且唯一。
MAX_USERS = 100_000
LANGUAGE = :ruby
puts "最大用户数:#{MAX_USERS}"
puts "语言符号:#{LANGUAGE}"
puts "符号相等:#{:ruby == LANGUAGE}"
puts "字符串:#{LANGUAGE.to_s}"
实训1.4 输入与类型转换
用 gets 读取用户输入并转换为整数,输出计算结果。
gets 读取含换行符的字符串;chomp 去掉换行;to_i 转整数。
print "请输入一个整数:"
input = gets.chomp
n = input.to_i
puts "#{n} 的平方是 #{n * n}"
puts "输入的类型:#{input.class}"
puts "转换后类型:#{n.class}"
单元2 · 数据类型与运算符
数值、字符串、数组基础、算术/比较/逻辑运算符
- 运算:整数相除截断;** 幂;% 取余。
- 转换:to_i/to_f/to_s;Float() 转换。
- 逻辑:== != && || !;even? 谓词方法。
实训2.1 基础运算
给定整数 17 和 5,输出和、差、积、商、余数、幂。
Ruby 整数相除得整数;** 幂运算。
a = 17
b = 5
puts "和:#{a + b}"
puts "差:#{a - b}"
puts "积:#{a * b}"
puts "商:#{a / b}"
puts "余数:#{a % b}"
puts "幂:#{2 ** 10}"
实训2.2 浮点运算
计算半径为 7.5 的圆的周长与面积,π 取 Math::PI。
Math::PI 圆周率常量;format 或 sprintf 控制精度。
r = 7.5
circumference = 2 * Math::PI * r
area = Math::PI * r * r
puts "周长:#{format('%.4f', circumference)}"
puts "面积:#{format('%.4f', area)}"
实训2.3 比较与逻辑运算
a=8、b=12,输出 a>b、a!=b、a<10 && b>10、!(a==8)。
== 相等、!= 不等;&& 与、|| 或、! 非。
a = 8
b = 12
puts "a > b:#{a > b}"
puts "a != b:#{a != b}"
puts "a<10 && b>10:#{a < 10 && b > 10}"
puts "!(a == 8):#{!(a == 8)}"
实训2.4 运算符与类型转换
演示整数除法与浮点除法差异,以及 to_f/to_i 转换。
整数相除截断;除数转浮点得到浮点结果。
puts "7 / 2 = #{7 / 2}"
puts "7.0 / 2 = #{7.0 / 2}"
puts "7 / 2.0 = #{7 / 2.0}"
s = "42.5"
f = s.to_f
puts "字符串转浮点:#{f}"
puts "浮点转整数:#{f.to_i}"
puts "整数转字符串:#{42.to_s}"
单元3 · 流程控制:分支结构
if/elsif/else、unless、case/when
- if:elsif 分支;end 结束。
- unless:if 的反面;行尾修饰符。
- case:when 分支;支持范围匹配。
实训3.1 if 判断成绩等级
成绩 score=85,输出等级:>=90 优秀、>=80 良好、>=60 及格、否则不及格。
Ruby 用 elsif 而非 else if;end 结束块。
score = 85
if score >= 90
puts "优秀"
elsif score >= 80
puts "良好"
elsif score >= 60
puts "及格"
else
puts "不及格"
end
实训3.2 unless 与修饰符
用 unless 表示除非,演示单行 if/unless 修饰符。
unless 是 if 的反面;if/unless 可作为行尾修饰符。
age = 17
unless age >= 18
puts "未成年"
end
puts "成年" if age >= 18
puts "需要家长陪同" unless age >= 18
n = 42
puts "n 是偶数" if n.even?
实训3.3 case/when 判断星期
用 case/when 把数字 1-7 映射为星期。
case/when 类似 switch;支持 when 后多个值。
day = 4
case day
when 1 then puts "星期一"
when 2 then puts "星期二"
when 3 then puts "星期三"
when 4 then puts "星期四"
when 5 then puts "星期五"
when 6 then puts "星期六"
when 7 then puts "星期日"
else
puts "无效输入"
end
实训3.4 三元与 case 范围
用三元判断奇偶,用 case 区间匹配成绩等级。
三元 ?: 简洁;when 支持范围匹配 (90..100)。
n = 15
puts n.even? ? "偶数" : "奇数"
score = 85
grade = case score
when 90..100 then "优秀"
when 80..89 then "良好"
when 60..79 then "及格"
when 0..59 then "不及格"
else "非法分数"
end
puts "#{score} 分:#{grade}"
单元4 · 循环结构
times、each、while、until、break/next
- each:遍历最常用;块参数。
- times:固定次数循环。
- 控制:break/next;while/until。
实训4.1 each 求和 1 到 100
用 each 遍历 1..100 求和并输出。
(1..100).each 遍历范围;块参数 i 接收元素。
sum = 0
(1..100).each do |i|
sum += i
end
puts "1 到 100 的和:#{sum}"
实训4.2 times 与 while
用 times 输出 5 次问候,用 while 求 1 到 10 之和。
N.times 固定次数;while 条件循环。
5.times do |i|
puts "第 #{i + 1} 次问候"
end
sum = 0
i = 1
while i <= 10
sum += i
i += 1
end
puts "1 到 10 的和:#{sum}"
实训4.3 打印乘法表
输出 9x9 乘法表,每行一个乘数。
嵌套 each;print 不换行;printf 对齐。
(1..9).each do |i|
(1..i).each do |j|
printf "%dx%d=%-2d ", j, i, i * j
end
puts
end
实训4.4 break 与 next
输出 1 到 20 中能被 3 整除的数,遇到 15 用 break 结束。
break 终止循环;next 跳过当前迭代。
(1..20).each do |i|
break if i == 15
next if i % 3 != 0
puts i
end
sum = 0
(1..10).each do |i|
next if i.even?
sum += i
end
puts "1..10 奇数之和:#{sum}"
单元5 · 数组与哈希
数组方法、哈希、each 遍历、排序
- 数组:push/<< 添加;max/sort。
- 方法:map/select/reduce/uniq/flatten。
- 哈希:符号键;each 遍历键值。
实训5.1 数组基础操作
创建数组,添加元素、遍历、求最大值、排序。
数组字面量 [];push/<< 添加;max/sort 方法。
nums = [12, 45, 7, 89, 33]
nums << 60
nums.push(25)
puts "大小:#{nums.size}"
puts "最大值:#{nums.max}"
puts "最小值:#{nums.min}"
puts "排序:#{nums.sort.join(', ')}"
nums.each_with_index do |v, i|
puts "[#{i}] = #{v}"
end
实训5.2 数组常用方法
演示 map、select、reduce、flatten、uniq 等数组方法。
map 映射、select 筛选、reduce 归约、uniq 去重。
nums = [3, 1, 4, 1, 5, 9, 2, 6]
puts "去重:#{nums.uniq.join(', ')}"
puts "翻倍:#{nums.map { |n| n * 2 }.join(', ')}"
puts "偶数:#{nums.select(&:even?).join(', ')}"
puts "总和:#{nums.reduce(0) { |sum, n| sum + n }}"
matrix = [[1, 2], [3, 4]]
puts "展平:#{matrix.flatten.join(', ')}"
实训5.3 哈希 Hash
创建 Hash 存年龄,增删改查并遍历。
哈希字面量 {};symbol 键 ages[:zhang];delete 删除。
ages = { zhang: 20, li: 22 }
ages[:wang] = 24
ages[:li] = 23
ages.delete(:wang)
ages.each do |name, age|
puts "#{name}:#{age} 岁"
end
puts "张三年龄:#{ages[:zhang]}"
puts "键列表:#{ages.keys.join(', ')}"
实训5.4 哈希与数组综合
统计单词频次,输出出现最多的单词。
split 拆词 + Hash 默认值 0 + max_by 找最大值。
text = "ruby is elegant ruby is powerful ruby is fun"
words = text.split
freq = Hash.new(0)
words.each { |w| freq[w] += 1 }
freq.each { |word, count| puts "#{word}:#{count}" }
top = freq.max_by { |_, count| count }
puts "出现最多:#{top[0]},#{top[1]} 次"
单元6 · 方法与块
方法定义、默认参数、块 yield、Lambda/Proc
- 方法:def/end;最后表达式为返回值。
- 参数:默认参数;*args 可变参数。
- 块:yield 调用;Proc/Lambda。
实训6.1 定义方法
定义 add 方法返回两数之和并调用输出。
def/end 定义方法;最后一个表达式为返回值;可省略 return。
def add(a, b)
a + b
end
def greet(name)
"你好,#{name}!"
end
puts "add(10, 20) = #{add(10, 20)}"
puts "add(3, 7) = #{add(3, 7)}"
puts greet("小明")
实训6.2 默认参数与可变参数
定义带默认参数与 *args 可变参数的方法。
默认参数在未传时生效;*args 收集多余参数为数组。
def greet(name, greeting = "你好")
"#{greeting},#{name}!"
end
def sum_all(*numbers)
numbers.reduce(0) { |sum, n| sum + n }
end
puts greet("小明")
puts greet("小红", "早上好")
puts "sum_all(1,2,3,4) = #{sum_all(1, 2, 3, 4)}"
实训6.3 块与 yield
用 yield 调用块,演示块参数的传递。
方法内 yield 调用块;块参数 |x| 接收值。
def repeat(n)
n.times { |i| yield i }
end
def with_prefix(prefix)
yield prefix if block_given?
end
repeat(3) { |i| puts "第 #{i + 1} 次" }
with_prefix("DEBUG") { |p| puts "[#{p}] 日志信息" }
实训6.4 Proc 与 Lambda
对比 Proc 与 Lambda 的差异,用 &block 接收块。
Proc/Lambda 封装代码块;&block 参数捕获块;lambda 参数检查严格。
double = Proc.new { |x| x * 2 }
triple = lambda { |x| x * 3 }
puts "Proc 调用:#{double.call(5)}"
puts "Lambda 调用:#{triple.call(5)}"
def execute(&block)
result = block.call(10)
"执行结果:#{result}"
end
puts execute { |x| x + 100 }
单元7 · 字符串与符号
字符串方法、gsub、正则、Symbol
- 字符串:upcase/gsub/split/size 常用。
- 插值:#{} 任意表达式;重复 *。
- 正则:/pattern/ 字面量;=~ 匹配。
实训7.1 字符串常用方法
对字符串做大小写、替换、拆分、拼接、长度统计。
upcase/downcase/gsub/split/join/size 常用。
s = " Hello, Ruby "
puts "去掉空格:|#{s.strip}|"
puts "大写:#{s.strip.upcase}"
puts "小写:#{s.strip.downcase}"
puts "替换:#{s.strip.gsub('Ruby', 'Rails')}"
puts "拆分:#{s.strip.split(',').join(' | ')}"
puts "长度:#{s.strip.size}"
实训7.2 字符串插值与重复
用 #{} 插值表达式,演示重复与格式化。
#{} 任意表达式;* 重复字符串;format 格式化。
name = "Ruby"
puts "长度:#{name.length}"
puts "大写:#{name.upcase}"
puts "重复:#{'ab' * 3}"
total = 42
percent = 85.5
puts "总计:#{total},完成度:#{format('%.1f%%', percent)}"
实训7.3 正则表达式
用 =~ 匹配邮箱,用 scan 提取数字,用 gsub 替换。
正则字面量 /pattern/;=~ 匹配返回位置;scan 提取。
email = "user@example.com"
if email =~ /^[\w.-]+@[\w.-]+\.\w+$/
puts "邮箱格式正确"
else
puts "邮箱格式错误"
end
text = "订单号 123,金额 45.6 元"
numbers = text.scan(/\d+/)
puts "提取数字:#{numbers.join(', ')}"
puts "替换数字:#{text.gsub(/\d+/, '#')}"
实训7.4 字符串编码与转换
演示字符编码处理、字符串与符号互转、格式化。
to_sym/to_s 互转;length 字符数;bytesize 字节数。
s = "Hello"
puts "符号化:#{s.to_sym}"
sym = :world
puts "字符串化:#{sym.to_s}"
puts "反转:#{s.reverse}"
text = "中文Ruby"
puts "字符数:#{text.length}"
puts "字节数(UTF-8):#{text.bytesize}"
puts format("整数:%d,浮点:%.2f,字符串:%s", 42, 3.14159, "ok")
单元8 · 类与对象
类定义、实例变量、attr_accessor、继承、模块
- 类:initialize 构造;@ 实例变量。
- 属性:attr_accessor 生成读写方法。
- 继承:< 继承;super 调用父类;模块混入。
实训8.1 定义类与实例变量
定义 Student 类,包含实例变量与方法,实例化调用。
class 定义类;@name 实例变量;initialize 构造方法;new 实例化。
class Student
def initialize(name, score)
@name = name
@score = score
end
def info
"#{@name},成绩 #{@score} 分"
end
end
stu = Student.new("小明", 92.5)
puts stu.info
实训8.2 attr_accessor 与属性
用 attr_accessor 自动生成读写方法,演示存款取款。
attr_accessor 同时生成读与写方法;attr_reader 只读。
class BankAccount
attr_accessor :balance
def initialize(balance = 0)
@balance = balance
end
def deposit(amount)
@balance += amount if amount > 0
end
def withdraw(amount)
if amount > 0 && amount <= @balance
@balance -= amount
true
else
false
end
end
end
acc = BankAccount.new(1000)
acc.deposit(500)
acc.withdraw(300)
puts "余额:#{acc.balance} 元"
实训8.3 继承与方法重写
定义 Animal 基类与 Dog 子类,子类重写 speak。
< 表示继承;super 调用父类同名方法。
class Animal
def initialize(name)
@name = name
end
def speak
"动物叫声"
end
end
class Dog < Animal
def speak
"#{super}:汪汪!"
end
end
dog = Dog.new("旺财")
puts dog.speak
puts "是 Animal 子类:#{dog.is_a?(Animal)}"
实训8.4 模块与 Mixin
用 module 定义模块并 include 到类中,实现混入。
module 组织方法;include 混入实例方法;extend 混入类方法。
module Printable
def print_info
"#{@name} 可打印"
end
end
module ClassHelper
def create_default
new("默认")
end
end
class Document
include Printable
extend ClassHelper
def initialize(name)
@name = name
end
end
doc = Document.create_default
puts doc.print_info
puts "模块方法:#{doc.respond_to?(:print_info)}"
单元9 · 异常与文件
begin/rescue、ensure、文件读写、CSV 简介
- 异常:begin/rescue/ensure。
- 自定义:继承 StandardError;raise。
- 文件:File.read/write;块形式自动关闭。
实训9.1 异常处理
捕获除零与转换异常,用 ensure 清理。
begin/rescue/ensure;e.message 错误信息。
begin
n = 0
puts 10 / n
rescue ZeroDivisionError => e
puts "除零异常:#{e.message}"
end
begin
Integer("abc")
rescue ArgumentError => e
puts "转换异常:#{e.message}"
ensure
puts "清理资源(总是执行)"
end
实训9.2 自定义异常
定义自定义异常类并在评级时抛出捕获。
自定义异常继承 StandardError;raise 抛出。
class ScoreOutOfRangeError < StandardError; end
def grade(score)
raise ScoreOutOfRangeError, "非法分数:#{score}" if score < 0 || score > 100
case score
when 90..100 then "优秀"
when 60..89 then "及格"
else "不及格"
end
end
begin
puts grade(95)
puts grade(120)
rescue ScoreOutOfRangeError => e
puts "自定义异常:#{e.message}"
end
实训9.3 文件读写
用 File 写入与读取文本,演示块形式自动关闭。
File.write 写入;File.read 读取;File.open 块形式自动 close。
File.write("notes.txt", "第一行内容\n第二行内容")
content = File.read("notes.txt")
puts "文件内容:"
puts content
File.open("notes.txt", "a") do |f|
f.puts "追加的一行"
end
puts "追加后:"
puts File.read("notes.txt")
实训9.4 目录与 CSV
列出目录文件,演示 CSV 读写数据。
Dir.glob 匹配文件;CSV 标准库读写表格。
require "csv"
Dir.mkdir("data") unless Dir.exist?("data")
File.write("data/row1.txt", "内容A")
File.write("data/row2.txt", "内容B")
puts "data 目录文件:"
Dir.glob("data/*").each { |f| puts " #{f}" }
CSV.open("data/users.csv", "w") do |csv|
csv << ["name", "age"]
csv << ["Alice", 25]
csv << ["Bob", 30]
end
puts "CSV 内容:"
CSV.foreach("data/users.csv", headers: true) do |row|
puts "#{row["name"]}:#{row["age"]} 岁"
end
单元10 · 模块与命名空间
模块、Enumerable、each/map、Ruby 标准库
- Enumerable:include + each 获得全部方法。
- 命名空间:module 组织;require 加载。
- 惯用:&:method 符号转块;&. 安全导航。
实训10.1 Enumerable 模块
在自定义类中 include Enumerable,实现 each 即可获得全部集合方法。
include Enumerable + each 方法 => map/select/sort 全可用。
class ScoreList
include Enumerable
def initialize(scores)
@scores = scores
end
def each(&block)
@scores.each(&block)
end
end
scores = ScoreList.new([55, 90, 72, 88, 45])
puts "最大值:#{scores.max}"
puts "及格数:#{scores.count { |s| s >= 60 }}"
puts "总和:#{scores.sum}"
puts "映射:#{scores.map { |s| s * 2 }.join(', ')}"
实训10.2 命名空间与 require
用 module 组织命名空间,require 引入标准库。
module 防止命名冲突;require 加载库;:: 访问常量。
require "date"
require "json"
module Utils
module Math
def self.square(n)
n * n
end
end
end
puts "平方:#{Utils::Math.square(6)}"
puts "今天:#{Date.today}"
puts "JSON 输出:#{JSON.generate({ name: "Ruby", version: 3.2 })}"
实训10.3 each_with_index 与高阶
用 each_with_index、zip 处理数据。
each_with_index 同时取元素与索引;zip 合并数组。
names = ["张三", "李四", "王五"]
names.each_with_index do |name, i|
puts "#{i + 1}. #{name}"
end
scores = [90, 85, 78]
pairs = names.zip(scores)
pairs.each do |name, score|
puts "#{name}:#{score} 分"
end
doubled = names.map.with_index { |n, i| "#{i}:#{n}" }
puts doubled.join(" | ")
实训10.4 Ruby 惯用法
演示符号转 Proc、安全导航 & 等惯用写法。
&:method 符号转块;&. 安全导航避免 nil 异常。
nums = [1, 2, 3, 4]
puts "偶数:#{nums.select(&:even?).join(', ')}"
puts "平方:#{nums.map { |n| n ** 2 }.join(', ')}"
name = nil
puts "安全导航:#{name&.upcase || '默认值'}"
config = { debug: true }
puts "fetch 默认:#{config.fetch(:missing, '未配置')}"
result = [1, 2, 3, 4, 5].inject(0) { |sum, n| sum + n }
puts "inject 求和:#{result}"
单元11 · 正则与元编程
正则表达式、模块混入、define_method、高级特性
- 正则:=~ 匹配;match 捕获组。
- Symbol:to_sym/to_s 互转;哈希键。
- 元编程:define_method 动态方法。
实训11.1 正则表达式匹配
用 =~ 匹配字符串,用 match 提取捕获组。
=~ 返回匹配位置;match 返回 MatchData。
text = "订单号 2026-0822-001,金额 45.6 元"
if m = text.match(/订单号 ([\d-]+)/)
puts "订单号:#{m[1]}"
end
if text =~ /金额 ([\d.]+)/
puts "金额:#{Regexp.last_match(1)} 元"
end
email = "user@example.com"
puts "邮箱匹配:#{!!(email =~ /^[\w.-]+@[\w.-]+\.\w+$/)}"
实训11.2 Symbol 与字符串互转
演示 Symbol 与字符串的互转与哈希键用法。
to_sym/to_s 互转;符号作为哈希键高效。
str = "hello"
sym = str.to_sym
puts "字符串转符号:#{sym}"
puts "符号转字符串:#{sym.to_s}"
puts "符号相等:#{sym == :hello}"
config = { port: 8080, host: "localhost" }
puts "端口:#{config[:port]}"
puts "键类型:#{config.keys.first.class}"
实训11.3 module_function 与 mixin
用 module_function 提供模块方法,用 extend 混入类方法。
module_function 使方法既可模块调用又可混入;extend 混入类方法。
module Formatter
def pretty(value)
"[#{value}]"
end
module_function :pretty
end
puts Formatter.pretty("模块调用")
class Report
extend Formatter
end
puts Report.pretty("extend 混入")
实训11.4 define_method 元编程
用 define_method 动态定义方法。
define_method 在运行时创建方法;send 动态调用。
class Dynamic
[:add, :sub, :mul].each_with_index do |op, i|
define_method(op) do |a, b|
case i
when 0 then a + b
when 1 then a - b
when 2 then a * b
end
end
end
end
d = Dynamic.new
puts "add:#{d.add(10, 5)}"
puts "sub:#{d.sub(10, 5)}"
puts "mul:#{d.mul(10, 5)}"
puts "send 动态调用:#{d.send(:add, 1, 2)}"
单元12 · 综合项目实训
综合运用 Ruby 知识完成项目
- 综合:类、数组、哈希、块、异常组合。
- 工程化:Struct、sort_by、格式化输出。
实训12.1 学生成绩管理系统
用类与数组实现学生管理:添加、排序、统计。
class + attr_accessor + sort_by + 统计。
class Student
attr_accessor :name, :chinese, :math
def initialize(name, chinese, math)
@name = name
@chinese = chinese
@math = math
end
def average
(@chinese + @math) / 2.0
end
end
students = [
Student.new("张三", 90, 85),
Student.new("李四", 78, 92),
Student.new("王五", 88, 76)
]
sorted = students.sort_by { |s| -s.average }
puts "姓名\t语文\t数学\t平均"
sorted.each do |s|
puts "#{s.name}\t#{s.chinese}\t#{s.math}\t#{format('%.1f', s.average)}"
end
avg = students.map(&:average).sum / students.size
puts "全班平均:#{format('%.1f', avg)}"
puts "第一名:#{sorted.first.name}"
实训12.2 待办事项管理器
实现待办事项:添加、标记完成、过滤未完成。
Struct 轻量结构体 + 数组操作 + 过滤。
Task = Struct.new(:id, :title, :done)
tasks = [
Task.new(1, "学习 Ruby 语法", false),
Task.new(2, "完成实训项目", false),
Task.new(3, "复习集合", false)
]
tasks[1].done = true
puts "待办清单:"
tasks.each do |t|
mark = t.done ? "✓" : " "
puts "[#{mark}] #{t.id}. #{t.title}"
end
pending = tasks.select { |t| !t.done }
puts "未完成数:#{pending.size}"
实训12.3 词频统计器
统计文本单词出现次数,输出出现最多的单词。
split + Hash 默认值 + max_by 组合。
text = <<~TEXT
ruby is elegant ruby is powerful ruby is fun
ruby is concise and expressive
TEXT
words = text.downcase.split
freq = Hash.new(0)
words.each { |w| freq[w] += 1 }
freq.sort_by { |_, c| -c }.each do |word, count|
puts "#{word}:#{count}"
end
top = freq.max_by { |_, count| count }
puts "出现最多:#{top[0]},#{top[1]} 次"
实训12.4 简易计算器
实现支持 + - * / 的计算器:解析表达式并计算。
split 解析 + case 分发 + 异常处理。
def calculate(expr)
parts = expr.split
raise "格式错误" unless parts.size == 3
a = Float(parts[0])
b = Float(parts[2])
case parts[1]
when "+" then a + b
when "-" then a - b
when "*" then a * b
when "/"
raise "除数不能为 0" if b.zero?
a / b
else
raise "不支持的运算符:#{parts[1]}"
end
end
["10 + 5", "10 * 3", "10 / 0", "abc + 1"].each do |expr|
begin
puts "#{expr} = #{calculate(expr)}"
rescue => e
puts "#{expr} -> 错误:#{e.message}"
end
end