Bài 21-Collections trong Kotlin


Không giống như các ngôn ngữ lập trình khác, Kotlin phân biệt rõ 2 loại Collections(Mutable collections và Immutable collections).

Mô hình lớp kế thừa của các Collection trong Kotlin/java:

Mutable Collections là tập các lớp dùng để lưu trữ danh sách dữ liệu và có thể thay đổi kích thước được

Immutable Collections là tập các lớp dùng để lưu trữ danh sách dữ liệu và không thể thay đổi kích thước được

Cả 2 loại Collections này rất dễ tạo và sử dụng, chỉ khác nhau chút xíu ở mục đích sử dụng của lập trình viên.

Trong giới hạn bài học này Tui chỉ trình bày về MutableListList, các lớp Collection khác các bạn tự tìm hiểu thêm nếu trong dự án có gặp. Tuy nhiên với MutableListList thì theo Tui bạn đã có thể xử lý được hầu hết các trường hợp lưu trữ, tương tác, hiển thị dữ liệu trong phần mềm rồi.

MutableList Là collection có thể thay đổi kích thước dữ liệu: Có thể thêm, sửa, xóa…

List Là collection chỉ có nhiệm vụ readOnly, dùng để hiển thị thông tin. Và dĩ nhiên nó sẽ tối ưu bộ nhớ hơn so với MutableList. Do đó nếu như bạn chỉ muốn hiển thị thông tin thì nên dùng List.

Các collection trong Kotlin không có các Constructor khởi tạo riêng, mà nó thông qua các hàm mutableListOf(), listOf() để khởi tạo

Ví dụ 1 dưới đây mình họa cách khởi tạo 2 collections:


var ds1:MutableList<Int> =mutableListOf()
var ds2:List<Int> = listOf()

Ở trên 2 đối tượng ds1 và ds2 được khởi tạo với danh sách rỗng.

Ta có thể khởi tạo với một số dữ liệu ban đầu,

Ví dụ 2


var ds1:MutableList<Int> =mutableListOf(5,6,1,0,4)
var ds2:List<Int> = listOf(1,2,3,4)

Ở trên ds1 được khởi tạo mặc định với 5 phần tử và ta có thể thay đổi thông tin, kích thước ds1

ds2 được khởi tạo mặc định với 4 phần tử và ta không thể thay đổi thông tin, kích thước ds2. Khi ta dùng List tức là trong đầu ta muốn rằng nó là readOnly, chỉ hiển thị dữ liệu mà thôi.

Dưới đây là một số phương thức thường dùng với MutableList/List:

Tên Thuộc tính/phương thức Mô tả
size Thuộc tính trả về kích thước thực sự của Collection
[i] Indexer cho phép truy suất và thay đổi giá trị tại vị trí i của collection
add() Thêm một phần tử
addAll() Thêm nhiều phần tử
removeAt() Xóa theo vị trí
remove() Xóa theo đối tượng
removeIf{} Xóa theo điều kiện
clear() Xóa toàn bộ danh sách
sort() Sắp xếp tăng dần
sortDescending() Sắp xếp giảm dần
filter {  } Lọc dữ liệu
contains() Kiểm tra Collection có chứa phần tử nào đó hay không

Và còn nhiều các phương thức lợi hại khác, các bạn tự tìm hiểu thêm nhé.

Ví dụ 3 – Thao tác với List:


/**
* Created by cafe on 29/05/2017.
*/
fun main(args: Array<String>) {
var ds:List<Int> = listOf(5,6,1,9,-4,7,8,2)
println("Các phần tử trong List cách 1:")
for(i in ds.indices)
print("${ds[i]}\t")
println()
println("Các phần tử trong List cách 2:")
for(i in ds)
print("$i\t")
println()
println("Các phần tử sắp xếp tăng dần:")
var ds2= ds.sorted()
for(i in ds2)
print("$i\t")
println()
println("Các phần tử sắp xếp giảm dần:")
var ds3= ds.sortedDescending()
for(i in ds3)
print("$i\t")
println()
var ds4=ds.filter { x->x%2==0 }
println("Các phần tử chẵn:")
for(i in ds4)
print("$i\t")
println()
println("SUM="+ds.sum())
println("MAX="+ds.max())
println("MIN="+ds.min())
println("AVERAGE="+ds.average())
}

Kết quả khi chạy ta thấy:

Các phần tử trong List cách 1:
5    6    1    9    -4    7    8    2
Các phần tử trong List cách 2:
5    6    1    9    -4    7    8    2
Các phần tử sắp xếp tăng dần:
-4    1    2    5    6    7    8    9
Các phần tử sắp xếp giảm dần:
9    8    7    6    5    2    1    -4
Các phần tử chẵn:
6    -4    8    2
SUM=34
MAX=9
MIN=-4
AVERAGE=4.25

Ta để ý các phương thức của List đa phần không làm thay đổi nội tại List mà nó trả về một List mới.

Ví dụ 4 – Thao tác với MutableList:


/**
* Created by cafe on 29/05/2017.
*/
fun main(args: Array<String>) {
var ds:MutableList<Int> = mutableListOf()
ds.add(10)//thêm một phần tử có giá trị 10
ds.add(4)//thêm một phần tử có giá trị 4
ds.add(5)//thêm một phần tử có giá trị 5
ds.add(8)//thêm một phần tử có giá trị 8
ds.addAll(mutableListOf(9,0,7))//thêm một danh sách có 3 phần tử: 9,0,7
println("Các phần tử trong MutableList - theo giá trị:")
for(i in ds)
print("$i\t")
println()
println("Các phần tử trong MutableList - theo vị trí:")
for(i in ds.indices)
print("${ds[i]}\t")
println()
ds[2]=113//đổi giá trị phần tử thứ 2 thành 113
println("Các phần tử trong MutableList sau khi đổi:")
for(i in ds.indices)
print("${ds[i]}\t")
println()
ds.removeAt(3)//xóa phần tử tại vị trí thứ 3
println("Các phần tử trong MutableList sau khi xóa:")
for(i in ds.indices)
print("${ds[i]}\t")
println()
ds.sort()//sắp tăng dần
println("Các phần tử trong MutableList sau sắp tăng dần:")
for(i in ds.indices)
print("${ds[i]}\t")
println()
ds.sortDescending()//sắp giảm dần
println("Các phần tử trong MutableList sau sắp giảm dần:")
for(i in ds.indices)
print("${ds[i]}\t")
println()
println("SUM="+ds.sum())
println("MAX="+ds.max())
println("MIN="+ds.min())
println("AVERAGE="+ds.average())
//lọc các số lẻ
var dsLe=ds.filter { x->x%2==1 }
println("Các phần tử trong MutableList là số lẻ:")
for(i in dsLe.indices)
print("${dsLe[i]}\t")
println()
var dsNT=ds.filter {
x->
var dem=0
for(i in 1..x)
{
if(x%i==0)
dem++
}
dem==2
}
println("Các phần tử trong MutableList là số nguyên tố:")
for(i in dsNT.indices)
print("${dsNT[i]}\t")
println()
}

Kết quả khi chạy ta thấy:

Các phần tử trong MutableList – theo giá trị:
10    4    5    8    9    0    7
Các phần tử trong MutableList – theo vị trí:
10    4    5    8    9    0    7
Các phần tử trong MutableList sau khi đổi:
10    4    113    8    9    0    7
Các phần tử trong MutableList sau khi xóa:
10    4    113    9    0    7
Các phần tử trong MutableList sau sắp tăng dần:
0    4    7    9    10    113
Các phần tử trong MutableList sau sắp giảm dần:
113    10    9    7    4    0
SUM=143
MAX=113
MIN=0
AVERAGE=23.833333333333332
Các phần tử trong MutableList là số lẻ:
113    9    7
Các phần tử trong MutableList là số nguyên tố:
113    7

Ta thấy collection trong Kotlin rất linh động và mạnh mẽ, ta có thể tùy biến trong vấn đề xử lý. Hàm filter như là một cuộc cách mạng trong lọc dữ liệu.

Như vậy tới đây Tui đã hướng dẫn xong cách xử 2 Collection quan trọng trong Kotlin, các bạn chú ý học kỹ và hiểu được nó thông qua các ví dụ ở trên nhé. Cần thành thạo các Collection để có thể áp dụng tốt vào các dự án thực tế của mình.

Các bạn có thể tải source code bài này ở đây: http://www.mediafire.com/file/d1b3imc09aw60et/HocXuLyCollection.rar

Hẹn gặp các bạn ở những bài tiếp theo

Chúc các bạn thành công!

