Aug 31, 2013

Nguyên tắc lập trình C/C++

Một số nguyên tắc lập trình trên C/C++ khá là hay, việc tuẩn thủ, hoặc làm theo những gợi ý được đề ra sẽ giúp lập trình viên tránh được một số "tính năng bất ngờ" mà C++ gây ra mà ta không lường trước được. Đồng thời giúp lập trình viên có thói quen làm việc hiệu quả hơn


  • Original Indian Hill guide with annotations by H. Spencer. PDF
  • Indian Hill C style guide, as amended at UofT, UW, and elsewhere. PDF
  • C++ coding rules from Ellemtel (Swedish Telecom) by Mats Henricson and Erik Nyquist. PDF
  • C++ style guide from Wildfire Communications. Link
  • C++ Coding Standard by Todd Hoff. Link.
  • C++ style advice called "The Tao of Coding" from Koen Witters.Link
  • The C Style Guide and Programming Guidelines from The C Kernel pages by Peter van der Vlugt.PDF
  • Words of wisdom from Henry Spencer and Geoff Collyer about the appropriate use of #ifdefs, a paper presented at the Summer 1992 Usenix conference.PDF
  • C Coding Standard.Link

Aug 25, 2013

Ép kiểu ngầm định - Implicit conversion

Một buổi chiều dẹp các chuyện linh tinh bên Windows Phone, mình lại có hứng thú viết về cu C++ dấu yêu. Lần này là 1 chủ đề rất là nhỏ: ép kiểu ngầm định (implicit conversion)

Vì sao gọi là nhỏ? Vì nó khá là cổ điển và ít được quan tâm nhiều lắm. Tuy nhiên để tìm hiểu tận gốc vấn đề thì cái này khá là hay ho.

Ép kiểu ngầm định từ T1 sang T2 xảy ra khi trong một biểu thức kiểu T1 được dùng trong ngữ cảnh nó không được chấp nhận, tuy nhiên, ngữ cảnh đó lại chấp nhận kiểu T2.

Ví dụ:

int b = 1.2 + 3.4;

Biểu thức ở đây có kiểu là float, nhưng ngữ cảnh của nó sử dụng lại là kiểu

int
. Và thế là chương trình phải làm một cái gì đó để chuyển đổi giữa kiểu float sang int, tuy nhiên điều này không được người lập trình đề cập, thành ra trình biên dịch sẽ tự làm âm thầm và đó chính là ép kiểu ngầm định .

Đọc cái này. Và ta cần highlight một số đoạn sau.

Standard conversions affect fundamental data types

Điều gì ở đây? Standard conversionfundamental data types .Các kiểu dữ liệu cơ sở đã cung cấp sẵn một số ép kiểu, người lập trình không cần định nghĩa lại. Đồng thời, những phương thức ép kiểu đó đã được nâng lên thành chuẩn. Danh sách các phép ép kiểu chuẩn hóa có trong đây (tài liệu từ MSDN ).

the compiler can signal with a warning. This warning can be avoided with an explicit conversion.

Về cái sự ép kiểu ngầm định có thể xảy ra mất mát thông tin (thử ép biến i = 1000 sang char thì biết), compiler sẽ thông báo với ta về sự mất mát thông tin đó. Tuy nhiên, nếu sử dụng ép kiểu chỉ định (explicit conversion) thì điều này không xảy ra. Lý do? Vì khi đó người lập trình đã chấp nhận mất mát thông tin, bởi chính họ là người đã gõ dòng code đó vào.

Tip nho nhỏ: để bật chế độ kiểu tra ép kiểu ngầm định, dùng option -Wconversion , option -Wall không support chuyện này.

Ép kiểu ngầm định xảy ra khi từ T1 sang T2 khi:

  1. Một biểu thức là tham số đầu vào có kết quả trả về là T1 nhưng tham số lại yêu cầu kiểu T2
  2. Một biểu thức có toán hạng là kiểu T2.
  3. Khởi gán một biến có kiểu T2.
  4. Lệnh return trả về kiểu T2.
  5. Biểu thức dùng trong lệnh switch (với T2 là integral type)
  6. Biểu thức dùng trong các lệnh if và các lệnh lặp. T2 trong trường hợp này là kiểu bool

Đọc tiếp tài liệu bên cpp, ta highlight tiếp phần này:

Implicit conversions also include constructor or operator conversions

