Ruby基础_2

1.2 Ruby之语法

总体来说,个人感觉Ruby语法与Python语法较为类似。

1.2.1 Ruby的输入与输出

RuBy的输入会自动带入换行符,因此需要使用gets.chomp提取纯净的字符串。

Ruby的输出也有三种方式,分别是p、puts、print。它们之间输出方式有差异:

- p 方法会以可读性更好的方式输出对象,包括对象的类型和结构。
- puts 方法会输出对象,并在末尾添加换行符。
- print 方法会输出对象,但不会添加换行符。

运行下列程序:

a=gets.chomp
p a
print a
puts a

有结果:

PS C:\Users\Administrator\Desktop> ruBy RuByTest.rb
测试
"测试"
测试测试

在输出字符串时,单引号与双引号皆可,双引号多了一个插值语法:

a=gets.chomp
puts "A#{a}B"

返回

PS C:\Users\Administrator\Desktop> ruBy RuByTest.rb
测试
A测试B

不仅如此,与单引号相比,双引号支持转义操作,如/n。

1.2.2 Ruby的注释

#单行注释

=begin
a="多行注释"
=end

__END__
之后全注释

1.2.3 Ruby的条件语句

1.2.3.1 case-when条件

较为简单,见实例:

op=gets
a=gets
b=gets
case op.chomp
	when "+"
		jg=a.to_i+b.to_i
	when "-"
		jg=a.to_i-b.to_i
end
puts jg
1.2.3.2 if分支语句

较为简单,见实例:

a=gets.chomp.to_i
if	a>80
	puts "very good"
elsif	a>60
	puts "enough"
else
	puts "death"
end

其中表“或”与“且”的符号仍是||与&&,不同条件之间可不加括号分隔。

在简单两种情况的if-else运算时,完全可以使用三项运算减少代码冗余:

条件 ? 处理1:处理2

当条件为真时执行处理1,当条件为假时执行处理2。

1.2.4 Ruby的循环语句

1.2.4.1 while-do循环

利用while-do循环实现猜数游戏:

#rand while break
puts "game begins"
a=rand(1..20)
i=0
while i!=1 do
	puts "game continue"
	b=gets.chomp.to_i
	if a>b
		puts 'be bigger'
	elsif a<b
		puts 'be smaller'
	else
		i=1
		puts "congratulation!,the answer is #{a}!!!"
	end
end
1.2.4.2 for循环

有代码:

#循环数组
l1=["q1","q2","q3","q4"]
for i in l1 do
    puts i
end

#循环1到5
for num in 1..5 do
    puts num
end

#循环1到4
for num in 1...5 do
    puts num
end

有输出:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
q1
q2
q3
q4
1
2
3
4
5
1
2
3
4

可以看到,闭区间与开区间的区别就在于..与...之间。

1.2.4.3 downto循环
(9.downto(0)).each do |i|
  puts i
  if i == 5
    break
  end
end

1.2.5 Ruby的函数

运行下列函数,体会Ruby内置的可忽略参数与默认参数机制:

def fun1
    puts "函数1"
end

def fun2(*a)
    print "函数2"
    puts a
end

def fun3(a="asd")
    print "函数3"
    puts a
end

fun1
fun2("qwe")
fun2
fun3("zxc")
fun3()

结果:

PS C:\Users\Administrator\Desktop>  ruBy RuByTest.rb
函数1
函数2qwe
函数2函数3zxc
函数3asd

Ruby中的函数也可以应用全局变量,如下例:

$x = 10

def update_global_variable
  $x = 20
end

puts $x  # 输出 10
update_global_variable
puts $x  # 输出 20

1.2.6 Ruby的对象

1.2.6.1 对象的基础用法

具体语法如下所示,另外需要说明,按我们现在的操作,成员变量无法像C#一样直接调用,需要用如下方法:

class Player
    #构造函数
    def initialize(name="Koma")
        #@后相当于成员
        @id=name
    end
    def claim
        p @id
    end
    def claim2
        @id
    end
end

Symbolism=Player.new("Symbol")
Symbolism.claim
p "输出成员变量"
p Symbolism.claim2

直接调用属性的方法下一节会讲到。

1.2.6.2 对象的内部成员的探究
1.2.6.2.1 instance_methods函数

列出对象内部的方法。

class Player
    #构造函数
    def initialize(name="Koma")
        #@后相当于成员
        @id=name
    end
    def claim
        p @id
    end
    def claim2
        @id
    end