Trần Duy Thanh (http://ssoftinc.com/)

Bài 20- Xử lý mảng hai chiều trong Kotlin


bài 19 chúng ta đã thao tác được với mảng 1 chiều. Trong bài này Tui sẽ trình bày về cách thức khai báo và sử dụng mảng 2 chiều của Kotlin.

Cú pháp khai báo mảng 2 chiều tổng quát trong Kotlin:

var M:Array<Kiểu_Dữ_Liệu_Mảng> = Array(Số_Dòng,{Kiểu_Dữ_Liệu_Mảng(Số_Cột)})

Ví dụ dưới đây sẽ khai báo một mảng 2 chiều tên là M có 10 dòng và 5 cột, dữ liệu các phần tử trong M có kiểu Int:

var M:Array<IntArray> = Array(10,{IntArray(5)})

Các chỉ số dòng và cột cũng chạy từ 0->n-1

Bạn có thể tưởng tượng cấu trúc dữ liệu của mảng 2 chiều như sau:

Mảng 2 chiều trong Kotlin cũng có một tập các phương thức vô cùng mạnh mẽ.

Để nhập liệu cho các phần tử trong mảng 2 chiều M ta làm như sau:

var rd:Random = Random()
for(i in M.indices)
{
for(j in M[i].indices)
{
M[i][j]=rd.nextInt(100)
}
}

Ta dùng 2 vòng lặp for duyệt theo vị trí (indices). Vòng lặp ngoài là duyệt theo dòng, vòng lặp trong là duyệt theo cột. Mỗi làn duyệt ta có M[i][j] chính là phần tử ở dòng thứ i và cột thứ j. Ta cập nhật dữ liệu cho phần tử này.

Để xuất dữ liệu ra màn hình ta cũng làm tương tự:

for(i in M.indices)
{
for(j in M[i].indices)
{
print(“${M[i][j]}\t”)
}
println()
}

Ví dụ chi tiết một số chức năng xử lý Mảng 2 chiều trong Kotlin:


import java.util.*

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var M:Array<IntArray> = Array(10,{IntArray(5)})
var rd:Random = Random()
for(i in M.indices)
{
for(j in M[i].indices)
{
M[i][j]=rd.nextInt(100)
}
}
println("Mảng 2 chiều sau khi nhập:")
for(i in M.indices)
{
for(j in M[i].indices)
{
print("${M[i][j]}\t")
}
println()
}
println("Mảng 2 chiều sau khi nhập - cách 2:")

for(row in M)
{
for(cell in row)
{
print("$cell \t")
}
println()
}
println("Mảng thứ 1:")
var M1=M[1]
for (i in M1.indices)
print("${M1[i]}\t")
println()
}

Kết quả khi chạy ta thấy:

Mảng 2 chiều sau khi nhập:
51    9    58    96    46
48    76    11    68    44
11    73    77    18    45
22    10    91    22    35
59    66    48    42    59
84    5    58    0    79
50    68    72    29    64
8    66    69    90    93
35    92    5    8    13
18    48    44    82    52
Mảng 2 chiều sau khi nhập – cách 2:
51     9     58     96     46
48     76     11     68     44
11     73     77     18     45
22     10     91     22     35
59     66     48     42     59
84     5     58     0     79
50     68     72     29     64
8     66     69     90     93
35     92     5     8     13
18     48     44     82     52
Mảng thứ 1:
48    76    11    68    44

Như vậy tới đây Tui đã hướng dẫn xong cách khai báo, nhập, xuất mảng 2 chiều trong Kotlin, các bạn chú ý học kỹ và hiểu được nó thông qua các ví dụ ở trên nhé. Các bạn Cần kiểm tra thêm nhiều phương thức khác trong mảng 2 chiều để có thể áp dụng tốt vào các dự án thực tế của mình.

Các bạn có thể tải source code bài này ở đây:http://www.mediafire.com/file/sxi7swegsgcsz17/HocXuLyMang_2d.rar

Hẹn gặp các bạn ở những bài tiếp theo

Chúc các bạn thành công!

Trần Duy Thanh (http://ssoftinc.com/)

Bài 19- Xử lý mảng một chiều trong Kotlin


Với Kotlin thì Mảng là một kiểu dữ liệu rất mạnh mẽ, nó khắc phục được rất nhiều nhược điểm so với các ngôn ngữ lập trình khác như C++, C#, Java…

bài số 6 Tui đã nói sơ qua một số kiểu dữ liệu là mảng được built-in sẵn trong Kotlin. Để giúp các bạn dễ dàng hiểu được cách khai báo cũng như sử dụng mảng một chiều trong Kotlin thì Tui sẽ dùng IntArray để minh họa trong các ví dụ dưới đây, các kiểu mảng khác các bạn có thể tự suy luận được.

Để khai báo và cấp phát mảng ta làm như sau:

var M:IntArray= IntArray(n)

Với n là số phần tử lưu trữ tối đa của mảng.

M là một mảng lưu trữ tập các kiểu dữ liệu Int (lưu trữ tối đa n phần tử). Ta cũng có thể nói M là một đối tượng có kiểu IntArray. Tương tự như các ngôn ngữ lập trình khác, Mảng cũng lưu chỉ số từ 0, cho phép truy suất các phần tử thông qua chỉ số:

Nhưng các bạn cần chú ý là việc truy suất phần tử chỉ là một chức năng vô cùng nhỏ trong mảng của Kotlin, vì với Mảng trong Kotlin nó rất phong phú các phương thức, nó là một đối tượng được xây dựng với vô vàn phương thức xử lý rất hiệu quả: Tìm min, max, trung bình, tổng, tìm kiếm, sắp xếp…

Tui liệt kê một số thuộc tính và phương thức thường dùng của Mảng (dĩ nhiên còn rất nhiều phương thức khác, khi nào gặp thì các bạn nghiên cứu thêm):

Tên Thuộc tính/phương thức Mô tả
size Thuộc tính trả về kích thước thực sự của mảng
[i] Indexer cho phép truy suất và thay đổi giá trị tại vị trí i của mảng
count/count{} đếm/ đếm có điều kiện
min() hàm trả về số nhỏ nhất trong mảng
max() hàm trả về số lớn nhất trong mảng
sum() hàm trả về tổng mảng
average() hàm trả về trung bình mảng
sort() sắp xếp mảng tăng dần
sortDescending() sắp xếp mảng giảm dần
filter{} Tìm kiếm/lọc danh sách trong mảng
reverse() Đảo mảng
contains() Kiểm tra Mảng có chứa phần tử nào đó hay không

Ví dụ khai báo mảng M có khả năng chứa tối đa 10 phần tử:

var M:IntArray= IntArray(10)

Nhập giá trị cho từng phần tử trong mảng M:

M[0]=100

M[1]=20

M[9]=-5

Vì mảng M có khả năng chứa 10 phần tử nên các Indexer sẽ chạy từ 0 –> 9

Để lấy giá trị tại một vị trí bất kỳ:

var x:Int=M[2]

Để duyệt các phần tử trong mảng ta  có thể duyệt theo vị trí như sau:

for (i in M.indices)
print(“${M[i]}\t”)

hoặc duyệt giá trị theo cách:

for (i in M)
print(“$i\t”)

Các hàm khác trong mảng cũng dễ dàng thực hiện.

Ví dụ chi tiết tạo mảng M có 10 phần tử với các giá trị ngẫu nhiên:


import java.util.*

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var M:IntArray= IntArray(10)

var rd=Random()
for(i in M.indices)
M[i]=rd.nextInt(100)//nhập giá trị là các số ngẫu nhiên [0..99]
println("Mảng sau khi nhập - duyệt theo giá trị:")
for (i in M)
print("$i\t")
println()
println("Mảng sau khi nhập - duyệt theo vị trí:")
for (i in M.indices)
print("${M[i]}\t")
println()
//số lớn nhất
println("MAX=${M.max()}")
//số nhỏ nhất
println("MIN=${M.min()}")
//tổng mảng
println("SUM=${M.sum()}")
//trung bình mảng
println("AVERAGE=${M.average()}")
//đếm số chẵn
println("Số chẵn=${M.count { x->x%2==0 }}")
//đếm số lẻ
println("Số lẻ=${M.count { x->x%2==1 }}")
//sắp xếp tăng dần
M.sort()
println("Tăng dần:")
for (i in M)
print("$i\t")
println()
//sắp xếp giảm dần
M.sortDescending()
println("Giảm dần:")
for (i in M)
print("$i\t")
println()
//lọc các số chẵn trong mảng
var dsChan= M.filter { x->x%2==0 }
println("Các số chẵn:")
for (i in dsChan)
print("$i\t")
println()
//lọc các số lẻ trong mảng
var dsLe= M.filter { x->x%2==1 }
println("Các số Lẻ:")
for (i in dsLe)
print("$i\t")
println()
var k=50
//lọc các số >50 trong mảng
var dsTim=M.filter { x->x>k }
println("Các số > $k:")
for (i in dsTim)
print("$i\t")
println()
}

