11/08/2018, 23:07

2-3 Kiểm soát "dòng chảy"

Khi thực hiện một chương trình, nó có một thứ gọi là "dòng chảy", tức là thứ tự thực hiện các lệnh. Cho đến thời điểm này, những chương trình mà tôi đã giới thiệu đều thực hiện các lệnh từ trên trở xuống, là những chương trình cực kì đơn giản. Tuy nhiên, các chương trình trên thực tế không chỉ đơn ...

Khi thực hiện một chương trình, nó có một thứ gọi là "dòng chảy", tức là thứ tự thực hiện các lệnh. Cho đến thời điểm này, những chương trình mà tôi đã giới thiệu đều thực hiện các lệnh từ trên trở xuống, là những chương trình cực kì đơn giản. Tuy nhiên, các chương trình trên thực tế không chỉ đơn giản thực hiện từ trên xuống dưới một chiều như vậy. Trong ngôn ngữ lập trình có những tổ chức thực hiện công việc kiểm soát thứ tự chạy chương trình đó. Tất nhiên, có rất nhiều những công cụ dùng để kiểm soát dòng chảy của Ruby rất tiện lợi.

Dùng hàm [if] thể biểu thị điều kiện

Nếu dùng hàm if chúng ta có thể điều chỉnh thao tác của chương trình theo tùy từng điều kiện. Hàm if được sử dụng như dưới đây.

if công thức điều kiện
khi điều kiện được hình thành thì những xử lý được chạy
....
....
end

Nếu không muốn điền thẳng giá trị số vào thì ta có thể dùng biến số a, ví dụ chúng ta có thể chỉ định một số lệnh như dưới đây.

● Nếu a bằng một giá trị nào đó ● Nếu a không bằng một giá trị nào đó ● Nếu a lớn hơn một giá trị nào đó

Đây là ví dụ một chương trình sử dụng hàm if.

a=0
if a==0
   puts "A"
   puts "B"
   puts "C"
end
puts "Bye"

Hãy chú ý bộ phận dưới đây

if a ==0

Dòng này thực hiện lệnh kiểm tra điều kiện "nếu a bằng 0". Sử dụng dấu == thì có thể so sánh hai giá trị nêu trên. Tại dòng đầu, a được dùng thay thế cho giá trị 0 nên điều kiện này có hình thành. Nếu điều kiện được hình thành thì các lệnh từ if cho đến end sẽ được thực hiện. Tức là sẽ được thực hiện các lệnh dưới đây.

puts "A"
puts "B"
puts "C"

Sau khi thực hiện lệnh được ghi từ phần if~end thì lệnh bên dưới phần end sẽ được thực hiện.Vì vậy, kết quả chương trình sẽ trở nên như dưới đây.

A
B
C
Bye

Nếu chúng ta điền cho a một giá trị khác 0, điều kiện không được thỏa mãn. Nếu điều kiện không được thỏa mãn thì bộ phận lệnh được viết từ phần if~end sẽ không được thực hiện.

a=1
if a==0
   puts "A"
   puts "B"
   puts "C"
end
puts "Bye"

[Kết quả hiển thị]

Bye

Lùi đầu dòng

Trong chương trình ví dụ ở trên, dòng được bao bởi if~end đều được lùi vào một khoảng trống so với những dòng trên.

a=1
if a==0
   puts "A"   # <-
   puts "B"   # <- đầu dòng đều được cho thêm khoảng cách
   puts "C"   # <-
end
puts "Bye"

Đây là thứ để xem chương trình dễ hơn nên người ta gọi nó là Indent (lùi đầu dòng). Trong khi chạy chương trình thì ta có thêm space hay tab ở đầu dòng thì nội dung chương trình không thay đổi, kết quả vẫn giống nhau thì người ta dùng hay không dùng lùi đầu dòng cũng được.

a=1
if a==0
puts "A"
puts "B"
puts "C"
end
puts "Bye"

Tuy nhiên, nếu viết như trên thì ta không thể nhìn thấy rõ khu vực lệnh sẽ chạy khi điều kiện được thỏa mãn nên rất khó hiểu. Nếu ta dùng cách đầu dòng đối với khu vực bảo trong khoảng if~end thì chương trình sẽ rõ nhìn hơn.

a=1
if a==0
   puts "A"
   puts "B"
   puts "C"
end
puts "Bye"

Tại Ruby thì người ta dùng 2 lần phím Space để lùi đầu dòng.

Các kí hiệu dùng để so sánh hai giá trị

Dấu [==] được gọi là dấu dùng để so sánh hai giá trị. Ngoài ra còn có rất nhiều loại dấu dùng để so sánh hai giá trị.

| Dấu | Ý nghĩa |Ví dụ|Ý nghĩa của ví dụ| |--------|--------| | == | bằng |a==0|a bằng 0| |!=|không bằng|a!=0|a khác 0| |>|lớn hơn|a>0|a lớn hơn 0| |<|nhỏ hơn|a<0|a nhỏ hơn 0| |>=|lớn hơn hoặc bằng|a>=0|a lớn hơn hoặc bằng 0| |<=|nhỏ hơn hoặc bằng|a<=0|a nhỏ hơn hoặc bằng 0|