end

Symbolism=Player.new("Symbol")
puts Player.instance_methods(false)
puts "--------------------------------"
puts Player.instance_methods(true)

返回值为:

PS C:\Users\Administrator\Desktop> ruBy RuByTest.rb
claim
claim2
--------------------------------
claim
claim2
singleton_class
dup
itself
methods
singleton_methods
protected_methods
private_methods
public_methods
instance_variables
instance_variable_get
instance_variable_set
instance_variable_defined?
remove_instance_variable
instance_of?
kind_of?
is_a?
display
public_send
class
tap
frozen?
extend
yield_self
then
clone
<=>
===
!~
method
public_method
singleton_method
nil?
eql?
respond_to?
define_singleton_method
hash
freeze
inspect
object_id
send
to_s
to_enum
enum_for
equal?
!
__send__
==
!=
__id__
instance_eval
instance_exec

Player.instance_methods(false) 和 Player.instance_methods(true) 的区别在于是否包含继承的方法。

- Player.instance_methods(false) 会返回 Player 类自身定义的实例方法,不包括从父类继承的方法。
- Player.instance_methods(true) 会返回 Player 类及其父类继承的所有实例方法。

1.2.6.2.2 respond_to?函数与属性寄存器

见下代码:

class Player
    attr_accessor :id
    #构造函数
    def initialize(name="Koma")
        #@后相当于成员
        @id=name
        @attribute=100
    end
    def claim
        p @attribute
    end
end

Symbolism=Player.new("syb")
if Symbolism.respond_to?("id")
    p Symbolism.id
else
    p "该属性目前不可读"
end

if Symbolism.respond_to?("attribute")
    p Symbolism.id.to_s
else
    p "该属性目前不可读"
end

if Symbolism.respond_to?("claim")
    Symbolism.claim
else
    p "该函数目前不可读"
end

if Symbolism.respond_to?("claim2")
    Symbolism.claim2
else
    p "该函数目前不可读"
end

(1)attr_accessor,一个属性寄存器,在此后写过的属性大概相当于public过了,可以直接调用。

(2)respond_to?,调查对象的方法、属性是否可用,返回的是一个布尔值。

1.2.6.3 Ruby的静态函数

如下,可以用两种方式调用:

class Player
    attr_accessor :id
    #构造函数
    def initialize(name="Koma")
        #@后相当于成员
        @id=name
        @attribute=100
    end
    def claim
        p @attribute
    end
    def self.static
        p "这是一个静态函数"
    end
end

Player.static
Player::static

输出:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
"这是一个静态函数"
"这是一个静态函数"

值得注意的是,在静态函数中,不可以调用非静态的成员,否则会报错。

1.2.6.4 Ruby的类之继承

程序如下:

class Player
    attr_accessor :id
    #构造函数
    def initialize(name="Koma")
        #@后相当于成员
        @id=name
        @attribute=100
    end
    def claim
        p @attribute
    end
end

class Young_player < Player
    def child_claim
        p id
    end
end

Symbolism=Young_player.new("syb")
Symbolism.claim
Symbolism.child_claim

输出:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
100
"syb"

最重要的是,类的名称首字母一定大写,这个重要规则之前都没有提到,在此补充。

1.2.7 Ruby的数组

1.2.7.1 数组的定义
a=["q1","q2","q3","q4"]
p a
puts a
print a

注意这三种输出也是不同的:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
["q1", "q2", "q3", "q4"]
q1
q2
q3
q4
["q1", "q2", "q3", "q4"]

如果想要输出数组中某一值,只需要:

puts a[3]
1.2.7.2 数组的循环
a=["q1","q2","q3","q4"]

a.each do |i|
    puts "输出:#{i}"
end

a.each_with_index do |i,q|
    puts "第#{q}次输出,启动#{i}"
end

输出的结果为:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
输出:q1
输出:q2
输出:q3
输出:q4
第0次输出,启动q1
第1次输出,启动q2
第2次输出,启动q3
第3次输出,启动q4

可以看出,这两种输出方式没有明显不同,第二种循环方式把脚标也带上了罢了。

1.2.7.3 数组的链接
a=["q1","q2","q3","q4"]

if a.respond_to?("each")
    puts a.join(";")
end

这里补充一个知识点,respond_to?仍然可以应用到ruby的数组上,毕竟ruby号称万物皆对象,究极的OOP。

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
q1;q2;q3;q4

1.2.8 字符串运算