Kết quả khi chạy ta thấy:

Mảng sau khi nhập – duyệt theo giá trị:
47    50    51    71    63    96    65    91    1    90
Mảng sau khi nhập – duyệt theo vị trí:
47    50    51    71    63    96    65    91    1    90
MAX=96
MIN=1
SUM=625
AVERAGE=62.5
Số chẵn=3
Số lẻ=7
Tăng dần:
1    47    50    51    63    65    71    90    91    96
Giảm dần:
96    91    90    71    65    63    51    50    47    1
Các số chẵn:
96    90    50
Các số Lẻ:
91    71    65    63    51    47    1
Các số > 50:
96    91    90    71    65    63    51

Như vậy tới đây Tui đã hướng dẫn xong cách xử mảng 1 chiều trong Kotlin, các bạn chú ý học kỹ và hiểu được nó thông qua các ví dụ ở trên nhé. Cần thành thạo các thư viện để có thể áp dụng tốt vào các dự án thực tế của mình.

Bài sau Tui sẽ trình bày về mảng 2 chiều trong Kotlin

Các bạn có thể tải source code bài này ở đây: http://www.mediafire.com/file/yha9wwfu1879ac4/HocXuLyMang_1d.rar

Hẹn gặp các bạn ở những bài tiếp theo

Chúc các bạn thành công!

Trần Duy Thanh (http://ssoftinc.com/)

Bài 18- Xử lý chuỗi trong Kotlin


Trong tất cả các ngôn ngữ lập trình thì Xử lý chuỗi vô cùng quan trọng, hầu như các dự án ta đều phải liên quan tới xử lý chuỗi.

Toàn bộ thông tin chi tiết về chuỗi trong Kotlin được trình bày tại đây https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/, các bạn có thời gian thì vào đó xem. Trong bài học này Tui sẽ trình bày một số hàm thường dùng nhất trong chuỗi.

Để khai báo chuỗi trong Kotlin ta dùng:

var s:String=”Obama”

hoặc

var s:String?=”Putin”

Một chuỗi trong Kotlin sẽ có các thuộc tính và phương thức sau(rất rất nhiều phương thức hữu ích, nhưng Tui chỉ có thể liệt kê một số mà thôi):

Tên Thuộc tính/

phương thức

Mô tả
length thuộc tính trả về chiều dài của chuỗi
indexOf(chuỗi) Trả về vị trí đầu tiên tìm thấy, không tìm thấy trả về -1
lastIndexOf(chuỗi) lastIndexOf trả về vị trí cuối cùng tìm thấy
contains(chuỗi con) Contains Kiểm tra chuỗi con có nằm trong chuỗi s?
subString(vt) Trích lọc toàn bộ bên phải chuỗi từ vt
subString(startIndex,endIndex) Trích lọc giữa chuỗi nằm giữa start tới end index
replace(chuỗi cũ, chuỗi mới) Đổi toàn bộ chuỗi cũ thành chuỗi mới
replaceFirst(chuỗi cũ, chuỗi mới) Đổi chuỗi cũ thành chuỗi mới nhưng chỉ áp dụng cho chuỗi cũ đầu tiên
trimStart xóa khoảng trắng dư thừa bên trái
trimEnd xóa khoảng trắng dư thừa bên phải
trim xóa khoảng trắng dư thừa bên trái và phải
compareTo(chuỗi s2)
So sánh 2 chuỗi có phân biệt chữ HOA và chữ thường

=0 khi s1=s2

>0 khi s1>s2

<0 khi s1<s2

compareTo(s2, ignoreCase = true) So sánh 2 chuỗi KHÔNG phân biệt chữ HOA và chữ thường

=0 khi s1=s2

>0 khi s1>s2

<0 khi s1<s2

 plus(chuỗi x)  Nối chuỗi x vào chuỗi gốc
 split(chuỗi tách)  Tách chuỗi gốc thành List<String>
 toUpperCase  Chuyển chuỗi thành IN HOA
 toLowerCase  Chuyển chuỗi thàh in thường

Bây giờ Tui đi vào từng hàm để các bạn dễ dàng thực hành về xử lý chuỗi:

  • Hàm IndexOf – trả về vị trí đầu tiên tìm thấy, nếu không thấy trả về -1:

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var s:String="Obama"
var i = 0
// Trả về i = 2
i = s.indexOf("a")
println(i)
}

Ta thấy rõ ràng ký tự/chuỗi a xuất hiện 2 lần, nhưng Kotlin chỉ quan tâm kết quả đầu tiên mà thôi, vì vậy kết quả =2 sẽ được xuất ra màn hình (vị trí bắt đầu tính từ 0).

  • lastIndexOf trả về vị trí cuối cùng tìm thấy, nếu không thấy trả về -1:

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var s: String = "Hello everybody !";
var i = 0;
// Trả về i = 8
i = s.lastIndexOf("e");
println(i)
}

Ta thấy kết quả xuất ra =8 là vị trí cuối cùng của ký tự/chuỗi e

  • Contains kiểm tra chuỗi con có tồn tại trong chuỗi gốc hay không, có thì trả về true, còn không trả về false

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var s :String  = "Hello everybody !"
var s2="body"
if(s.contains(s2))
{
println("Có tồn tại [$s2]")
}
else
{
println("Ko tồn tại [$s2]")
}
}

Kết quả chạy ta thấy xuất “Có tồn tại [body]”. Hàm contains được sử dụng rất nhiều để kiểm tra sự tồn tại của chuỗi con.

  • subString – trích lọc chuỗi

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
val s = "Xin chào Obama! Tui là Putin"
val s2 = s.substring(9)
println(s2)
val s3 = s.substring(9, 14)
println(s3)
}

Kết quả khi chạy ta thấy:

Obama! Tui là Putin
Obama

Muốn trích lọc bên phải chuỗi thì dùng substring với 1 đối số, muốn trích lọc giữa chuỗi thì dùng 2 đối số.

  • replace – đổi chuỗi cũ thành chuỗi mới

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var s = "Xin chào Obama! Tui là Putin"
s = s.replace("Obama", "Kim Jong Un")
println(s)
}

Kết quả khi chạy ta thấy:

Xin chào Kim Jong Un! Tui là Putin
  • replaceFirst-Đổi chuỗi cũ thành chuỗi mới nhưng chỉ áp dụng cho chuỗi đầu tiên tìm thấy

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var s = "Obama Xin chào Michelle Obama"
s = s.replaceFirst("Obama", "Putin")
println(s)
}

Kết quả khi chạy ta thấy:

Putin Xin chào Michelle Obama

Mặc dù chuỗi gốc ta có 2 chuỗi con Obama, nhưng chương trình chỉ áp dụng cho Obama đầu tiên

  • Các hàm xóa khoảng trắng: trim,trimEnd,trimStart

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var s:String= "    Trần Duy Thanh      "
val s2=s.trimStart()
println(s2+"=>size="+s2.length)
val s3=s.trimEnd()
println(s3+"=>size="+s3.length)
val s4=s.trim()
println(s4+"=>size="+s4.length)

}

Kết quả khi chạy ta thấy:

Trần Duy Thanh      =>size=20
Trần Duy Thanh=>size=18
Trần Duy Thanh=>size=14
  • compareTo – so sánh chuỗi

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
val s1 = "Hạnh phúc"
val s2 = "Hạnh PHÚC"
val x = s1.compareTo(s2, ignoreCase = true)
println(x)
val y = s1.compareTo(s2, ignoreCase = false)
println(y)
}/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
val s1 = "Hạnh phúc"
val s2 = "Hạnh PHÚC"
val x = s1.compareTo(s2, ignoreCase = true)
println(x)
val y = s1.compareTo(s2, ignoreCase = false)
println(y)
}

Kết quả khi chạy ta thấy:

0
32

Ta thấy nếu so sánh không phân biệt chữ Hoa – thường(ignoreCase = true) thì kết quả =0, còn có phân biệt chữ HOA – thường(ignoreCase = false) thì kết quả >1 (32)

  • plus– nối chuỗi

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var s:String="Obama"
s=s.plus(" ")
s=s.plus("Putin")
println(s)
}

Kết quả khi chạy ta thấy:

Obama Putin

Hàm plus ở trên nối chuỗi nhưng nó không làm thay đổi chuỗi gốc mà nó trả về 1 chuỗi mới do đó ta phải lưu lại địa chỉ mới này. Ta có thể dùng dấu + (nhưng không nên dùng khi nối chuỗi quá nhiều đặc biệt đọc từ file hay internet), Ngoài ra có thể dùng StringBuilder để xử lý nối chuỗi.

  • split– tách chuỗi theo tiêu chí bất kỳ, trả về một List<String>

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var s:String="Trần Duy Thanh"
var arr:List<String> = s.split(" ")
println("Số phần tử="+arr.size)
for(x in arr)
println(x)
}