Đây là những vsi dụ chương trình sử dụng những dấu so sánh ngoài [==]

if a!=0
  # nếu a không bằng 0 thì sẽ thực hiện lệnh tiếp theo
end
if a > 0
  # nếu a có giá trị lớn hơn 0 thì thực hiện lệnh tiếp theo
end
if a <= 0
  # nếu a có giá trị nhỏ hơn hoặc bằng 0 thì thực hiện lệnh tiếp theo
end

Chúng ta cũng có thể so sánh biến số với biến số

a=10
b=5
if a>b
  # nếu a lớn hơn b thực hiện lệnh tiếp theo
end

Đúng và sai

Nếu một điều kiện nào đó thỏa mãn thì người ta nói điều kiện đó [Đúng]. Ngược lại, nếu một điều kiện không được thỏa mãn thì người ta gọi điều kiện đó [Sai].

Nếu a=0 thì

a==0 -> đúng a!=0 -> sai a>=0 -> đúng a<0 -> sai

If và Else

Nếu sử dụng [else] thì chúng ta có thể tạo ra những câu lệnh được chạy khi điều kiện không được thỏa mãn.

Ví dụ

hp=1
if hp==0
  puts "Nhân vật đã chết"
else
  puts "Nhân vật vẫn khỏe"
end

[Kết quả hiển thị]

Nhân vật vẫn khỏe

Trong chương trình này, điều kiện không được thỏa mãn nên phần lệnh được thực hiện Nếu mọi người có thể hiểu được các loại so sánh và điều kiện [if~else~end]thì ngày càng trở nên master về nó là điều đương nhiên. Dưới đây tôi sẽ giới thiệu kĩ hơn về những chức năng tiện lợi để việc kiểm soát thứ tự thực hiện lệnh, công việc xử lý điều kiện được thực hiện dễ dàng hơn.

True và False

Những công thức điều kiện như [a==0] hay [b>5] đều sẽ trả lại một giá trị. Giá trị được trả lại nhất định sẽ nhận 2 giá trị là True hoặc False. Nếu câu điều kiện đúng thì giá trị trả lại sẽ là true, ngược lại nếu câu điều kiện sai thì giá trị trả lại sẽ là false.

Chúng ta có thể viết trực tiếp vào chương trình là [true] hoặc [false] như dưới đây.

if true
  puts "true!"
end
if false
  puts "false!"
end

[Kết quả hiển thị]

true!

Nếu chúng ta sử dụng kí hiệu [p] thì cũng có thể đưa ra kết quả của câu điều kiện là true hay false.

a=0
p a==0
# biểu thị kết quả của điều kiện

[Kết quả biểu thị]

true

elsif

Giả sử trong game có một nhân vật tên là Slime. Con slime này có HP là số máu mà nó còn, số máu của nhân vật được biểu thị bởi hp. Thông qua số hp này mà tôi muốn biểu thị 3 tin nhắn sau.

Giá trị hp Tin nhắn biểu thị
0 Slime đã chết
1~7 Slime đang yếu
8~ Slime còn rất khỏe

Nếu chúng ta thực hiện dãy [if~else~end] trong dãy [if~else~end] thì vẫn có thể biểu thị được 3 tin nhắn muốn hiển thị.

if hp == 0
  puts "Slime đã chết"  # hp: 0
else
  if hp <=5
    puts "Slime đang yếu"  # hp: 1~7
  else
    puts "Slime còn rất khỏe"  # hp: 8~
  end
end

Nếu ta dùng lệnh elsif thì có thể viết ngắn lại như sau:

hp=3
if hp==0
  puts "Slime đã chết"
elsif hp<=5
  puts "Slime đang yếu"
else
  puts "Slime còn rất khỏe"
end

[Kết quả hiển thị]

Slime đang yếu

[elsif] được sử dụng khi điều kiện if ban đầu không được thỏa mãn mà mình muốn check tiếp điều kiện tiếp theo.

Chúng ta cũng có thể sử dụng liên tiếp [elsif] như dưới đây

hp=7
if hp==0
  puts "Slime đã chết"
elsif hp<=3
  puts "Slime đang cận kề cái chết"
elsif hp<=5
  puts "Slime đang yếu"
elssif hp <=7
  puts "Slime đang khỏe"
else
  puts "Slime đang rất khỏe"
end

[Kết quả hiển thị]

Slime đang khỏe

Điều kiện and

Khi chúng ta gặp phải trường hợp "Chỉ thực hiện lệnh khi cả hai điều kiện được thỏa mãn" thì mình phải làm thế nào?

Ví dụ, chúng ta có 2 điều kiện như dưới đây.

● Điều kiện A ---- a bằng 0 -> a==0 ● Điều kiện B ---- b lớn hơn 0 -> b>0

Nếu có trường hợp điều kiện là cả hai điều kiện này đều phải đúng thì chúng ta có 1 cách là dùng 2 lần hàm if.