Ép kiểu ngầm định cho phép dùng contructor và toán tử ép kiểu để chuyển đổi. Vậy ngoài standard conversions ra, ta còn có cả user-defined conversions. Vì vậy, compiler sẽ có một số nguyên tắc nhằm chọn ra phép biến đổi nào cần dùng:

  • Khi T2 là tham số của constructor hay của hàm chuyển kiểu do người dùng định nghĩa (user-defined conversion function) thì compiler sẽ ưu tiên cho standard conversion
  • Khi T2 và T1 đều là built-in types thì compiler sẽ ưu tiên standard conversions.

Tham khảo:

  1. Implicit cast in cppreference
  2. cplusplus
  3. MSDN

Khắc phục lỗi không tương thích gVim và iBus trong Linux.

Một vấn đề làm đau đầu mình mấy tháng nay đó là cu GVim không gõ được tiếng Việt nếu dùng iBus. Điều lạ lùng là em ý lại chạy ngon lành trên Windows mới ác(trên Win thì dùng UniKey). Sau một ngày rãnh rỗi không biết làm gì, mình đã tìm ra được nguyên nhân.

  1. Đối với Vim/GVIM. Đảm bảo rằng hỗ trợ utf-8 đầy đủ. Có thể tham khảo ở đây.
  2. Đối với cu Ibus, trong phần preference, tick bỏ mục Embed predict text in application windows..
Nguyên nhân, do mình suy đoán là lỗi không tương thích giữa phần popup các của gVim (chức năng intellisense) với phần predict text của cu iBus.

Aug 21, 2013

Bisection method


Tình cờ *học lại* môn nhập môn lập trình bên MIT, thực ra đó là khóa Introduciton to Computer Science. Thuật toán này không có gì mới lạ, nhưng ứng dụng của nó khá là hay ho.

Bài toán: Tìm căn bậc 2 của 1 số thực dương cho trước.

Phân tích một cách thông thường, ta sẽ đi tìm nghiệm của phương trình: x^2- a = 0. Với a nhập từ bàn phím. Bài toán quay về tìm nghiệm của phương trình trên.

Có 2 phương pháp chính ở đây được giới thiệu là bisection method và Newton method, cả 2 phương pháp này khá là dễ hiểu. Và nếu tìm hiểu trên wiki, ta sẽ thấy 2 giải thuật trên là nền móng cho kha khá cả giải thuật khác.Link

Bisection method

Tư tưởng của Bisection khá là dễ hiểu: cho một hàm $f$ liên tục, nếu ta biết được răng $f(a)f(b) < 0$ thì đâu đó trong đoạn [a, b] có một giá trị x để f(x) bằng 0. Dĩ nhiên, mấu chốt vẫn là $f$ phải liên tục. Ta tiếp tục thu nhỏ khoảng $[a,b]$ này lại cho đến khi nào giá trị tìm được của a hoặc b cho $f(x) = 0 $ hoặc khoảng cách a và b nhỏ hơn 1 epsilon nào đó. Để làm điều đó, ta xét giá trị c: $ c = \frac{a+b}/2 $. Nếu f(c) = 0, thì c là số cần tìm, còn nếu $f(c) < 0 $ thì chắc chắn giá trị cần tìm ở đâu đó trong đoạn [c, b]. Ngược lại nếu $f(c) > 0$ thì giá trị x trong khoảng [a, c]. Cứ tiếp tục vậy.

Đoạn code thử nghiệm

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def bisectionMethod(x, epsilon):
    """ Find square root of x with epsilon
    """
    assert x > 0
    assert epsilon > 0
    low = 0
    high = max(x, 1)
    value = (low + high) / 2.0
    loop = 0
    while (abs(value**2 - x) > epsilon ):
        if ((value**2-x) < -epsilon): low = value
        elif ((value**2-x) > epsilon): high = value
        value = (low + high) / 2.0
        loop += 1;
    print "Bisection method: Value:", value, ". Loop: ", loop

Newton method

Tư tưởng của phương pháp này dựa vào công thức tính đạo hàm của 1 hàm số:

\[ f'(x_1) = \frac{df(x_1)}{dx} \approx \frac{f(x_1) - f(x_2)}{x_1-x_2} \]

\[ x_2 = x_1 - \frac{f(x_1)}{f'(x_1)} - \frac{f(x_2)}{f'(x_1)} \]

Vì $f(x_2) = 0 $ nên :

\[ x_2 = x_1 - \frac{f(x_1)}{f'(x_1)} \]

Tổng quát hóa:

\[ x_n = x_{n-1} - \frac{f(x_{n-1})}{f'(x_{n-1})} \]

Đoạn code thử nghiệm:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def newtonMethod(x, epsilon):
    """ Newton method
    """
    assert x > 0
    assert epsilon > 0
    value = x
    loop = 0
    while (abs(value**2 - x) > epsilon):
        value = value - (value**2-x)/(2.0*value)
        loop += 1
    print "Newton method. Value: ", value, ".Loop: ", loop

So sánh 2 phương pháp:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
def test(x, epsilon):
    assert x > 0
    assert epsilon > 0
    bisectionMethod(x, epsilon)
    newtonMethod(x, epsilon)
    print
test(100, 0.2)
test(10000, 0.0000002)
test(123456789,0.0000002)
test(0.25, 0.00002)

Ta nhận thấy phương pháp Newton tốt hơn so với Bisection. Tuy nhiên, với phương pháp Newton, chọn giá trị khởi đầu như thế nào sẽ là một vấn đề quan trọng.


Aug 13, 2013

Thủ thuật VIM.

Có rất nhiều cách khác nhau để thao tác trong VIM, quan trọng là công việc đó khiến ta nhanh đến mức nào. Dưới đây là cơ số các thủ thuật, kinh nghiệm của mình khi tìm hiểu và lập trình dùng VIM.


  1. Chọn nội dung của 1 tag trong HTML/XML: vit. Dịch sang tiếng việt: chuyển sang chế độ visual (v), chọn nội dung trong (in - a) tag (t) hiện thời. Thay i thành a ta chọn cả nội dung và cả tag mà nó chứa.
  2. Tự động canh lề cả file text: gg=G. Nhìn đẹp như vậy nhưng cũng có ý nghĩa của nó: gg để di chuyển đến đầu file. = dùng để tự canh lề và G là thực hiện đến cuối file.

Tài liệu sử dụng VIM.

Một slide rất hay và hấp dẫn dành cho người tim hiểu về VIM.

Một bài nữa, của chính tác giả đã viết ra VIM, Brian Moolenaar:

Bài dưới này trình bày cách "làm thế nào học và sử dụng VIM hiệu quả":


Một chút tự sướng về VIM, editor dành cho hacker :D

Xóa hoàn toàn Visual Studio 2008/2010


Vào một ngày đẹp trời và mình cần phải dọn dẹp cu Visual Studio 2008. Điều oái ăm là suite này đã cài vào máy hầm bà lằng các thứ, và do mình cài cả 2010, 2013 và vọc lại toàn bộ component nào của VS2008 rất là cực hình

May mắn là mình tìm được vài tool xóa sạch mấy thức rắc rối này.

Cả 2 tool này đều gọn nhẹ và rất dễ dùng. :)

Aug 6, 2013

Lấy dữ liệu từ checkbox trong php

Bài này ... không viết không được. Một vấn đề mà hồi nhỏ mình đã nghi ngờ nhưng chưa thử. Nhỏ thực ra thì lúc đó tầm lớp 9, làm cái Đố Vui bằng PHP. Giờ gặp lại.


Làm thế nào để lấy các giá trị từ các checkbox có cùng tên?. Giả sử có 1 checkbox là danh sách các món ăn để gọi. Điều ta mong đợi ở đây là nó sẽ trả về cho ta 1 mảng chứa các giá trị mà người dùng đã chọn

Code demo nó như thế này:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
// For processing
if (isset($_POST[sbMyForm]))
{
    echo "<pre>";
    print_r ($_POST[myCheckbox]);
    echo "</pre>";

}
?>
<html>
<head>
<title>Demo: checkbox</title>
</head>
<body>
<form method="POST" action ="checkbox.php">
    <p><input type="checkbox" name="myCheckbox" value = "TrangTron">Bánh tráng trộn</input></p>
    <p><input type="checkbox" name="myCheckbox" value = "BapXao"> Bắp xào </input></p>
    <p><input type="checkbox" name="myCheckbox" value = "TrangNuong">Bánh tráng nướng </input></p>
    <input type="submit" name="sbMyForm" value="Hoàn thành"></input>
</form>
</body>
</html>

Chạy thử code, điều đáng buồn là nó chị hiện đúng cái selection cuối cùng mà người dùng chọn. Để sửa lỗi trên, ta chỉ cần thay đổi myCheckbox thành myCheckbox. Nó sẽ trở thành 1 mảng khi truyền vào trong $_POST. Đơn giản và hiệu quả.
1
2
3
<p><input type="checkbox" name="myCheckbox[]" value = "TrangTron">Bánh tráng trộn</input></p>
    <p><input type="checkbox" name="myCheckbox[]" value = "BapXao"> Bắp xào </input></p>
    <p><input type="checkbox" name="myCheckbox[]" value = "TrangNuong">Bánh tráng nướng </input></p>