Kết quả khi chạy ta thấy:

Số phần tử=3
Trần
Duy
Thanh

Hàm tách chuỗi rất quan trọng, vì hầu như ta đều gặp trong quá trình viết phần mềm. Input là 1 chuỗi có quy luật, và ta phải phân tích để tách chuỗi rồi mô hình hóa thành dữ liệu có cấu trúc(thường là OOP)

  • toUpperCase, toLowerCase để chuyển CHỮ HOA, chữ thường

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var s:String="Trần Duy Thanh"
var s2=s.toUpperCase()
println(s2)
var s3=s.toLowerCase()
println(s3)
}

Kết quả khi chạy ta thấy:

TRẦN DUY THANH
trần duy thanh

Bây giờ Tui thử làm một chương trình tối ưu chuỗi:

Cho một chuỗi bất kỳ, hãy tối ưu chuỗi theo mô tả: Chuỗi không có khoảng trắng dư thừa, các từ cách nhau bởi 1 khoảng trắng, ký tự đầu của các từ viết HOA

Ví dụ:

Input: “  TRẦN       duY       THAnh  ”

Output: “Trần Duy Thanh”


/**
* Created by cafe on 28/05/2017.
*/
fun toiUU(s: String): String {
var sToiTuu = s
sToiTuu = sToiTuu.trim()
val arrWord = sToiTuu.split(" ");
sToiTuu = ""
for (word in arrWord) {
var newWord = word.toLowerCase()
if (newWord.length > 0) {
newWord = newWord.replaceFirst((newWord[0] + ""), (newWord[0] + "").toUpperCase())
sToiTuu += newWord + " "
}
}
return sToiTuu.trim()
}
fun main(args: Array<String>) {
var s = "   TRẦN         dUY     THanh   "
println(s)
var sToiUuu = toiUU(s)
println(sToiUuu)

s = "     NguyễN      VĂN  OBAMA   "
println(s)
sToiUuu = toiUU(s)
println(sToiUuu)
}

Kết quả khi chạy ta thấy:

   TRẦN         dUY     THanh
Trần Duy Thanh
NguyễN      VĂN  OBAMA
Nguyễn Văn Obama

Như vậy tới đây Tui đã hướng dẫn xong cách xử lý chuỗi trong Kotlin, các bạn chú ý học kỹ và hiểu được nó thông qua các ví dụ ở trên nhé. Cần thành thạo các thư viện để có thể áp dụng tốt vào các dự án thực tế của mình.

Cần phải đọc nhiều ví dụ về cách xử lý chuỗi từ Kotlin, vì trong bài này Tui mới liệt kê được một số phương thức thường dùng mà thôi, nó còn vô vàn các phương thức khác rất hữu ích

Các bạn có thể tải source code bài này ở đây: http://www.mediafire.com/file/v62acsqhh101jp8/XuLyChuoi.rar

Hẹn gặp các bạn ở những bài tiếp theo

Chúc các bạn thành công!

Trần Duy Thanh (http://ssoftinc.com/)

Bài 17-Các thư viện quan trọng thường dùng trong Kotlin


Ngôn ngữ nào cũng có tập các thư viện giúp ta giải quyết nhanh những công việc nào đó, và chắc chắn chúng ta phải sử dụng vì ta không thể tự viết ra được, ta phải biết cách sử dụng nó. Các thư viện này có thể nằm trong JVM hay KotlinJavaRuntime hay ở bất kỳ thư viện ngoài nào khác:

Trong bài này Tui sẽ trình bày một số thư viện thường dùng như:

  • Thư viện xử lý dữ liệu số
  • Thư viện xử lý ngày tháng
  • Thư viện xử lý toán học
  • Thư viện xử lý số ngẫu nhiên
  • Thư viện xử lý chuỗi

Và còn rất nhiều thư viện xử lý khác nữa, khi nào gặp ta lại ngâm cứu tiếp

Các thư viện này có thể được sử dụng từ JVM, Bây giờ Tui đi vào chi tiết từng thư viện xử lý

  • Thư viện xử lý dữ liệu số

Muốn định dạng chữ số thập phân cho số thực ta có thể dùng format sau:


fun main(args: Array<String>) {
var d:Double=10.0/3.0
println(d)
println("%.2f".format(d))
}

Kết quả xuất ra màn hình khi chưa định dạng và đã định dạng thập phân:

3.3333333333333335
3.33

“%.2f” là cú pháp định số thập phân, ở trong Tui để số 2 tức là 2 số thập phân, bạn muốn bao nhiêu số thì tự thay thế.

Ta có thể sử dụng thư viện DecimalFormat nằm trong JVM để định dạng số, ví dụ dưới đây minh họa tạo ngăn cách phần nghìn:


import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.Locale

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var x:Int=986553823
var dcf=DecimalFormat("#,###")
var dcfs=DecimalFormatSymbols(Locale.getDefault())
dcfs.groupingSeparator=','
dcf.decimalFormatSymbols=dcfs
println(x)
println(dcf.format(x))
}

Kết quả khi chạy chương trình:

986553823
986,553,823

Chú ý những dòng lệnh import ở trên là IntelliJ IDEA tự import giùm, ta chỉ cần gõ Control +Space khi dùng các thư viện thì tự động nó xuất hiện. Kotlin giúp ta triệu gọi thư viện trong JVM một cách dễ dàng nhất giúp các lập trình viên Java dễ chuyển đổi ngôn ngữ

  • Thư viện xử lý ngày tháng

Khi xử lý ngày tháng năm ta thường dùng 3 thư viện:

Date
Calendar
SimpleDateFormat

Các thư viện này nằm trong gói:

import java.util.Date
import java.util.Calendar
import java.text.SimpleDateFormat

  • Lấy ngày tháng năm hiện tại:

var cal=Calendar.getInstance()

  • Lấy từng tiêu chí

var year=cal.get(Calendar.YEAR)

var month=cal.get(Calendar.MONTH)

var day=cal.get(Calendar.DAY_OF_MONTH)

  • Thay đổi thông số ngày tháng năm:

cal.set(Calendar.YEAR, 1990);

cal.set(Calendar.MONTH,2)

cal.set(Calendar.DAY_OF_MONTH,20)

  • Lấy đối tượng ngày tháng năm:

var date=cal.time

  • Để định dạng ngày tháng năm dd/MM/YYYY

var date=cal.time
var sdf=SimpleDateFormat(“dd/MM/yyyy”);
println(sdf.format(date))

Ví dụ:


import java.util.Date
import java.util.Calendar
import java.text.SimpleDateFormat

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
var cal=Calendar.getInstance()
var year=cal.get(Calendar.YEAR)
var month=cal.get(Calendar.MONTH)
var day=cal.get(Calendar.DAY_OF_MONTH)
println("Năm=$year")
println("Tháng=$month")
println("Ngày=$day")

var date=cal.time
var sdf=SimpleDateFormat("dd/MM/yyyy");
println(sdf.format(date))
var sdf2=SimpleDateFormat("dd/MM/yyyy hh:mm:ss aaa");
println(sdf2.format(date))
}

Kết quả khi chạy chương trình:

Năm=2017
Tháng=4
Ngày=28
28/05/2017
28/05/2017 07:26:33 AM

Chú ý tháng luôn chạy từ 0->11 nên khi ra số 4 chính là tháng 5 (ta có thể xem SimpleDateFormat xuất ra đúng tháng) .

hh:mm:ss aaa là định dạng giờ:phút:giây, aaa là AM hoặc PM . Muốn định dạng 24h thì thay hh thành HH

  • Thư viện xử lý toán học

Để xử lý toán học ta dùng thư viện Math nằm trong gói java.lang

Một số phương thức thường dùng của Math:

Tên phương thức Mô tả
PI Trả về giá trị PI
abs(a) Trả về trị tuyệt đối của a
max(a,b) Trả về giá trị lớn nhất giữa a và b
min(a,b) Trả về giá trị nhỏ nhất giữa a và b
sqrt(a) Trả về căn bậc 2 của a
pow(x,y) Tính lũy thừa xy
sin(radian) Tính sin, radian=Math.PI*góc/180
cos(radian) Tính cos
tan(radian) Tính tan

Ví dụ:


/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {
println("Số PI="+Math.PI)
println("Giá trị tuyệt đối của -4="+Math.abs(-4))
println("số "+Math.max(9,2)+" là số lớn")
println("Căn bậc 2 của 25="+Math.sqrt(25.0))
println("3 mũ 4 ="+Math.pow(3.0,4.0))
var goc=45
var rad=Math.PI*goc/180
println("sin($goc)="+Math.sin(rad))
println("cos($goc)="+Math.cos(rad))
println("tan($goc)="+Math.tan(rad))
println("cotan($goc)="+Math.cos(rad)/Math.sin(rad))
}

Kết quả khi chạy chương trình:

Số PI=3.141592653589793
Giá trị tuyệt đối của -4=4
số 9 là số lớn
Căn bậc 2 của 25=5.0
3 mũ 4 =81.0
sin(45)=0.7071067811865475
cos(45)=0.7071067811865476
tan(45)=0.9999999999999999
cotan(45)=1.0000000000000002
  • Thư viện xử lý số ngẫu nhiên

Để xử lý số ngẫu nhiên ta dùng lớp Random nằm trong gói import java.util.Random

var rd=Random()

var x=rd.nextInt(n);

Trả về số ngẫu nhiên từ [0…n-1]

Ví dụ:

[0….100]=>rd.nextInt(101)

[-100 …100]=>-100+rd.nextInt(201)

[-100 … -50]=>-100+rd.nextInt(51)

rd.nextDouble() trả về số ngẫu nhiên [0…1)

Ví dụ viết Game đoán số theo mô tả:

Máy tính sẽ ra 1 số ngẫu nhiên [0..100], yêu cầu người chơi đoán số này, cho phép đoán sai 7 lần (quá 7 lần thì Game Over). Nếu đoán sai thì phải cho người chơi biết là số Người chơi đoán nhỏ hơn hay lớn hơn số của máy.

=>Sau khi kết thúc game (WIN or LOST)=>hỏi xem Người chơi có muốn chơi nữa không.

import java.util.Random

/**
* Created by cafe on 28/05/2017.
*/
fun main(args: Array<String>) {

while (true) {
choi()
println("Chơi nữa không thím?(c/k):")
val tl = readLine()
if (tl.equals("k", ignoreCase = true))
break
}
println("Tạm biệt Thím!")

}
fun choi()
{
val rd = Random()
val soMay = rd.nextInt(101)
println("Máy đã ra 1 số [0...100] mời Thím đoán!")
var soNguoi: Int=0
var soLanDoan = 0
do {
println("Bạn đoán số gì?:")
var s=readLine()
if(s!=null)
soNguoi = s.toInt()
soLanDoan++
println("Thím đoán lần thứ " + soLanDoan)
if (soNguoi == soMay) {
println("Chúc mừng Thím! Thím đoán đúng, số máy =" + soMay)
break
}
if (soNguoi < soMay) { println("Thím đoán sai! số máy > số thím")
} else {
println("Thím đoán sai! số máy <số thím")
}
if (soLanDoan == 7) {
println("Thím đã Cáo Phó, vì đoán 7 lần mà ko trúng!")
break
}
} while (soLanDoan <= 7)
}

Kết quả khi chạy chương trình:

Máy đã ra 1 số [0…100] mời Thím đoán!
Bạn đoán số gì?:
50
Thím đoán lần thứ 1
Thím đoán sai! số máy > số thím
Bạn đoán số gì?:
75
Thím đoán lần thứ 2
Thím đoán sai! số máy <số thím
Bạn đoán số gì?:
62
Thím đoán lần thứ 3
Chúc mừng Thím! Thím đoán đúng, số máy =62
Chơi nữa không thím?(c/k):
k
Tạm biệt Thím!
  • Thư viện xử lý Chuỗi

Ta thường sử dụng lớp StringBuilder (nằm trong kotlin.text) để xử lý chuỗi

  • StringBuilder(): Mặc định tạo ra một đối tượng StringBuilder có thể lưu giữ được 16 ký tự
  • StringBuilder(int capacity): Tạo ra một đối tượng StringBuilder có thể lưu giữ được capacity ký tự
  • StringBuilder(String s): Tạo một đối tượng StringBuilder lấy thông tin từ chuỗi s

Các phương thức thường sử dụng:

  • append() – nối chuỗi
  • insert() – chèn chuỗi
  • delete() – xóa chuỗi
  • reverse() – đảo ngược chuỗi

Ví dụ:


fun main(args: Array<String>) {
var sb= StringBuilder("Obama Putin")
println(sb.toString())
sb.insert(5,"Kim Jong Un")
println(sb.toString())
sb.append(" Donald Trump")
println(sb.toString())
sb.reverse()
println(sb.toString())
}

Kết quả khi chạy chương trình:

Obama Putin
ObamaKim Jong Un Putin
ObamaKim Jong Un Putin Donald Trump
pmurT dlanoD nituP nU gnoJ miKamabO

Đặc biệt khi nối chuỗi như đọc từ File, đọc từ internet với nội dung dài thì ta nên dùng StringBuilder để nối (append) thay vì dùng dấu +. Vì khi dùng dấu + tốc độ xử lý sẽ rất chậm.

Như vậy tới đây Tui đã hướng dẫn xong một số thư viện quan trọng thường dùng trong Kotlin, các bạn chú ý học kỹ và hiểu được nó thông qua các ví dụ ở trên nhé. Cần thành thạo các thư viện để có thể áp dụng tốt vào các dự án thực tế của mình.

Các bạn có thể tải source code bài này ở đây: http://www.mediafire.com/file/hkqhv8emwnrep4v/HocThuVienThuongDung.rar

Hẹn gặp các bạn ở những bài tiếp theo

Chúc các bạn thành công!