1.2.8.1 字符串+运算

不赘述,通用。

a=["q1","q2","q3","q4"]
puts a[0]+a[1]+a[2]+a[3]

输出:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
q1q2q3q4
1.2.8.2 字符串<<运算

看代码:

a="Symbolism"
b=" ,blessing"
a<<b
puts a
puts b

输出:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
Symbolism ,blessing
 ,blessing

也就是说,a<<b的操作相当于a=a+b。

1.2.8.3 字符串*运算

代码:

a="Symbolism"
puts a*3

输出:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
SymbolismSymbolismSymbolism
1.2.8.4 字符串截取运算
str = "0123456789"  # 10-character string
substring = str[5..7]

puts substring

1.2.9 Ruby的哈希表

1.2.9.1 一般哈希表

代码:

mvp_rank={
    "curry"=>28.1,
    "harden"=>30.3,
    "lebron"=>26,
}

puts mvp_rank
puts mvp_rank["harden"]

输出:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
{"curry"=>28.1, "harden"=>30.3, "lebron"=>26}
30.3
1.2.9.2 JSON形式哈希表

代码:

player={
    name:"harden",
    age:28,
    point:30.3
}

puts player
puts player[:name]+";"+player[:age].to_s+";"+player[:point].to_s+";"

输出:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
{:name=>"harden", :age=>28, :point=>30.3}
harden;28;30.3;

1.2.10 Ruby的模板

1.2.10.1 模板的简单应用

见代码:

module BaseFunc
    Version="0.0.1"

    def v
        return Version
    end

    def add(a,b)
        return a+b
    end

    def self.showVersion
        return Version
    end

    #定义静态方法
    module_function :v
end

puts BaseFunc::Version
puts BaseFunc::showVersion
puts BaseFunc.showVersion
puts BaseFunc.v

有输出:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
0.0.1
0.0.1
0.0.1
0.0.1

(1)模板有了字段成员。

(2)模板函数在声明时即可被声明为静态。

(3)可以用module_function补充定义静态模板函数。

(4)模板函数是否静态皆可调用模板成员。

1.2.10.2 类继承模板

见代码:

module BaseFunc
    Version="0.0.1"

    def v
        return Version
    end

    def add(a,b)
        return a+b
    end

    def self.showVersion
        return Version
    end

    #定义静态方法
    module_function :v
end

class Baseclass include BaseFunc
end

puts Baseclass::Version
myCls=Baseclass.new
puts myCls.add(10,20)

输出为:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb       
0.0.1
30

(1)通过”class 类 include 模块“语法实现从模块到类的继承。

(2)模块中的静态函数不可被类继承。

(3)模块成员可以被继承,并可以直接通过::打印出来。

1.2.10 Ruby的例外处理

见下列代码:

begin
    #有可能发生错误的处理
    puts "处理开始"
    #raise "my raise error!"
    #10/0
rescue=>e
    #错误发生时
    puts "错误发生!"
    puts e
else
    #正常处理时
    puts "正常处理"
ensure
    #最后处理,无论是否发生错误
    puts "最后的扫尾处理"
end

当工作流运行正常时:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
处理开始
正常处理
最后的扫尾处理

当工作流发生异常时:

PS C:\Users\Administrator\Desktop> ruby RubyTest.rb
处理开始
错误发生!
divided by 0
最后的扫尾处理

具体流程备注里写的很明白了。

1.2.11 Ruby的其余函数

1.2.11.1 随机数函数
a=rand(1..20)
1.2.11.2 字符串向整形的转化
b=gets.chomp.to_i

同理,还有数字转字符串:to_s、整形转浮点:to_f。

1.2.11.3 矩阵运算函数

定义矩阵并按行列索引:

require 'matrix'