if a==0
  if b==0
    puts "a và b đều bằng 0"
  end
end

Trong chương trình bên trên, câu if đầu tiên ra lệnh điều tra xem a có bằng 0 hay không, chỉ khi a=0 thì câu if tiếp theo mới được thực hiện. Nếu câu if so sánh b có bằng 0 hay không cũng đúng thì câu lệnh puts sẽ được thực hiện.

Trong trường hợp như thế này thì chúng ta có thể sử dụng câu lệnh and. Nếu sử dụng câu lệnh and thì chương trình sẽ được viết như sau

if a==0 and b==0
  puts " a và b đều bằng 0 "
end

Chúng ta viết hai câu điều kiện và dùng lệnh and ở giữa như sau

if A and B
  xử lý khi thỏa mãn đồng thời 2 điều kiện AB
end

Câu lệnh or

Cũng giống như keyword and thì chúng ta có keyword or. Từ này được dùng khi ta muốn lệnh bên dưới được thực hiện khi một trong hai hoặc cả hai điều kiện A và B được thỏa mãn. Như chương trình dưới đây, khi chỉ cần 1 trong 2 điều kiện [a bằng 0] hoặc [b bằng 0] đúng thì lệnh puts sẽ được thực hiện.

if a==0 and b==0
  puts "[a bằng 0] hoặc [b bằng 0]"
end

Về cách sử dụng or là như dưới đây.

if A or B
  Phần xử lý khi chỉ cần 1 trong 2 điều kiện A hoặc B thỏa mãn
end

Lệnh không được thực hiện khi ta dùng or này chỉ xảy ra khi cả hai điều kiện A và B sai.

Kết hợp [and] và [or]

Chúng ta cũng có thể sử dụng [and] và [or] với 2 điều kiện trở lên.

if a==0 and b==0 and c==0
  puts " Cả a, b, c đều bằng 0"
end
if a==0 or b==0 or c==0
  puts "Ít nhất a, b, c có một số bằng 0"
end

Chúng ta cũng có kết hợp đồng thời [and] và [or]

A and B or C

Với điều kiện như thế này, thì đầu tiên máy tính sẽ thực hiện xem [A and B] có đúng không, sau đó kết hợp kết quả [A and B] với điều kiện C qua [or]. Sẽ dễ hiểu hơn nếu chúng ta dùng ngoặc đơn.

(A and B) or C

Nếu muốn kết hợp kết quả [B or C] trước rồi kết hợp với A qua [and] thì chúng ta có thể viết như sau:

A and (B or C)

Phần ở trong ngoặc đơn sẽ được ưu tiên xử lý trước.

Giá trị sai chỉ là false và nil

Trả lời giá trị của câu điều kiện (true/false) thì tôi đã giới thiệu ở p.51. Nếu sử dụng [if] thì chúng ta có thể đưa ra câu trả lời ngoài [true/false]. Chương trình dưới đây sẽ điều tra tính đúng sai của giá trị số [1].

if 1
  puts "hello"
end

[Kết quả hiển thị]

hello

Như trên, nếu chúng ta để điều kiện là [1], chương trình sẽ không quan tâm [1] là đúng hay sai mà vẫn sẽ thực hiện lệnh bên dưới. Kể cả chúng ta thay một giá trị khác ngoài [1] vào thì điều kiện vẫn đúng. Tại Ruby, [sai] chỉ xảy ra khi là [false] và [nil] (giá trị đặc biệt không biểu thị gì cả). Ngoài giá trị [false] và [nil] thì tất cả mọi giá trị đều đúng.

Tại Ruby thì số 0 cũng trở thành điều kiện đúng.

if 0
  puts "hello"
end

[Kết quả hiển thị]

hello

Ngôn ngữ C hay Java thì [0] là giá trị sai, nhưng tại Ruby thì [0] cũng là giá trị đúng.

! và unless

Nếu sử dụng [!] thì có thể lật ngược lại đúng sai. Với chương trình dưới đây thì chỉ khi [a] không bằng [0] thì lệnh mới được thực hành.

  puts "a không phải bằng 0"
end

Mặt khác, chương trình dưới đây cũng giống vậy.

unless a==0
  puts "a không phải bằng 0"
end

[unless] là ngược của [if], chỉ khi giá trị đằng sau là sai thì bộ phần bên trong [unless~end] mới được thực hiện. Chúng ta cũng có thể sử dụng [else] cùng với [unless]

unless a==0
  puts "a không phải bằng 0"
else
  puts " a bằng 0"
end

Dùng if làm liên từ

Hãy xem chương trình dưới đây.

if a==0
  puts "a bằng 0"
end

Chương trình này chúng ta cũng có thể viết như sau khi dùng [if] làm liên từ.

puts " a bằng 0" if a==0

Bằng cách dùng [if] làm liên từ như thế này làm chúng ta có thể câu lệnh gọn hơn. Và [unless] cũng có thể dùng với hình thức như vậy.

puts " a không phải bằng 0" unless a==0
0