Trần Duy Thanh (http://ssoftinc.com/)

Bài 16-Cách gỡ lỗi Kotlin bằng công cụ Debug


bài 15 Tui đã trình bày cách xử lý biệt lệ để kiểm soát lỗi phát sinh trong quá trình runtime. Tuy nhiên để lần vết tường tận từng bước chương trình thực hiện để tìm ra các lỗi khó như lỗi Logic thì bắt buộc ta phải sử dụng công cụ Debug, phần mềm IntelliJ IDEA đã tích hợp sẵn công cụ Debug giúp chúng ta dễ dàng lần vết.

Theo kinh nghiệm của Tui thì thời gian viết mã lệnh mới chiếm khoảng 40% còn 60% thời gian còn lại là chúng ta phải lần vết sửa lỗi (nói cho sang miệng thì giới lập trình viên gọi bằng cụm từ Fix Bug). Dĩ nhiên con số này chỉ là cảm tính của Tui thôi, nó không phải là 1 con số chính xác cho từng lập trình viên. Nhưng Tui cam đoan rằng thời gian Fix Bug phải luôn luôn > thời gian viết code mới.

Với một công cụ Debug bất kỳ thì ta thường có 3 thao tác chính:

  1. Cách đặt break point
  2. Cách debug từng dòng
  3. Cách xem giá trị của biến trong khi debug

Bây giờ Tui sẽ hướng dẫn chi tiết từng thao tác trong công cụ IntelliJ IDEA để  bạn Debug nhé, giả sử Tui có đoạn lệnh giải phương trình bậc 2 dưới đây (Tui đang chủ ý làm sai Logic), nhiệm vụ của ta là tìm ra các lỗi sai Logic này bằng công cụ Debug:


fun NhapGiaTri():Double
{
var s:String?= readLine()
if(s!=null)
return s.toDouble()
return 0.0
}
fun main(args: Array<String>) {
var a:Double=0.0
var b:Double=0.0
var c:Double=0.0
println("Nhập a:")
a=NhapGiaTri()
println("Nhập b:")
b=NhapGiaTri()
println("Nhập c:")
c=NhapGiaTri()
if(a==0.0)
{
if(b==0.0 && c==0.0)
println("PT Vô số No")
else if(b==0.0 && c!=0.0)
println("PT Vô No")
else
println("X="+(-b/c))
}
else
{
val delta:Double=Math.pow(b,2.0)-4*a*c
if(delta<0)
println("Vô nghiệm")
else if(delta==0.0)
{
var x:Double=-b/(2*a)
println("No kép x1=x2=$x")
}
else
{
var x1:Double=(b-Math.sqrt(delta))/(2*a)
var x2:Double=(b+Math.sqrt(delta))/(2*a)
println("x1=$x1")
println("x2=$x2")
}
}
}

Nhìn lệnh trên bạn phát hiện ra sai Logic chỗ nào?

Tui đưa ra 2 trường hợp để Test xuất hiện lỗi Logic bên trên như sau:

1.Trường hợp 1:  0x^2+5x+2=0

Nếu đúng thì kết quả phải là x=-0.4, nhưng khi chạy lên kết quả lại là x=-2.5 đây chính là lỗi sai Logic đầu tiên

2.Trường hợp 2: x^2+5x-6 =0

Nếu đúng thì kết quả sẽ là: x1=-6, x2= 1. Nhưng kết quả ở trên lại ra x1=-1.0, x2=6.0 đây chính là lỗi sai Logic thứ 2

Vậy làm sao sửa cho đúng? thường ta phải Debug vào từng dòng để kiểm tra (dĩ nhiên khi làm thực tế thì chả bao giờ gặp những giải thuật tầm thường như thế này, đây là Tui lấy ví dụ cụ thể bài giải phương trình bậc 2 để hướng dẫn các bạn cách thức Debug và cũng chỉ rõ luôn 2 chỗ sai Logic) .

Bây giờ ta đi vào chi tiết:

Bước 1: Muốn dừng lại kiểm tra lệnh ở dòng nào thì tạo break point ở dòng đó (bước này gọi là đặt Break Point):

Ví dụ bạn muốn đặt Break Point ở dòng lệnh 25 và dòng lệnh 39 thì lần lượt bấm chuột vào kế bên số dòng chỗ mũi tên màu đỏ Tui trỏ tới đó, nó sẽ xuất hiện Núm tròn màu đó, muốn bỏ nó thì Bấm lại lần nữa:

Khi dòng nào có Núm tròn đỏ xuất hiện thì chính là Break Point được đặt thành công.

Bước 2: Chạy Debug từng dòng

Ta vào menu Run/ chọn Debug App_debug.kt (là tập tin mà ta viết lệnh main muốn Debug)

Chương trình sẽ thực thi và ta nhập các giá trị cho các biến:

Ở trên ta thử nhập a=0, b=5 và c=2 ==> lúc này chương trình sẽ tự động xuất hiện Tab Debugger kế bên Tab Console và di chuyển con trỏ lệnh tới dòng 25 mà ta đã đặt Break Point:

Ở màn hình trên ta có thể thấy được giá trị của các biến ngay dòng debug.

Và công cụ ở chế độ Debug cho phép ta dùng các phím F7, F8, F9 để điều hướng quá trình Debug:

F7 là đi vào bên trong phương thức được triệu gọi, F8 là vượt qua phương thức triệu gọi, F9 là quay trở về chế độ bình thường. Và còn nhiều các phím tắt khác các bạn có thể test.

Bước 3: Cách xem giá trị của biến trong khi debug

Để xem thêm các giá trị của các Biến trong quá trình Debug, IntelliJ IDEA còn cung cấp chức năng Add to Watches (bôi đen biến bất kỳ -> bấm chuột phải –>chọn Add to Watches):

Sau khi chọn Add to Watches –> biến này sẽ được xuất hiện trong màn hình Variables:

Ta nhấn F8 để chạy tiếp thì thấy kết quả:

Dĩ nhiên vì lỗi Logic Tui nói trước nên tới đây ta cũng biết kết quả nó sai, và cần sửa lại lệnh cho đúng (thực tế nó khó hơn nhiều, có khi bạn phải F7 F8 cả ngày chưa chắc tìm ra nó lỗi chỗ nào mà sửa)

Tương tự như vậy bạn Test trường hợp thứ 2 là có 2 nghiệm phân biệt bị sai

Như vậy tới đây Tui đã hướng dẫn xong cách gỡ lỗi Kotlin bằng công cụ Debug, các bạn chú ý học kỹ và hiểu được nó thông qua các ví dụ ở trên nhé. Cần thành thạo công cụ Debug, các phím duyệt debug cũng như add to Watches để có thể áp dụng tốt vào các dự án thực tế của mình.

Các bạn có thể tải source code sai logic bài này ở đây: http://www.mediafire.com/file/zo2t52p0qorz1dz/HocDebug.rar

Hẹn gặp các bạn ở những bài tiếp theo

Chúc các bạn thành công!

Trần Duy Thanh (http://ssoftinc.com/)

Bài 15-Xử lý biệt lệ trong Kotlin


Tại sao phải xử lý biệt lệ?

Trong quá trình thực thi phần mềm sẽ có những lỗi phát sinh mà trong quá trình coding ta đã dự đoán hoặc chưa dự đoán được

Việc kiểm soát các biệt lệ giúp cho phần mềm tiếp tục hoạt động nếu lỗi xảy ra hoặc cũng đưa ra các gợi ý bên phía User Problem

Khi lập trình thường chúng ta gặp 3 cấp độ lỗi:

  • Lỗi biên dịch (mới học lập trình, viết đâu sai đó… rất đáng thương)
  • Lỗi runtime exception (học lập trình chưa thông, chạy lên báo lỗi om sòm)
  • Lỗi logic exception – sai nghiệp vụ yêu cầu (đã thành lập trình viên, gặp những lỗi khó sửa)

Và khi gặp lỗi thì thường có 2 hành vi với lỗi: Không quan tâm (Unchecked error) và quan tâm(Checked error)

Để hướng tới lập trình viên chuyên nghiệp thì ta cần quan tâm tới những lỗi này, phải kiểm tra cẩn thận để khi có gặp lỗi xảy ra thì chương trình vẫn tiếp tục mà không bị tắt ngang.

Kotlin hỗ trợ chúng ta cú pháp tổng quát để xử lý biệt lệ như sau:

try {

// viết lệnh ở đây và các lệnh này có khả năng sinh ra lỗi

}

catch (e: SomeException) {

// handler lỗi ở đây -> thông báo lỗi chi tiết để biết mà sửa cái gì

}

finally {

// optional finally block – cho dù có lỗi hay không có lỗi xảy ra thì block luôn luôn thực hiện

}

Ví dụ 1: Viết chương trình chia 2 số a và b. Chủ ý cho mẫu số =0 để sinh ra lỗi


fun main(args: Array<String>) {
try {
var a:Int=5
var b:Int=0;
var c=a/b
println("$a/$b=$c")
}
catch (e:Exception)
{
println(e.message)
}
finally {
println("Đây là finally, 100% chạy, cho dù lỗi hay không")
}
}

Khi chạy đoạn lệnh ở trên thì đến dòng a/b sẽ sinh ra lỗi và nó nhảy vào exception, sau đó finally sẽ được thực hiện:

/ by zero
Đây là finally, 100% chạy, cho dù lỗi hay không

Ngoài ra Kotlin cũng hỗ trợ từ khóa throws để ném lỗi này ra nơi khác, những chỗ nào gọi nó sẽ xử lý lỗi này.

Ví dụ 2:


fun chia(a:Int,b:Int):Int
{
if(b==0)
throw Exception("Mẫu số =0")
return a/b
}
fun main(args: Array<String>) {
chia(5,0)
println("Cám ơn!")
}

Khi chạy chương trình ở ví dụ 2 lên thì nó sẽ xuất ra thông báo lỗi: Mẫu số =0 và tắt ngang phần mềm, không cho dòng chữ “Cám ơn”có cơ hội xuất hiện. VÌ lúc này ta chưa dùng try..catch để checked error:

Exception in thread “main” java.lang.Exception: Mẫu số =0
at App_bietle_throwsKt.chia(app_bietle_throws.kt:7)
at App_bietle_throwsKt.main(app_bietle_throws.kt:11)

Ta sửa lại mã lệnh ở trên để khi có lỗi xảy ra thì chương trình vẫn tiếp tục hoạt động:

Ví dụ 3:


fun chia(a:Int,b:Int):Int
{
if(b==0)
throw Exception("Mẫu số =0")
return a/b
}
fun main(args: Array<String>) {
try {
chia(5, 0)
}
catch (e:Exception)
{
println(e.message)
}
println("Cám ơn!")
}

Khi có try .. catch thì cho dù có lỗi xảy ra, chương trình vẫn tiếp tục thực hiện các lệnh còn lại (tránh tắt ngang phần mềm), chương trình trên khi chạy sẽ có kết quả:

Mẫu số =0
Cám ơn!

Như vậy tới đây Tui đã hướng dẫn xong xử lý biệt lệ trong Kotlin, các bạn chú ý học kỹ và hiểu được nó thông qua các ví dụ ở trên nhé. Đặc biệt nắm được cách thức vận hành của try..catch..finally…throw để có thể áp dụng tốt vào các dự án thực tế của mình.

Các bạn có thể tải source code bài này ở đây: http://www.mediafire.com/file/ko46c0s2d476669/HocXuLyBietLe.rar

Hẹn gặp các bạn ở những bài tiếp theo

Chúc các bạn thành công!

Trần Duy Thanh (http://ssoftinc.com/)

Bài 14-Vòng lặp do while trong Kotlin


bài 13 chúng ta đã hiểu được cấu trúc lặp while, trong bài này chúng ta qua một cấu trúc tương tự đó là do…while

Cú pháp vòng lặp do…while:

do

  statement

}

while(expression)

Các bước thực hiện:

−B1:Statement được thực hiện

−B2:Expression được định trị.

−Nếu expression là true thì quay lại bước 1

−Nếu expression là false thì thoát khỏi vòng lặp.

Để thoát vòng lặp: dùng break

Để di chuyển sớm qua lần lặp tiếp theo : dùng continue

Lưu ý: Lệnh trong do…while chắc chắn được thực hiện ít nhất một lần.

Lưu đồ hoạt động:

Ví dụ 1: Viết chương trình tính 5 giai thừa


fun main(args: Array<String>) {
var n:Int = 5
var gt:Int=1
var i:Int = 1
do
{
gt *= i
i++
}while (i<=n)
println("$n! =$gt")
}

Giải thích chi tiết quá trình chạy:

Khởi tạo: n=5; gt=1, i=1

Lần 1: gt=gt*i=1*1=1

i++=> i=i+1=1+1=2

Kiểm tra i<=n <=>2<=5=>đúng

Lần 2: gt=gt*i=1*2=2

i++=>i=i+1=2+1=3

Kiểm tra i<=n <=> 3<=5=>đúng

Lần 3: gt=gt*i=2*3=6

i++=>i=i+1=3+1=4

Kiểm tra i<=n <=> 4<=5=>đúng

Lần 4: gt=gt*i=6*4=24

i++=>i=i+1=4+1=5

Kiểm tra i<=n <=> 5<=5=>đúng

Lần 5: gt=gt*i=24*5=120

i++=>i=i+1=5+1=6

Kiểm tra i<=n <=> 6<=5=>sai=>ngừng do while

Kết thúc chương trình ta được giai thừa =120

Tương tự như các vòng lặp khác, do..while cũng có thể kết hợp lồng ghép các vòng lặp với nhau:

Ví dụ 2: Viết chương trình kiểm tra 1 năm bất kỳ có phải năm nhuần hay không (Năm nhuần là năm chia hết cho 4 nhưng không chia hết cho 100 hoặc chia hết cho 400). Chương trình bắt buộc phải nhập năm >=0, nếu nhập sai bắt nhập lại cho tới khi nào nhập đúng, kết thúc chương trình cho phép người dùng lựa chọn tiếp tục hay không:


fun main(args: Array<String>) {
var year:Int=0
var s:String?
println("Chương trình kiểm tra năm nhuần:")
do
{
println("Nhập 1 năm:")
s= readLine()
while (s==null || s.toInt()<0)
{
println("Nhập sai năm, nhập lại:")
s= readLine()
}
year=s.toInt()
if(year%4==0&&year%100!=0 || year%400==0)
{
println("Năm $year là năm nhuần")
}
else
{
println("Năm $year ko phải là năm nhuần")
}
print("Tiếp không?(c/k):")
s= readLine()
if(s=="k")
break;
}while (true)
println("Tạm biệt")
}

Chạy chương trình và nhập các giá trị sau để xem kết quả:

Chương trình kiểm tra năm nhuần:
Nhập 1 năm:
-4
Nhập sai năm, nhập lại:
2000
Năm 2000 là năm nhuần
Tiếp không?(c/k):c
Nhập 1 năm:
2015
Năm 2015 ko phải là năm nhuần
Tiếp không?(c/k):k

Tạm biệt

Như vậy tới đây Tui đã hướng dẫn xong vòng lặp do…while trong Kotlin, các bạn chú ý học kỹ và hiểu được nó thông qua các ví dụ ở trên nhé. Đặc biệt nắm được cách thức vận hành của do..while để có thể áp dụng tốt vào các dự án thực tế của mình.

Các bạn có thể tải source code bài này ở đây: http://www.mediafire.com/file/zehz2biw992vxeh/HocDoWhile.rar

Hẹn gặp các bạn ở những bài tiếp theo

Chúc các bạn thành công!

Trần Duy Thanh (http://ssoftinc.com/)

Bài 13-Vòng lặp while trong Kotlin


bài 12 chúng ta đã nắm chắc được cách thức hoạt động của vòng lặp for, trong bài này Tui sẽ hướng dẫn các bạn cấu trúc lặp với while. Đây cũng là một trong những cấu trúc lặp khá phổ biến trong các ngôn ngữ lập trình không riêng gì Kotlin, cú pháp:

while(expression)

{

  statement

}

Các bước thực hiện:

  • B1: Expression được định trị
  • B2: Nếu kết quả là true thì statement thực thi và quay lại B1
  • B3: Nếu kết quả là false thì thoát khỏi vòng lặp while.

Để thoát vòng lặp: dùng break

Để di chuyển sớm qua lần lặp tiếp theo : dùng continue

Lưu ý: Lệnh trong while có thể không được thực hiện lần nào do ngay từ đầu expression không thỏa

Lưu đồ hoạt động:

Ví dụ 1: Viết chương trình tính 5 giai thừa


fun main(args: Array<String>) {
var n:Int = 5
var gt:Int=1
var i:Int = 1
while (i <= n)
{
gt *= i
i++
}
println("$n! =$gt")
}

Giải thích chi tiết quá trình chạy:

Khởi tạo n=5, gt=1, i=1

Lần 1: kiểm tra i<=n <=>1<=5=>đúng => làm body while:

gt=gt*i=1*1=1

i++=>i=i+1=1+1=2

Lần 2: kiểm tra i<=n <=> 2<=5 => đúng => làm body while:

gt=gt*i=1*2=2

i++=>i=i+1= 2+1=3

Lần 3: kiểm tra i<=n <=> 3 <=5 => đúng => làm body while:

gt=gt*i=2*3=6

i++=>i=i+1=3+1=4

Lần 4: Kiểm tra i<=n <=> 4<=5 => đúng => làm body while:

gt=gt*i=6*4=24

i++=>i=i+1=4+1=5

Lần 5: Kiểm tra i<=n <=> 5<=5 => đúng => làm body while:

gt=gt*i=24*5=120

i++=>i=i+1=5+1=6

Lần 6: kiểm tra i<=n <=> 6<=5 => sai => ngừng while

Kết thúc chương trình ta được giai thừa =120

Ta có thể kết hợp các vòng lặp khác nhau lại, ví dụ có thể kết hợp vòng while và for, ví dụ dưới đây sẽ minh họa việc kết hợp này:

Ví dụ 2: Viết chương trình Kiểm tra một số bất kỳ có phải là số nguyên tố hay không(số nguyên tố là số chỉ chia hết cho 1 và chính nó, số 0 và số 1 không phải là số nguyên tố), chương trình cho phép hỏi người dùng có muốn tiếp tục nữa hay không?


fun main(args: Array<String>) {
var n:Int=0
var s:String?
println("Chào mừng đến với Chương trình kiểm tra số Nguyên Tố")
while (true)
{
println("Nhập số nguyên:")
s= readLine()
if(s!=null)
n=s.toInt()
var dem:Int=0
for(i in 1..n)
{
if(n%i==0)
dem++
}
if(dem==2)
println("$n là số nguyên tố")
else
println("$n ko phải là số nguyên tố")
print("Tiếp không?(c/k):")
s= readLine()
if(s=="k")
break;
}
println("Chào tạm biệt")
}

Chạy chương trình và nhập các giá trị sau để xem kết quả:

Chào mừng đến với Chương trình kiểm tra số Nguyên Tố
Nhập số nguyên:
5
5 là số nguyên tố
Tiếp không?(c/k):c
Nhập số nguyên:
7
7 là số nguyên tố
Tiếp không?(c/k):c
Nhập số nguyên:
6
6 ko phải là số nguyên tố
Tiếp không?(c/k):k
Chào tạm biệt

Như vậy tới đây Tui đã hướng dẫn xong vòng lặp while trong Kotlin, các bạn chú ý học kỹ và hiểu được nó thông qua các ví dụ ở trên nhé. Đặc biệt nắm được cách thức vận hành của while để có thể áp dụng tốt vào các dự án thực tế của mình.

Các bạn có thể tải source code bài này ở đây:http://www.mediafire.com/file/gv9pj5v721374qr/HocWhile.rar

Hẹn gặp các bạn ở những bài tiếp theo

Chúc các bạn thành công!

Trần Duy Thanh (http://ssoftinc.com/)

Bài 12-Vòng lặp for trong Kotlin


Với mọi ngôn ngữ lập trình thì các cấu trúc vòng lặp rất là quan trọng, đặc biệt là vòng for rất là phổ biến và hầu như trong mọi phần mềm đều chắc chắn sử dụng để giải quyết những công việc lặp đi lặp lại một cách có quy luật.

Kotlin cung cấp khoảng 5+ cách thức làm việc với vòng lặp for rất đa dạng, các kỹ thuật này Tui sẽ trình bày chi tiết thông qua việc giải thích lý thuyết cũng như các ví dụ minh họa, hi vọng các bạn sẽ hiểu thật chắc Vòng lặp for trong Kotlin.

1) Loại for thứ 1 – Duyệt tuần tự hết giá trị trong danh sách (closed range)

for (i in a..b)
{
Xử lý biến i
}

Với cú pháp ở trên thì biến i thực ra là biến bước nhảy, nó tự động tăng dần từ a cho tới b. Ta có thể thay tên biến i thành tên biến bất kỳ

Ví dụ 1: Viết chương trình tính giai thừa của một số nguyên dương n:


fun main(args: Array<String>) {
var gt:Int=1
val n:Int=5
for (i in 1..n)
{
gt *= i
}
println("$n!=$gt")
}

Ở đoạn lệnh trên, i sẽ chạy tuần tự từ 1 tới n (với n=5). Mỗi lần chạy nó sẽ nhân dồn i cho biến gt. Kết thúc vòng lặp ta sẽ được giai thừa của n.

Chi tiết quá trình chạy tính giai thừa theo thuật giải ở trên:

Lần lặp
Giá Trị Biến i Giá Trị Biến gt
0 gt=1
1 1 gt*=i=>gt=1*1=1
2 2 gt*=i=>gt=1*2=2
3 3 gt*=i=>gt=2*3=6
4 4 gt*=i=>gt=6*4=24
5 5 gt*=i=>gt=24*5=120

Sau đó lệnh:

println("$n!=$gt")

Được thực hiện, với kết quả: 5!=120

2) Loại for thứ 2 – Duyệt tuần tự gần hết giá trị trong danh sách (half-open range)

for (i in a until b)
{
Xử lý biến i
}

Với cú pháp ở trên thì biến i thực ra là biến bước nhảy, nó tự động tăng dần từ a cho tới gần b. Ta có thể thay tên biến i thành tên biến bất kỳ

Ví dụ 2: Viết chương trình tính tổng từ 1 tới gần số nguyên dương n:


fun main(args: Array<String>) {
var sum:Int=0
val n:Int=5
for (i in 1 until n)
{
sum += i
}
println("Tổng=$sum")
}

Chi tiết quá trình tính tổng:

lần lặp Giá Trị Biến i Giá Trị Biến sum
0 sum=0
1 1 sum+=i=>sum=0+1=1
2 2 sum+=i=>sum=1+2=3
3 3 sum+=i=>sum=3+3=6
4 4 sum+=i=>sum=6+4=10

Chú ý là chỉ chạy tới 4, vì theo cú pháp của until là chạy tới gần bằng. Do đó ở trên until n tức là gần bằng n, ở đây n=5 => i  chạy tới 4.

Sau đó lệnh:

println("Tổng=$sum")

Được thực hiện, với kết quả: Tổng=10

3) Loại for thứ 3 – Điều hướng bước nhảy step

for (i in a .. b step x)
{
Xử lý biến i
}

Với cú pháp ở trên thì biến i thực ra là biến bước nhảy, nó tự động tăng dần từ a cho tới b, nhưng mỗi lần duyệt nó tăng theo x đơn vị. Ta có thể thay tên biến i thành tên biến bất kỳ

Ví dụ 3: Viết chương trình tính tổng các số chẵn nhỏ hơn hoặc bằng số nguyên dương n:


fun main(args: Array<String>) {
var sum:Int=0
var n:Int=10
for (i in 2 .. n step 2)
sum+=i
println("Tổng chẵn=$sum")
}

Chi tiết quá trình tính tổng chẵn:

lần lặp Giá Trị Biến i Giá Trị Biến sum
0 sum=0
1 2 sum+=i =>sum=0+2=2
2 4 sum+=i =>sum=2+4=6
3 6 sum+=i =>sum=6+6=12
4 8 sum+=i =>sum=12+8=20
5 10 sum+=i =>sum=20+10=30

Chương trình chạy mỗi lần tăng i lên 2 đơn vị, ta khởi tạo i chạy từ 2 nên nó sẽ tự động tăng thành các số chẵn, gặp 10 thì nó thực hiện và kết thúc vòng lặp.

Sau đó lệnh:

println("Tổng chẵn=$sum")

Được thực hiện, với kết quả: Tổng chẵn =30

4) Loại for thứ 4 – Điều hướng bước nhảy downTo