# 创建一个矩阵
matrix = Matrix[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# 按行列索引输出元素
element = matrix[1, 2]  # 第2行第3列的元素,索引从0开始

puts element

求逆矩阵函数:

require 'matrix'

# 创建一个矩阵
matrix = Matrix[[1, 2], [3, 4]]

# 计算矩阵的逆矩阵
inverse_matrix = matrix.inverse

puts inverse_matrix
1.2.11.4 程序运行时间

这里给出第一种,用于测试简单代码块儿的时间。

require 'benchmark'

# 定义一个需要测试运行时间的代码块
def my_method
  sum = 0
  (1..1000000).each { |i| sum += i }
end

# 使用Benchmark模块测试代码块的运行时间
time = Benchmark.realtime do
  my_method
end

puts "程序运行时间:#{time} 秒"

然后第二种测算时间的方式比较灵活。

# 记录开始时间戳
start_time = Time.now.to_i

# 这里是你想要测试的Ruby程序代码
# 例如,一个简单的循环
(1..1000).each do |i|
  i = i + 1
  yy = i *1000 + 1
  puts yy
end

# 记录结束时间戳
end_time = Time.now.to_i

# 计算运行时间
runtime = end_time - start_time

# 输出运行时间
puts "程序运行时间:#{runtime} 秒"
1.2.11.5 程序消耗内存
require 'memory_profiler'

report = MemoryProfiler.report do
  arr = []
  1000000.times { arr << "a" * 1000 }
end

puts "Total allocated memory: #{report.total_allocated_memsize / 1048576} MB"

1.2.12 Ruby调用其他程序集的方法

1.2.12.1 Ruby调用dll

要在Ruby中调用C++编写的DLL,你可以使用Ruby的Win32API库。这个库允许Ruby代码调用Windows的动态链接库(DLL)中的函数。以下是详细步骤和示例:

步骤 1: 创建C++ DLL

首先,你需要有一个C++ DLL。这里是一个简单的示例,它包含一个函数add,用于计算两个整数的和。

// add.cpp
extern "C" {
    __declspec(dllexport) int add(int a, int b) {
        return a + b;
    }
}

使用Visual Studio或其他编译器将上述代码编译成DLL。确保使用__declspec(dllexport)来导出函数。

步骤 2: 编译DLL

在Visual Studio中,创建一个新的项目,选择“动态链接库(DLL)”作为项目类型。将上述代码添加到项目中,并编译。编译后,你将得到一个.dll文件。

步骤 3: 在Ruby中调用DLL

在Ruby中,你可以使用Win32API库来加载并调用这个DLL中的函数。以下是如何做到这一点的示例代码:

require 'Win32API'

# 创建一个Win32API对象来调用DLL中的add函数
# 参数分别是:DLL文件路径,函数名,参数类型数组,返回值类型
add_function = Win32API.new('path/to/your/add.dll', 'add', ['I', 'I'], 'I')

# 调用函数
result = add_function.call(5, 3)

# 输出结果
puts "The result is #{result}"

注意事项

1. 确保DLL文件的路径正确无误。

2. 确保DLL中的函数名与你在Ruby代码中使用的一致。

3. 如果在调用时遇到任何问题(如找不到符号),请检查你的DLL是否正确编译并导出了所需的函数。

4. 如果DLL正在被其他程序使用,可能会遇到无法写入的问题。确保没有其他程序正在使用该DLL,或者在尝试重新编译前关闭使用该DLL的程序。

通过以上步骤,你可以在Ruby程序中调用C++编写的DLL中的函数。

在Ruby的Win32API库中使用的参数具体含义如下:

1. 'path/to/your/add.dll' - 这是DLL文件的路径。你需要提供DLL文件的完整路径或相对路径,确保Ruby能找到并加载这个DLL。

2. 'add' - 这是你想要调用的函数名。这个名字必须与DLL中导出的函数名完全匹配。

3. ['I', 'I'] - 这是一个数组,表示函数参数的类型。每个字符代表一个参数的类型。在这个例子中,'I'代表整数(Integer)。因此,['I', 'I']表示这个函数接受两个整数作为参数。

4. 'I' - 这表示函数的返回值类型。在这个例子中,'I'同样代表整数。

返回值类型

Win32API支持的返回值类型有限,主要包括:

'I' 或 'L':表示整数(Integer)或长整数(Long),在32位系统中通常是32位,在64位系统中可能是64位。

'S':表示字符串(String)。如果函数返回一个字符串,可以使用这个类型。

'P':表示指针(Pointer),可以用来接收字符串或数组的地址。

关于字符串、数组和列表的返回值

字符串:可以通过返回类型'S'或'P'(指针)来处理。如果使用'P',你可能需要在Ruby中进一步处理这个指针来转换成字符串。

数组和列表:Win32API本身不直接支持数组或列表作为返回类型。如果需要从DLL获取数组或列表,通常会返回一个指针(使用'P'),然后在Ruby中根据需要解析这个指针。

如果你的函数需要返回复杂的数据结构(如数组或结构体

),通常的做法是返回一个指针,并在Ruby中使用额外的库(如ffi)来解析这些复杂的数据类型。

具体参数类型简写如下:

# Verbose data types that can be used instead of single letters
      DATA_TYPES = {
         'ATOM'         => 'I',
         'BOOL'         => 'B',
         'BOOLEAN'      => 'B',
         'BYTE'         => 'I',
         'CALLBACK'     => 'K',
         'CHAR'         => 'I',
         'COLORREF'     => 'L',
         'DWORD'        => 'L',
         'DWORDLONG'    => 'L',
         'DWORD_PTR'    => 'P',
         'DWORD32'      => 'I',
         'DWORD64'      => 'L',
         'HACCEL'       => 'L',
         'HANDLE'       => 'L',
         'HBITMAP'      => 'L',
         'HBRUSH'       => 'L',
         'HCOLORSPACE'  => 'L',
         'HCONV'        => 'L',
         'HDC'          => 'L',
         'HFILE'        => 'I',
         'HKEY'         => 'L',
         'HFONT'        => 'L',
         'HINSTANCE'    => 'L',
         'HKEY'         => 'L',
         'HLOCAL'       => 'L',
         'HMENU'        => 'L',
         'HMODULE'      => 'L',
         'HRESULT'      => 'L',
         'HWND'         => 'L',
         'INT'          => 'I',
         'INT_PTR'      => 'P',
         'INT32'        => 'I',
         'INT64'        => 'L',
         'LANGID'       => 'I',
         'LCID'         => 'L',
         'LCTYPE'       => 'L',
         'LONG'         => 'L',
         'LONGLONG'     => 'L',
         'LONG_PTR'     => 'P',
         'LONG32'       => 'L',
         'LONG64'       => 'L',
         'LPARAM'       => 'P',
         'LPBOOL'       => 'P',
         'LPBYTE'       => 'P',
         'LPCOLORREF'   => 'P',
         'LPCSTR'       => 'P',
         'LPCTSTR'      => 'P',
         'LPCVOID'      => 'L',
         'LPCWSTR'      => 'P',
         'LPDWORD'      => 'P',
         'LPHANDLE'     => 'P',
         'LPINT'        => 'P',
         'LPLONG'       => 'P',
         'LPSTR'        => 'P',
         'LPTSTR'       => 'P',
         'LPVOID'       => 'L',
         'LPWORD'       => 'P',
         'LPWSTR'       => 'P',
         'LRESULT'      => 'P',
         'PBOOL'        => 'P',
         'PBOOLEAN'     => 'P',
         'PBYTE'        => 'P',
         'PHKEY'        => 'P',
         'SC_HANDLE'    => 'L',
         'SC_LOCK'      => 'L',
         'SERVICE_STATUS_HANDLE' => 'L',
         'SHORT'        => 'I',
         'SIZE_T'       => 'P',
         'TCHAR'        => 'L',
         'UINT'         => 'I',
         'UINT_PTR'     => 'P',
         'UINT32'       => 'I',
         'UINT64'       => 'L',
         'ULONG'        => 'L',
         'ULONGLONG'    => 'L',
         'ULONG_PTR'    => 'P',
         'ULONG32'      => 'L',
         'ULONG64'      => 'L',
         'USHORT'       => 'I',
         'USN'          => 'L',
         'WINAPI'       => 'L',                           
         'WORD'         => 'I'
      }      

1.2.13 Ruby对文件操作

1.2.13.1 文件的复制
# 原始文件的路径
source_file_path = 'C:/Users/Administrator/Desktop/ach/SymPlugin/mod_coord.txt'
# 目标文件的路径,即复制后的文件名
destination_file_path = 'C:/Users/Administrator/Desktop/ach/SymPlugin/mod_coord1.txt'
# 使用FileUtils.copy方法复制文件
FileUtils.copy(source_file_path, destination_file_path)
1.2.13.2 文件的写入

首先加一个追加写入:

# 指定要追加写入的文件路径
file_path = destination_file_path
# 使用'a'模式打开文件,如果文件不存在,将会创建文件
File.open(file_path, 'a') do |file|
  # 向文件中追加内容
  file.puts a.bounds.corner(0).to_a[0]
  file.puts a.bounds.corner(0).to_a[1]
  file.puts a.bounds.corner(0).to_a[2]
end

然后再来一个一般写入(会覆盖):

File.open('C:\Users\Administrator\Desktop\ach\SymPlugin\face_coords.txt', "w") do |file|
  grid.each do |i|
    file.puts i[0].to_a[0].to_s
  end
end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值