for (i in b downTo a)
{
Xử lý biến i
}

Với cú pháp ở trên thì biến i thực ra là biến bước nhảy, nó tự động giảm dần từ b cho tới a, nhưng mỗi lần duyệt nó giảm 1 đơn vị. Ta có thể thay tên biến i thành tên biến bất kỳ

hoặc

for (i in b downTo a step x)
{
Xử lý biến i
}

Với cú pháp ở trên thì biến i thực ra là biến bước nhảy, nó tự động giảm dần từ b cho tới a, nhưng mỗi lần duyệt nó giảm x đơn vị. Ta có thể thay tên biến i thành tên biến bất kỳ

Ví dụ 4: Viết chương trình tính Ước số chung lớn nhất của 2 số bất kỳ


fun main(args: Array<String>) {
    var a:Int=9
    var b:Int=6
    var ucscln=1
    var min=if (a>b) b else a
    for (i in min downTo 1)
    {
        if(a%i==0 && b%i==0)
        {
            ucscln=i
            break
        }
    }
    println("USCL của $a và $b = $ucscln")
}

Chi tiết quá trình tìm ước số chung lớn nhất:

trước khi vào vòng lặp for thì ta được các thông tin sau:

a=9, b=6, ucscln=1, min=6 (ta phải tìm min vì với 2 số thì may ra nó chỉ chia hết cho số nhỏ hơn)

Lần lặp
Giá Trị Biến i Giá Trị Biến ucscln
0 a=9, b=6, ucscln=1, min=6
1 6 if (a%i==0 && b%i==0)

<=>if (9%6==0 && 6%6==0)

=>không thỏa

2 5 if (a%i==0 && b%i==0)

<=>if (9%5==0 && 6%5==0)

=>không thỏa

3 4 if (a%i==0 && b%i==0)

<=>if (9%4==0 && 6%4==0)

=>không thỏa

4 3 if (a%i==0 && b%i==0)

<=>if (9%3==0 && 6%3==0)

=>thỏa điều kiện

=>thực hiện ucscln=i=>ucscln=3

=>break =>thoát khỏi vòng lặp for

Tới lần lặp thứ 4 thì lúc này cả a và b điều chia hết cho i (i=3)  nên nội dung if sẽ được thực hiện, lúc này ucscln=3 và lệnh break ngay sau đó thực hiện ngừng vòng lặp

Sau đó lệnh:

println("USCL của $a và $b = $ucscln")

Được thực hiện, với kết quả: USCL của 9 và 6 = 3

5) Loại for thứ 5 – Lặp tập đối tượng

for (item in collection)

{

println(item)

}

Cấu trúc for trên sẽ duyệt từng đối tượng trong một tập đối tượng

Ví dụ 5: Duyệt danh sách tên sản phẩm


fun main(args: Array<String>) {
var dsSanPham= arrayOf("kotlin","java","c#","python","R")
for (item in dsSanPham)
println(item)
}

Đoạn code trên, chương trình sẽ duyệt tuần tự từng phần tử trong mảng dsSanPham và xuất tên của chúng ra.

Ngoài ra ta cũng có thể duyệt theo vị trí, từ vị trí này ta có thể xuất ra giá trị như sau:


fun main(args: Array<String>) {
var dsSanPham= arrayOf("kotlin","java","c#","python","R")

for (i in dsSanPham.indices)
println("Sản phẩm thứ $i có tên "+dsSanPham[i])
}

Cuối cùng kotlin cũng hỗ trợ vừa lấy vị trí vừa lấy giá trị theo cách sau:


fun main(args: Array<String>) {
var dsSanPham= arrayOf("kotlin","java","c#","python","R")
for ((index,value) in dsSanPham.withIndex())
{
println("Sản phẩm thứ $index có tên $value")
}
}

Như vậy tới đây Tui đã hướng dẫn xong vòng lặp for trong Kotlin, các bạn chú ý học kỹ và hiểu được nó thông qua các ví dụ ở trên nhé. Đặc biệt nắm được 5 cách thức vận hành của for để có thể áp dụng tốt vào các dự án thực tế của mình.

Các bạn có thể tải source code bài này ở đây: http://www.mediafire.com/file/7ku4okq72mj1iam/HocFor.rar

Hẹn gặp các bạn ở những bài tiếp theo

Chúc các bạn thành công!

Trần Duy Thanh (http://ssoftinc.com/)