Nov 14, 2013

Khôi phục USB Transend

Vừa bị chê cái giao diện của blog xấu, chăc hôm nào rảnh lại đi tìm theme khác vậy.

Quay lại chủ đề của entry này. Lâu nay mình vẫn trung thành với USB của Transcend. Ngày xưa thì xài cái USB 256MB, qua nhiều đợt mất, hư, cho mượn nhưng dân tình không trả, mình vẫn xài các thế hệ tiếp theo của em ý.

Chẳng là hôm trước cần cài lại Windows 8, và cũng phải config lại Boot Menu của Linux (khi cài Windows xong thì boot menu của GRUB 2 cũng mất theo). Sau một hồi nghịch, forrmat các kiểu thì Windows không còn nhận ra USB nữa. Kích thước ổ đĩa quay về mức 0 byte. Lúc đó đã cố gắng tìm một số tool chuyên dụng để forrmat lại cũng không thành công, trước đó thì usb mình không còn khả năng boot được nữa. Trong lúc không biết làm gì, mình quoẻn quởn lên trang của TRanscend và download tool của nó về. Và thật kỳ diệu, nó đã fix được cái USB xấu số một dăm ba cái Next.
Link download
Không biết các hãng khác có tool này không, nhưng tool này thực sự hữu dụng và cực kỳ dễ dùng.

Oct 6, 2013

Bộ lọc tuyến tính.

Đáng lí ra sẽ có bài về các phép tính trên từng pixel, nhưng vì hiện giờ đang học về filter. Nên sẽ nói về filter trước.

Bài viết dưới đây được lấy và tham khảm từ một số nguồn:

  • Khóa Computer Vision - Stanford.
  • Cuốn "Computer Vision - A Modern Approach".
  • Một số nguồn linh tinh khác sẽ được liệt kê sau.

Một ảnh thực chất là biểu diễn của một hàm từ không gian $R^2$ sang không gian $R^M$. Hàm này sẽ cho ta biết về cường độ của điểm ảnh tại vị trí (x, y). Chính vì vậy, khi $M=1$ ta được ảnh mức xám, khi $M=3$ ta sẽ được ảnh màu gồm 3 kênh. Tuy nhiên, vì một ảnh trong tự nhiên là một hàm có tập xác định là tập số thực, nhưng máy tính chỉ hiểu được ảnh ở miền là các số nguyên. Vì vậy ta cần một bước để chuyển ảnh từ không gian thực sang miền mà máy tính hiểu được. Phép biến đổi đó gọi là số hóa.

Số hóa bao gồm các 2 phép chính:

  1. Sampling.
  2. Quantization - lượng hóa.

Phép Sampling làm nhiệm vụ chuyển tập xác định từ số thực sang số nguyên. Đơn giản hơn, sampling là phép dùng 1 cái lưới rộng và trùm lên trên tấm ảnh. Mỗi ô của lưới được gọi là pixel.

Sau khi thực hiện xong Sampling, ta sẽ chỉ chọn đúng 1 màu duy nhất cho mỗi pixel của ảnh. Giá trị này là số nguyên. Việc chọn giá trị của pixel như thế nào, hay chia lưới như thế nào là một kỹ thuật riêng, và ... khá là hấp dẫn. Sẽ được bàn luận sau vậy.

Bộ lọc tuyến tính - Linear Filters

Một bộ lọc có chức năng chuyển một tấm ảnh thành một tấm ảnh mới, mà những pixel của ảnh mới là tổ hợp giá trị pixel của các ảnh cũ. Việc dùng các bộ lọc có tác dụng:

  • Rút trích những thông tin hữu ích từ ảnh.
  • Thay đổi hoặc tăng cường các thuộc tính của ảnh.

Để sử dụng filter, ta áp dụng công thức sau:

\[ g(x,y) = \sum_{k,l}f(i-k, j-l)h(k,l) \]

Trong đó $g(x,y)$ là ảnh kết quả. $f(x,y)$ là ảnh đầu vào, $h(k,l)$ là mặt nạ (mask) hay còn gọi là nhân (kernel).

Công thức phía trên có thể viết gọn thành:

\[ g = f \bigotimes g \]

Tham khảo:

  • Computer Vision - A Modern Approach
Còn tiếp.

Sep 21, 2013

Bật chế độ God Mode trong Windows 7/8

Đây là một trong những tính năng ẩn của Windows. Sau 1 ngày vật vã để sửa lại driver Windows 8, mình tình cờ phát hiện ra em này.

Chức năng: Liệt kê tất cả các chức năng cho phép và hợp pháp để chỉnh sửa, cấu hình trong Windows 7/8.
Thực hiện:
  1. Ra ngoài Desktop và tạo 1 thư mục
  2. Đối với Windows 7. Nhập tên thư mục như sau:
    GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}
    Đối với Windows 8:
    GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}
    Gõ xong phát hiện 2 cái này giống nhau :)). Kết quả sau đó ta được một thư mục liệt kê như sau:

Sep 19, 2013

Driver Wifi trên Windows 8

Vụ này không share không được, kể từ khi cài Windows 8 lên trên em Dell dòng Inspiron thì có hiện tượng mạng cực kỳ chậm và dễ gây ức chế kinh khủng. Đã vậy còn chập chờn.

Giải pháp là đây: Link download . Trong hàng tá cách, thì đây là cách đơn giản nhất, và là giải pháp hữu hiệu nhất. Xóa Driver cũ của Windows đi và cài cái mới này.
Chi tiết từng bước:
  1. Vào Control Panel - > Device Manager. Ta Click chuột phải vào Broadcom 802.11n rồi chọn Disable
  2. Sau đó chọn tiếp Uninstall
  3. sau khi xóa xong, Windows sẽ cố gắng tìm driver trong hệ thống để cài lại, và nếu nó cài thành công thì mọi chuyện vẫn hoàn cũ. Lúc này nhanh chóng cài driver mới tải kia về. Vậy là mọi chuyện được ổn thỏa.
  4. Trường hợp không tắt được dịch vụ tự tìm driver: ta click vào Properties của driver đó, chọn thẻ Driver chọn button Driver Details Trong đó liệt kê tất cả các file liên quan đến driver. Ta chỉ cần vào từng file rồi xóa. Sau đó cài lại driver mới.

Sep 5, 2013

Load ảnh từ OpenCV

Chào mừng năm học mới, thắng lợi mới nên mình sẽ viết một loạt series về opencv và một số kiến thức liên quan đến thị giác máy tính. Một phần để phục vụ việc học tập( ngâm cứu) của bản thân, một phần chia sẻ kiến thức với bạn nào có đam mê và muốn thử với lĩnh vực này.

Chủ đề của hôm nay. Mở đầu năm học bằng 1 công việc rất đơn giản: load ảnh dùng opencv.
Ngôn ngữ:C++, sẽ bàn một chút đến C và Python.
Để load 1 ảnh đã tồn tại trong bộ nhớ ngoài, ta dùng API imread.
Tham số của API này:
  • filename (const char*): đường dẫn đến file cần load.
  • flags (int): các tùy chọn khi load ảnh. Một số tham số hay ho:
    • &gt 0: Trả lại ảnh có 3 kênh màu. Kênh $ \alpha $ sẽ bị lược bỏ.
    • = 0: Trả về ảnh mức xám.
    • &lt 0: Trả về ảnh nguyên gốc.
imread sẽ trả lại là một đối tượng kiểu Mat. Nếu không thành công, kết quả trả về sẽ là một ma trận rỗng, tức Mat::data = NULL. Ta có thể dùng kết quả này để check xem file thực sự đã được load hay chưa. Bởi vì imread không có cơ chế exeptions nên khi có lỗi xảy ra, ta phải đợi đến các hàm xử lý tiếp theo (có exceptions hoặc assert) mới biết được. Điều này rất là bất lợi khi debug: ta cứ nghĩ ảnh đã được load vào, nhưng thực sự là chưa.
Sau khi load xong, công việc tiếp theo sẽ là show tấm ảnh đó ra màn hình. OpenCV hỗ trợ tốt tác vụ này với API: imshow. Tham số lần lượt của API này như sau:
  1. windows name (string): Tên của cửa sổ màn hình.
  2. image (Mat): biến lưu trữ ảnh đã được load
Đoạn mã ví dụ:

1
2
3
4
5
6
7
8
9
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
    Mat img = imread("hello.png", 1);
    imshow("show image", img);
    waitKey(0);
    return 0;
}

Hàm waitKey có một chức năng nho nhỏ. Nó sẽ đợi người dùng nhấn một phím bất kỳ rồi mới thực hiện công việc tiếp theo. Tham số đầu vào là 0, mặc định là vậy. Lớn hơn 0 là số milisecond mà waitKey sẽ delay.
Tất cả các api vừa kể trên là của C++, OpenCV hỗ trợ cả ngôn ngữ C. Để tránh nhầm lẫn đáng tiếc( vì C/C++ là hai anh em rất là gần gũi nhau), nên các API kể trên đều nằm trong namespace cv. Còn các cấu trúc khác thuộc C sẽ có tiền tố CV đứng trước.
Vậy ứng dụng của đoạn code nho nhỏ này là gì? Một điều hay ho của các API bên OpenCV là nó cross-platform. Rinh qua bên Linux chạy ngon, và để Windows cũng tốt chán. Vì cái sự cross-platform đó, và vì đây là thư viện tập trung vào xử lý ảnh, nên số các API hỗ trợ user interface rất ít. Nhưng, nhưng ít ra, nó cũng đủ cho ta chế 1 tool graphic debug. :D
Ý tưởng:
  • Một cửa sổ Windows cho phép resize, đồng thời là 1 điểm breakpoint kiểm tra xem đoạn code của ta tới đó đã thỏa mãn chưa.
  • (Option): Click vào mỗi pixel sẽ trả về giá trị ở pixel đó.
Hướng giải quyết:
  • Việc tạo 1 của sổ cho phép resize ảnh không khó, việc tạo breakpoint đơn thuần là gọi hàm waitKey().
  • Việc đọc giá trị của pixel phụ thuộc rất lớn vào: số kênh của ảnh (1, 3), và kiểu lưu trữ của mỗi kênh đó (uchar, float, double, int)... Việc click để chọn vị trí pixel khá đơn giản. Tuy nhiên, hiện nay mình vẫn chưa có cách thỏa đáng nào (ngoại trừ việc if...else một đống các trường hợp và gọi từng hàm phù hợp.
Tạo một header file. ví dụ là debugtool.h có nội dung sau:
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#ifndef __DEBUGTOOL
#define __DEBUGTOOL

#include <cassert>
#include <opencv2/opencv.hpp>
void __clickevent(int evnt, int x, int y, int flags, void* params);
#ifdef NDEBUG
#define debug_img(img) 
#else
#define debug_img(img) {\
 cv::namedWindow("Debug:"#img, CV_WINDOW_NORMAL | CV_WINDOW_FREERATIO);\
 cv::setMouseCallback("Debug:"#img, __clickevent,(void*) &img);\
 cv::imshow("Debug:"#img, img);\
    cv::waitKey(0);\
 cv::destroyWindow("Debug:"#img);\
 }
#endif

#endif
Sau đó tạo file cpp tên debugtool.cpp có nội dung:
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include "debugtool.h"

void __clickevent(int event, int x, int y, int flags, void* params)
{
    if (event != CV_EVENT_LBUTTONUP) return;
    IplImage *iplImg = new IplImage(*(cv::Mat*) params);   
    assert(iplImg->imageData != NULL);
    std::cout << "(" << x << "," << y << "): " 
                << cv::Scalar(cvGet2D(iplImg ,x, y)) << std::endl;
    std::cout.flush();
}

Xong, giờ có thể dùng debug_img bất cứ đâu như 1 breakpoint kiểm tra 1 ảnh. Click vào pixe để xem các giá trị. :)

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>

Jul 14, 2013

Câu chuyện về *const member method*


Câu chuyện về *const member function*


Một ngày vật lộn với cái paper. Chỉ còn chút xíu nữa thôi là thông xong. Tuy nhiên buổi chiều rảnh rỗi, mình lại nhớ đến vụ const member funciton mà mình muốn viết về nó chăm ba chút.

Nếu rảnh rỗi sinh nông nổi và không có chuyện gì để làm. Ta có thể mò đến trang về phương thức at của container vector. Rảnh rỗi nữa có thể xem luôn operator[] của container vector luôn.. Điều gì hay ho vậy? Ở đây có tới 2 hàm được overload (dịch là: chồng hàm, bên congdongc thì là quá tải hàm. Mình thì thích overload hơn ^_^ ).

Phương thức at và toán tử [] khác nhau ở điểm nào nhỉ? at có exception văng ra còn toán tử [] thì lại không.

Một chút về phần định nghĩa. Tụi MSDN có nói: const member function là một phương thức không làm thay đổi đối tượng khi được gọi. Nó CHỈ có thể thay đổi các giá trị static và gọi các const member function khác của object. Từ khóa const được dùng trong phần khai báo và phần định nghĩa.

Và như vậy, const object chỉ có thể gọi được các const member function. Tuy nhiên, const member funciton thì có thể được gọi từ non-const object và const object.

Hiểu tới đây thì vẫn chưa giải thích vì sao lại có 2 phương thức at và 2 toán tử []. Giờ là lúc xét ví dụ dưới đây:


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
*Example about const member function
*/
#include <iostream>

using namespace std;

class Point
{
private:
 int x, y;
public:
 Point() {};
 ~Point() {};
 const int& X(void) const {return this->x;}; // (1)
 Point& X(const int& x) { this->x = x; return *this;} ; //(2)
};
class Line
{
private:
 Point e1, e2;
public:
 const Point& E1() const {return this->e1;} ; // (3)
 Point& E1() {return this->e1;}; // (4)
 Line() {};
 ~Line() {};

};
int main()
{
 Line l;
 l.E1().X(10);
 //l.E1().X(10);
 return 0;
}

Đoạn code trên "nhại" lại phương thức at 1 chút. Và ta đã rõ: những phương thức nào cần truy xuất để lấy các giá trị (getter) thì ta cài đặt là const member function, còn phương thức nào nhằm thay đổi nội tại giá trị (trong ví dụ là thay đổi hành độ của 1 đỉnh trong đoạn thẳng) thì ta dùng non-const member function

Nhiều lúc vì vội vàng, mình chỉ đơn giản tạo 1 const member function mà không tạo 1 bản non-const. Chính điều đó khiến đôi lúc gặp phải những lỗi rất khó chịu, và thường với các đồ án lớn, việc debug trở nên một cực hình. Khi viết 1 hàm, ta cần phải suy nghĩ kĩ: có bao giờ hàm này làm thay đổi giá trị, hay gián tiếp làm thay đổi giá trị của đối tượng không? Như ví dụ trên, bên trong hàm const không hề có 1 câu lệnh nào làm thay đổi đối tượng, ta chỉ thông qua qua nó để thay đổi giá trị con (giá trị hoành độ).


Jul 7, 2013

Khắc phục lỗi khi đăng kí tài khoản Windows 8 Dev và Windows Phone Dev

Kinh nghiệm xương máu là khi đăng kí nó báo 2 lỗi sau:
  1. Không thể lưu thông tin. vui lòng thử lần nữa.
  2. Địa chỉ không hợp lệ
Để khắc phục lỗi này, cần lưu tâm 1 số điều:
  • Không điền postal code đối với các thành phố ở Việt Nam
  • Địa chỉ ngắn và gọn. Tốt nhất là dùng IE, vì nó có giới hạn số kí tự được nhập vùng Address
Đối với các tài khoản MSDN, khi đăng kí là học sinh(sinh viên) thì bên MS sẽ yêu cầu xác nhận, khi đó trang DreamPark hiện ra, ta nhập mã kích hoạt. Sau đó quay lại mới đăng kí làm tài khoản sinh viên được.

Jun 19, 2013

[Tips] Tổ chức mã nguồn và lập trình Windows

Hôm nay lại hì hục với đồ án cuối kì môn Đồ Họa, kinh nghiệm thương đau lại về. Mà đau đớn hơn là do cu Micro$oft làm ra. Có thể kể một số lỗi chết người sau.
Các định danh đã được xài. Tụi MS rất vui tính, trong các thư viện tụi nó đã vứt vào đó rất nhiều biến, hàm, macro toàn cục rất dễ bị nhầm lẫn. Ví dụ từ nearfar. Nếu khai báo rồi mà lại còn xài windows.h thì coi như toi.

Cái thứ 2: Dù lười mấy đó thì lười. Thì việc định nghĩa hàm (hàm function chứ không phải method). Nếu đặt vào file cpp chứ không đặt trên header file. Vì chỉ cần 2 file trong project cùng include file header đó thì hàm đó sẽ được định nghĩa 2 lần. Và lỗi này khó giải quyết. Để cẩn thận, tốt nhất là nên rạch ròi giữa phần khai báo và định nghĩa.

Cái thứ 3: Tổ chức dữ liệu cho rõ ràng và cụ thể. Điều này đặc biệt quan trọng trong lập trình team. Sự nhập nhằng này khiến cho code chung rất khó chịu. Chính điều đó làm mã nguồn rối rắm, thuật toán không cụ thể và đặc biệt là khó giao tiếp với nhau qua code được.

Cái thứ 4: Chuyện đặt trình tự file header khá là hay ho. Nó có thể giúp ta xác định được lỗi nhanh chóng. Dưới đây là 1 số cách thông dụng:
  • Gom tất cả những header file cần thiết vào 1 header file. Ví dụ đây là 1 file tên libs.h
    /* * * * * * * * * * * * * * * * * * * * 
    * System and Standard Library header file
    * Author: DangKhoaSDC.
    * * * * * * * * * * * * * * * * * * * * /
    #ifndef _STANDARDLIBS
    #define _STANDARDLIBS
     
     
    #ifndef __cplusplus
    #error "Must use C++ compiler!!"
    #endif
     
    /* Use pre-defined C/C++ compiler macros to determinate OS,
    * version or architectures
    * More info: http://sourceforge.net/p/predef/wiki/Home/
    */
    #ifdef _WIN32
    /* * * * * * * * * 
    * Place for Windows
    *  * * * * * * * */
    #endif
     
    #ifdef __gnu_linux__
    /* * * * * * * * * 
    * Place for Linux
    *  * * * * * * * */
     
    #endif
     
    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
     
    #include <cstdlib>
    #include <cstdio>
     
    /*
    * User-defined header file
    */
    #endif 
    
    Sau đó thì có thể thoải mái add file này vào trong các mã khác. File này cần header file đặc biệt thì mới cần thêm vào sau.
  • Tùy cơ ứng biến. File nào cần cái gì thì include cái đó. Một cái lợi lớn là không biên dịch ra những file quá lớn. Nhưng đôi lúc lại không quản lí được vì hơi lộn xộn. Hoặc cần phải tự tạo một phong cách đặt trình tự các header file để tránh gây ra các lỗi đáng tiếc.

Chút về viết tiếp
================

Jun 15, 2013

Review Linux Mint 15 Olivia

Không hổ danh là bản distro cực kì ổn định, Linux Mint 15 đã cho thấy những bước tiến khá tốt và giữ vững phong độ. Tuy không có quá nhiều thay đổi đột phá. Nhưng những cải tiến mới cũng đủ làm người dùng hài lòng.

Giao diện của cu cậu:
Đây là phiên bản dùng giao diện Cinnamon. Rất tinh tế, nhẹ nhàng và hiện đại. Hiện nay thì cu cậu mới hỗ trợ cho giao diện MATE và Cinnamon. Dĩ nhiên có thể dùng các giao diện khác nếu muốn ( Dùng Software Manager để tải).
Một số thay đổi trong phiên bản này:
  • Bản cày đặt "nặng" hơn tầm dăm ba MB. Tuy nhiên Linux Mint không còn cài sẵn ứng dụng Libre Office. Nautilus,cũng bị loại bỏ không thương. Cùng lúc đó, Linux Mint đã cài thêm một số gói: systemd, kmod. Ngoài ra không có quá nhiều thay đổi về hệ thống .
  • Thêm tính năng Desklets bên giao diện Cinnamon. Tượng như các Widget bên Windows. Cá nhân thì mình không thích nó lắm.
  • Login Screen hỗ trợ các giao diện được thiết kế bằng HTML nên rất đẹp và bắt mắt.
  • Software Source bây giờ đã chuyên dụng hơn so với trước, chăm chút và cấu hình dành riêng cho Linux Mint. Trong Software Source hỗ trợ đo tốc độ của các server. Khá hữu ích và tiện dụng:
    Lưu ý: Không thì nên dùng server của VietNam khi update và cài đặt gói. Đã có lỗi xung đột về các gói phần mềm ở server này.
  • File Manager bây giờ đã trở nên lung linh lấp lánh ánh sao mai hơn. Có thể thấy nó na ná với cu Windows Explorer của Windows 7
  • Các theme, extension được vứt hết lên mạng. Giúp giảm tài nguyên sử dụng lưu trữ trên máy, đồng thời giúp người dùng có thể cập nhật các phiên bản mới nhất của giao diện.
Hiệu năng luôn là vấn đề mà mình quan tâm. Và thực sự Linux Mint Olivia đã hoàn thành rất tốt. Máy chạy mượt. Hệ thống chạy nên chiếm chỉ khoảng 350MB RAM đối với phiên bản x64. Ngoài ra, Linux Mint cũng đã cấu hình sao cho máy có thể mượt mà hơn. Chính điều này giúp cho Linux Mint xứng đáng trở thành bản distro đáng giá cho người mới sử dụng Linux cũng như các người dùng tầm trung và muốn out-of-the-box trong quá trình cài đặt, cấu hình.
Những việc cần làm sau khi cài đặt Linux Mint:
  • Thực hiện update hệ thống. Đây là 1 điều cần thiết, có nhiều tính năng của Linux Mint bị "giấu" không có trong bản cài đặt. Nhưng khi update sẽ có.
  • System -> Language. Update hệ thống ngôn ngữ, nếu cần thiết thì có thể cài đặt thêm ngôn ngữ ViejtNam và dùng ibus. Trong Synaptic và cài đặt gói ibus-unikey.
  • Cài LibreOffice, cái này có thể dùng Software Manager để dễ cài đặt.
  • Ubuntu Tweak: giúp tinh chỉnh hệ thống
  • Dành cho laptop: kéo dài thời gian dùng pin, giảm nhiệt máy
  • Chmsee: ứng dụng đọc các file chm

Jun 6, 2013

[Tips] Macro, các vấn đề liên quan đến vùng nhớ và quản lí vùng nhớ.



Đang phải cày bừa với đồ án Đồ họa máy tính, nhiệm vụ của mình là viết 1 module để đọc được file WaveFront Obj. Dĩ nhiên là đã xong được các thành phần cơ bản. Link code ở đây Qua lần code tốc độ này, mình rút ra vài điều.

  • Khi dùng macro có nhiều dòng, tuyệt đối không được có dấu space, tab sau đầu \ khi xuống dòng. Nếu có, đôi khi sẽ dính các lỗi rất khó debug. Vì khi sử dụng macro, ta chấp nhận 1 sự thật cay đắng là không debug trực tiếp lên code macro được.
  • Kỹ thuật macro rất tốt cho việc viết các code tổng quát và tránh bị lặp mã. Nhưng như 1 con dao 2 lưỡi, đã chạm đến macro là chạm đến những rắc rối kỹ thuật linh tinh.
  • Trong C/C++ . Điều đau lòng là ta phải trực tiếp quản lí vùng nhớ. Nên máy tính không giúp ta chuyện vùng nhớ đó được alloc (xin cấp vùng nhớ) chưa, được init (khởi gán) chưa. Nên cần có 1 chiến lược code hợp lí. Vì nếu lỗi liên quan đến vùng nhớ, ta khó khoanh vùng được lỗi. Và thường, lỗi chỉ được báo như là lỗi ở code ta giải phóng vùng nhớ. Còn thực tế thì đâu đó xa vời trong các hàm ta làm
  • Quản lí code tốt sẽ giúp debug tốt hơn. Và điều quan trọng là: điều không thể thì chắc chắn nó không xảy ra rồi. Đừng ngồi đó mà loay hoay tìm hiểu. Nếu có gì đó lỗi ở lệnh int a = 1+1; thì đó không phải là lỗi của người lập trình.
  • Đôi khi, giải pháp nằm ngay trước mắt. Vấn đề là do ta đã không chịu đọc kỹ tài liệu

Jun 2, 2013

Mở chuyên mục mới

Một chuyên mục mới mang tên Tips and Tricks sẽ được mở. Nơi đây sẽ chưa các mẹo vặt và thủ thuật lập trình, sử dụng HĐH Linux, Windows cũng như giải quyết những vấn đề *lặt vặt* khi sử dụng máy tính.

May 20, 2013

Dẫn nhập đầu tiên về Prolog và swi-Prolog.

Các ví dụ và hướng dẫn trong blog này sử dụng swi-prolog. Có thể tải phiên bản mới nhất ở đây. Bài này giới thiệu sơ lược về Prolog và trình thông dịch swi-prolog.

Prolog là một ngôn ngữ lập trình logic, khá với các ngôn ngữ C/C++ là lập trình thủ tục, Haskell lập trình hàm, và Java/C# là lập trình hướng đối tượng. Mô hình của Prolog là lập trình logic. Chính vì vậy, Prolog được giảng dạy và nghiên cứu chủ yếu ở các mảng liên quan đến khoa học máy tính, phục vụ cho trí tuệ nhân tạoxử lý ngôn ngữ tự nhiên.

Về nguồn gốc của Prolog. Cái tên xuất phát từ tên tiếng Pháp: Programmation en logique. Được Alain Colmerauer giới thiệu vào những năm 1970. Đây cũng chính là một trong những ngôn ngũ lập trình logic đầu tiên của thế giới.

Sử dụng SWI-Prolog

Bàn qua một chút về Prolog. Vì là ngôn ngữ lập trình logic, Prolog gồm có 2 phần: 1 phần qui định các mệnh đề và các luật (facts and rules). Và một phần dùng để truy vấn (query ) từ các tập mệnh đề và luật đã được định nghĩa trước đó.
Phần mở rộng của phần swi-prolog là .pl (lưu ý: ngôn ngữ Perl cũng có phần mở rộng tương tự).

Đối với môi trường Windows. Tạm thời tham khảo link sau.
Đối với môi trường Linux. Ta viết các luật ở file xx.pl. Sau đó dùng terminal mở chương trình swipl lên, lưu ý là mở ngay chỗ file xx.pl đã được viết. Sau đó dùng lệnh sau để load các luật.
[tên file không chứa phần mở rộng]
Ví dụ:
[xx]
Sau khi load xong các luật, ta có thể dùng các truy vấn một cách thuận tiện.

Ví dụ

Trong file laptop.pl:
laptop(aa).
laptop(bb).
laptop(cc).

Sau khi lưu xong, ta mở swipl và gõ lệnh:
[laptop].
laptop(aa).
laptop(dd).
Nếu sau lệnh laptop(aa). trả về truelaptop(dd). trả về False thì coi như thành công. Mặc xác ta không hiểu nó là cái chi chi :)).

Tản mạn đêm khuya

Đúng lý ra lúc này mình phải đăng giặt áo quần, làm bài cơ sở dữ liệu và viết lại phần About me phiên bản Tiếng Anh. Nhưng tạm thời xõa hết các công việc đó để dành cho tâm trí vài phút suy tư.

Không, đúng ra là cái đầu đang quay cuồng cuồng bởi những suy nghĩ mông lung vớ vẩn, công việc, deadline, tương lai, sở thích, đam mê, thời gian... Chao ôi, hầm bà lằng các thứ, hầm bà lằng các suy nghĩ. Nhưng có lẽ đêm nay thôi, mình sẽ đem đi mổ xẻ và giải quyết tất tần tật để khỏi phải bận tâm nữa.

Đối với các *deadlines ngắn hạn*. Mình đã mần xong đồ án 2 môn Mạng máy tính (chu choa, vỗ tay). Deadline CSDL coi như xong, mình xõa cái này vậy, để dành sức cho 20% điểm ngày mai. Coi như đã xong, không bận tâm. Đồ án Prolog sẽ được mần vào ngày mai với những dòng Hello world bên em ý. Thứ 3 sẽ bàn về bài toán, code thử chơi, blah blah. Đồ án cuối kì môn NM Công nghệ phần mềm sẽ được mần vào cuối tuần này.

Có nên mua điện thoại mới không nhỉ? Mẹ đã cho mua Lumia 520, mình cũng chỉ cần thế. Nhưng cứ thấy sao sao. Thôi, tạm gác qua. Đúng là mình thích em ý thật, nhưng cảm giác là mình sẽ không dùng hết công suất của em ý. Smartphone với mình là 1 thứ gì đó xa xỉ, tới bây giờ vẫn vậy. Trong thâm tâm muốn mua, nhưng lại thấy tốn kém. Mình có lo lắng quá không?

Đại khái, để hạ màn cái trò Lumia này, mình sẽ quyết định như sau: mình *sẽ mua* và lên kế hoạch mua *khi và chỉ khi (iff) có thông báo học bổng kì vừa rồi*. Xem như là 1 phần thưởng, vừa xem như là tự mình mua, không mang cảm giác tội lỗi lắm.

Giờ là lúc quên em Lumia đi.

Đến kì thi cuối kì. Và bắt đầu từ tuần này sẽ là thời kì ôn tập: được chừng nào hay chừng đó. Tuần này chơi theo chiến thuật tùy cơ ứng biến: hôm nào học môn nào thì ôn môn đó, chỉ ôn những phần vừa mới học xong. Hiểu hay không cũng phải ôn. Tuần sau nữa mới ôn từ gốc lên. Không thể để cái tình trạng cái đầu không biết tí gì về kiến thức được. Phải làm, và phải học bài.
Tạm thời là thế. Cứ phải ôn. Deadline thì deadline, nhưng giờ môn nào thì ráng ôn phần môn đó. Được nhiêu phần trăm không quan trọng, quan trọng là có cái đà để tuần tới có thể tiến hành ôn tập thật kỹ.

À, còn về vụ ngôn ngữ lập trình.

Mình khoái cái này: mỗi mô hình lập trình có 1 tư duy khác nhau. Biết nhiều ngôn ngữ khác sẽ giúp khả năng mở rộng tư duy cao. Nhưng không thể tránh 1 điều là hiện nay thời gian của mình *quá ít*. Và ngậm ngùi không thể học ngôn ngữ nào mình thích được.
C/C mãi mãi là 2 ngôn ngữ mình quan tâm bậc nhất, không thể chối cãi được. Có PHP, Perl, Python, Ruby, Java, C# là thứ khiến mình đau đầu.

PHP có lẽ phải biết. Ít ra phải master nó tí. Nền tảng trên PHP còn trụ rất lâu nữa. Và có lẽ mình sẽ kiếm cơm được nhờ bé này. Vậy em này sẽ được tìm hiểu SÂU

Python là 1 ngôn ngữ triển vọng và là của tương lai. Khi hệ thống giáo dục bên Mỹ đã chuyển qua xài Python, cả Google cũng thế. Rồi hiện nay các libs, các framework hỗ trợ rất nhiều. Chính vì thế: mình sẽ học em này

Perl đã già cỗi, thật sự em ý là tư tưởng ảnh hưởng dến nhiều em sau này. Nhưng có lẽ đành kính nhi viễn chi. Khi nào cần dùng đến hệ thống Linux thì mình sẽ xài và sử dụng như 1 cách tham khảo. Không quá chuyên sâu làm gì.

Java và C#. Cá nhân mình thích C# hơn. Nhưng Java có lí do để nó tồn tại. Và nó còn ảnh hưởng đến chuyện nền tảng sau này theo đuổi. .Net thật sự hay ho đấy, nhưng không thể nào ôm và master 2 ngôn ngữ này cùng 1 lúc. Mình chọn C#. Mình cần 1 ngôn ngữ khi cần thiết sẽ là nơi có thể mình phát triển ứng dụng. Đành rằng Android hiện nay khá bá đạo. Nhưng nếu xét ra, thì thị trường PC vẫn còn chỗ đứng, "niche market" trên di động không phải không có. Thành thử ra, ngày xưa mình không có thiện cảm với em Java mấy, nên giờ chắc cũng không có hứng lắm. Nếu bắt buộc dùng Java thì vẫn phải xài thôi, nhưng không thường xuyên và Master.
Cơ mà mình là dân open-source mà ta. Sao lại đi theo C#. Không ở đây là chuyện cơm áo. Cơm áo là C# và sở thích có thể đụng đến Java nếu cần.

Ryby thì dẹp. Bé ý khó chịu, mình sẽ không giành thời gian cho bé. Nếu tương lai có gì sáng sủa. Mà thực tế thì nó đang sáng sủa lắm. Thì mình sẽ nhào vô. Không phải là bây giờ, không phải là 2 năm đại học nữa. Mà là 1 thời điểm khác. Nhiều time hơn.
Ý, còn em JavaScript. Khi nào anh cần thì anh mới gọi em nhé.

Vậy đúng kết ta có 1 mức độ ưu tiên sau: C/C++ > PHP = Python > C# > Perl > Java > JavaScript. Và trong thời gian hiện tại thì chỉ có C/C++, Python và PHP (cu này để duy trì việc cộng tác viên của Khoa học trẻ). Có vậy thôi.

Có 1 vấn đề nữa. Đó là phong cách làm việc. Dạo này tác phong quá tệ, hiệu suất không hề cao. Việc chia nhỏ các công việc khá hiệu quả ở chỗ trông mình lúc nào cũng rảnh rỗi. Nhưng thiệt hại ở chỗ *không lường trước khả năng mất nhiều time cho task đó*. Đó chính là khả năng phân tích rủi ro quá tệ. Chính vì điều này, cộng thêm sự mất tập trung do quá chia nhỏ các task. Nên giờ đây chiến thuật làm việc sẽ khác đi chút.
  • Chọn những công việc bắt buộc phải làm xong và buộc phải xong trước tiên. Đây là điều cần né. Ví dụ như còn 1 ngày nữa nộp bài, còn 1 ngày nữa đi thi mà chưa nhét vô 1 chữ. Ở đây phải dùng tối đa khả năng để làm việc. Không đáng như vậy
  • Các công việc chắc chắn có thể làm được và chắc chắn hoàn thành trong khả năng đã định
  • Các công việc chưa có hướng giải quyết, hoặc tốn nhiều time sẽ được ưu tiên sau. Và sẽ dành nhiều thời gian cho sự tập trung ở đây
  • Những điều vớ vẩn linh tinh thì dẹp đi. Ví dụ: voz, game, xem phim lung tung. Dành những việc này khi nào thực sự có thời gian để đốt chơi
Có những task bắt buộc phải làm, như 1 cách rèn luyện bản thân:
  • Đọc sách mỗi ngày, sách chuyên ngành, sách ngoại văn.
  • Code mỗi ngày. Tính ra mình code quá ít để có thể trở thành 1 Mark, 1 Bill thứ 2
  • Trao dồi Tiếng Anh, đặc biệt là phần nghe.
  • Uốn lưỡi khi nào, suy nghĩ trước khi làm. Bình tĩnh và không có gì phải xoắn cả
Tôn chỉ bây giờ không còn là làm việc theo đam mê nữa. Mà là: *Làm việc, học hành theo trách nhiệm và đam mê*. Có thể ta mệt mỏi, có thể chán chường, có thể đơn độc. Nhưng không được từ bỏ trách nhiệm. Và sau đó, không được từ bỏ đam mê. Khi mọi rào cản về nhiệm vụ phải làm đã qua đi, thời gian dành cho đam mê sẽ trở nên thực sự chất lượng.

Gõ xong mà vẫn chưa buồn ngủ. Và vẫn chưa tìm được cảm hứng để làm việc tiếp.

May 18, 2013

Tùy chỉnh giao diện Dynamic View của Blogspot

Bài viết đang được hoàn thiện

Dynamic View được Blogspot hỗ trợ rất là lâu. Tuy nhiên, sau một thời gian dài không đụng đến em ý. Giờ đây, mình lại thấy sự tiện dụng và linh hoạt của giao diện này. Dưới đây là một số tùy chỉnh hay ho mà mình góp nhặt được. Nó có thể giúp blog trở nên lung linh lấp lánh ánh sao mai

Tất cả các thao tác trên được thực hiện ở phần Mẫu - Tùy Chỉnh - Nâng cao - Thêm CSS

  1. Tùy biến thanh tìm kiếm: Danh sách các kết quả sự hiện trước tiếp, như một combobox ở khung tìm kiếm

    #header input#search {
      -moz-transition: all 0.3s ease-in-out;
      -ms-transition: all 0.3s ease-in-out;
      -o-transition: all 0.3s ease-in-out;
      -webkit-transition: all 0.3s ease-in-out;
      transition: all 0.3s ease-in-out;
    }
    
    #header input#search:focus {
      width: 450px;
    }
    
  2. Xóa hiệu ứng viền, đổ bóng của các ảnh được chèn trên phần nội dung bài blog
    .entry-content img{
    box-shadow: none !important;
    padding: 0px !important;
    border: 0px !important;
    }
    
  3. Tuy biến thanh sidebar bên trái

    #sidebar:hover 
    { 
       width: 350px; 
    } 
    #sidebar 
    { 
      -webkit-transition: width 500ms ease-in; 
      z-index: 99; 
    }
    
  4. Hiện thông tin ngày giờ đăng bài trong phần nội dung

    .sidebar .article .article-header .date, .ss 
    {
      display: block !important;
    }
    
  5. Thêm phần "Read more" vào chế độ hiển thị magazine.
    .magazine .summary:after, .ss{
    content: "Đọc thêm ..." !important;
    color: red !important;
    }
    

May 14, 2013

Hướng dẫn cài đặt Ecipse và Android SDK


Hướng dẫn cài đặt Ecipse và Android SDK

Bài viết đang được hoàn thiện về mặt nội dung.

Cài đặt các công cụ sau:

Bước 1. Lần lượt cài đặt các phần mềm trên trên máy tính. Eclipse chỉ cần giải nén rồi tạo shortcut trên Desktop là xong.Lưu ý: Khởi động lại máy sau khi cài JDK xong.

Bước 2. Cài ADT: Android Development Tools. Bước này làm như sau:

  1. Mở Eclipse, chọn mục Help -> Install New Software.
  2. Trong mục Work with. Dán link sau vào và nhấn Enter:
       https://dl-ssl.google.com/android/eclipse/
      
  3. Click vào mục Developer tools được liệt kê bên dưới. Nhấn Next. Ngồi chờ vì load kha khá lâu. Sau đó Next tiếp và OK cho 1 thông báo warning.
  4. Sau khi cài xong và khởi động lại Eclipse. Nó sẽ yêu cầu reference đến thư mục SDK. Ta sẽ trỏ tới thư mục sdk con khi giải nén Android SDK (Nó có 2 thư mục:eclipse và sdk). Việc cấu hình đường dẫn làm ở Preference -%gt Android. Trong mục Use existing SDKs trong hộp thoại lúc khởi động lại cũng làm tương tự
  5. Next, sau đó tick Yes/No tùy ý. Sau đó nhấn Finish

Bước 3.Cài đặt nền tảng và các gói lập trình. Trong thư mục đã giải nén của Android SDK. Chạy chương trình SDK manager.exe. Ta chọn version mới nhất: 4.12 và cài các components tùy yêu cầu sử dụng. Tuy nhiên phải có SDK platforms, ARM .... Phần Extra có thể cài thêm Web driver và USB driver. Xong nhấn Install, rồi tick Acpert rồi chờ.

Vậy là xong phần cài đặt, bây giờ ta sẽ tạo thử 1 project Android.

Bước 1. File -> New -> Project -> Android. Chọn Android Application Project .

Bước 2. Cấu hình: thiết lập tên project, các phiên bản Android yêu cầu từ thiết bị. Next, sau đó chọn icon, giao diện, font chữ cho ứng dụng. Sau khi cấu hình xong nhấn Finsh.

Để build thử ứng dụng. Trong Window - > Android Virtual Divices Manager. New để tạo 1 thiết bị giả lập mới. Các thông số như màn hình, RAM, thiết bị blah blah. Xong rồi nhấn OK. Cuối cùng nhấn Start, rồi Launch để chạy chương trình giả lập

Sau khi chạy chương trình xong, ta tạm thời khóa màn hình của thiết bị. Chuyển sang bên Eclipse và click vào biểu tượng Run. Chọn Android Application. Sau đó app của ta sự tự động load lên trên thiết bị giả lập

May 7, 2013

Kiểm tra 1 điểm có nằm trong đa giác lồi không


Đoạn code này khá hữu ích trong đồ họa máy tính, với chức năng kiểm tra xem 1 điểm có nằm trong 1 đa giác lồi hay không. Khá là ngắn và có thể áp dụng rộng rãi. Điển hình như dùng trong kĩ thuật tô màu, chọn 1 đối tượng hình ảnh ...

Chỉ có 7 dòng nhưng chứa đựng tinh túy của thuật toán và kỹ thuật sử dụng ngôn ngữ lập trình

Code nó đây

int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
{
  int i, j, c = 0;
  for (i = 0, j = nvert-1; i < nvert; j = i++) {
    if ( ((verty[i]>testy) != (verty[j]>testy)) &&
     (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
       c = !c;
  }
  return c;
}

Giải thích

  • Danh sách tham số: nvert số đỉnh của đa giác. vertx - mảng chứa tọa độ x của các đỉnh trong đa giác. verty tương tự như vertx nhưng là tọa độ y. testx tọa độ x điểm cần kiểm tra. testy tọa độ y điểm cần kiểm tra
  • Giá trị trả về là kiểu int. 0 là điểm đó nằm ở ngoài, 1 là điểm đó ở trong đa giác

Nguồn: Link đây

May 4, 2013

Lập trình quản lý file trong nachos

Hướng dẫn quản lí tập tin trong nachos

Bài viết đang được hoàn thiện


Đề bài cho đồ án này: Link đây

Các bước để tạo system call đã được đề cập tại : đây . Các bạn có thể tham khảo để nhớ lại

Bước 1. Cấu hình cho bài tập

Đầu tiên ta tìm hiểu sơ về các lớp trong nachos liên quan đến quản lý file.

  • FileSystem. Địa chỉ: filesys/filesys.h. Lớp này để quản lý các hệ thống file. Trong lớp này có các phương thức hỗ trợ việc quản lý bao gồm: tạo, xóa, mở 1 file dựa vào tên file đó
  • OpenFile. Địa chỉ:filesys/openfile.h. Lớp này dùng để thực thi các phép toán (operator) trên 1 file, bao gồm đọc, ghi, lấy độ dài Phương thức Close 1 file chính là destructor của nó luôn.

Hiểu được cái đề.

  • Đề yêu cầu cùng 1 lúc quản lý được 10 file. Tức là đâu đó trong hệ thống phải có 1 cái mảng kiểu OpenFile chứa 10 phần tử. Dĩ nhiên nó không nằm trong exception method, vì nằm ở đó mảng này sẽ bị xóa và khởi tạo lại mỗi lần gọi. Chính xác hơn, ta sẽ đặt nó ở lớp FileSystem ở dạng public (cho dễ cài đặt, để private phải cài thêm cái getter/setter khá khó chịu). Mỗi giá trị của OpenFileID chính là chỉ mục (index) của biến đó trong mảng ta tạo ở trên. Ví dụ mảng đó là openf thì khi mở file openf[3] giá trị trả về của hàm OpenFile sẽ là 3. Và dĩ nhiên, stdinstdoout chính là openf[0]openf[1]
  • 2 bé stdinstdoout được tạo và mở ngay trong constructor của FileSystem, nhờ đó nó luôn luôn tồn tại và không mất đi. Và khi viết systemcall ta chỉ cần kiểm tra index == 0 || index == 1 (chính là cái OpenFileID) là xong
  • Các thao tác đọc, viết, đóng đã có sẵn rồi, ta chỉ cần thêm phương thức Seek vào OpenFile class. Phương thức này được cài đặt bằng lệnh LSeek. Nếu chú ý các phương thức đọc và viết đã được cài sẵn thì có thể dễ dàng cài đặt phương thức này.
  • Về vấn đề console, khi người dùng yêu cầu các file stdinstdout thì ta xử lý riêng rẽ ( 1 lệnh if thôi). Để kiểm tra xem user có gọi 2 file đó không thì chỉ cần check OpenFileID

Cài đặt

  • Lưu ý: trong FileSystem và OpenFile có 2 version riêng cho mỗi lớp, để đảm bảo an toàn, ta cũng cài đặt cả 2 version đó những thay đổi khi làm
  • Project đã chạy được: Link đây

May 3, 2013

Sublime Text 2

Bài viết đang được hoàn thiện

Thực tế khi viết blog này, mình vẫn chưa biết nên chọn ẻm nào. Giống như cuộc chiến text editor war, Notepad++ và Sublime Text 2 là 2 đối thủ cực kì nặng ký

Apr 28, 2013

Phụ thuộc vòng

Bài viết đang được hoàn thiện

Phụ thuộc vòng - một cách dịch đầy thô thiển. Tên chính xác của nó "Circular Dependency". Nghe khá rờm rà. Từ giờ trở đi gọi là CDepend cho gọn. Wiki có hẳn 1 bài về nó: link đây. Đại để có thể hiểu theo ngôn ngữ C++ như sau: File header A dùng để khai báo lớp A, file header B dùng để khai báo lớp B. Trong lớp A có 1 attribute (thuộc tính) là thể hiện của B, và trong lớp B có một thuộc tính là thể hiện của A. Và như vậy, theo lẽ thông thường, Trong file header A sẽ có dòng #include"B.h" và trong file header B có dòng #include"A.h". Mọi sự rắc rối rồi.

Hậu quả:

  • Phát sinh những vấn đề không mong muốn trong quá trình thiết kế lớp. Như ví dụ nêu trên chắc chắn là sẽ chẳng thể cài đặt với thiết kế và giải pháp đó
  • Gây rò rỉ vùng nhớ (memory leak). Vì sao ư? Đối với các ngôn ngữ không có hỗ trợ việc tự dọn rác (automatic memory management), việc tự thiết kế các phương thức hủy (destructor) hay giải phóng vùng nhớ đối với các lớp phụ thuộc lẫn nhau như thế này rất khó chịu. Nếu "lỡ tay" giải phóng hết các thuộc tính trong A, tức là giải phóng luôn có bé thể hiện B trong đó. Mà bé ý vẫn còn đang sống nhăn răng, vẫn chưa muốn bị hủy thì coi như tách. Cài đặt fail và số quá nhọ. Dĩ nhiên, điều "may mắn" là compiler không bao giờ coi đó là syntax error để thông báo ngay từ đầu cả.
  • Gây hiệu ứng domino: một tác động nhỏ lên lớp này ảnh hưởng đến toàn bộ các lớp khác. Theo nguyên tắc thiết kế, các lớp phải độc lập khi sửa chữa. Tức thay đổi của lớp này không ảnh hưởng đến lớp kia.

Một số điểm thuận lợi:

Không phải cái gì xấu, hại thì xấu hoàn toàn. Cái gì nó cũng có 2 mặt của 1 vấn đề. CDepend cũng có một số điểm tích cực

  1. Có những thiết kế bắt buộc phải dính tới CDepend. Và như vậy buộc ta phải cài đặt nó. Ví dụ: danh sách liên kết, đồ thị ...

Giải quyết

  • Có những tool chuyên trị cái này: JDepend (cho Java), Code Analysis Plugin (cho Java).
  • Sử dụng mẫu thiết kế Observer, Visitor, Factory... blah blah

Một số vấn đề trong C++

Phần này sẽ nêu 1 số ví dụ thường gặp, thường dính khi lập trình trên C++

Tài liệu tham khảo:

Hầu hết những gì chém gió phía trên đều được trích lược và tran sờ lai (translate) sang Tiếng Việt. Những nguồn này khá bổ ích

  1. Avoiding Circular Dependencies of header files
  2. Wikipedia
  3. Một bài viết hữu ích trên stackoverflow
  4. Một bài tập nho nhỏ
  5. Có hẳn 1 mục trong stackoverflow

Mẹo nhỏ khi biên dịch chương trình Multithread trên Visual Studio

Mẹo cũng không phải là mẹo, đây chỉ là 1 lần tình cờ phải cài đặt multithread trên ứng dụng. Điều trớ trêu là khi chạy trên chế độ Debug thì khá ngon lành, đến khi chạy trên Release thì tính năng multithread bị tịt hoàn toàn

Và đây là cách giải quyết. Vào Project -> Propertíe (hoặc Alt+F7 cho gọn). Chuyển đến Configuration Properties và lần lượt thực hiện các công việc sau


  • C/C++ -> Optimization. Optimization:Disable. Phần Enable Intrinsic Functions:No


  • C/C++ -> Code Generation. Enable Minimal Rebuild :Yes. Basic Runtime Checks:Both. Runtime Library: Multi-Thread Dll

  • . Enable Function-Level Linking:Yes

Apr 26, 2013

Cấu hình VIM dành cho lập trình viên.


VIM và Emacs trước đây chính là cuộc chiến "editor war" đình đám của giới lập trình. Dĩ nhiên, chuyện gì cũng có nguyên nhân của nó. Với VIM, người dùng sẽ chẳng bao giờ cân đến chuột, những phím chức năng ngoài, tất cả được nằm gọn trong lòng bàn tay, và nhớ đó, số các động tác tay được giảm tối thiểu, thời gian di chuyển giữa các phím của giảm đi. Nhờ đó mà tốc độ code trở nên 1 phần "bá đạo"

Bài viết dưới đây hướng dẫn cách cấu hình VIM trở nên đa dụng, thông minh hơn

Bước 1: Chép dòng code sau vào terminal

curl http://j.mp/spf13-vim3 -L > spf13-vim.sh && sh spf13-vim.sh

Bước 2: Ngồi đợi ...

Bước 3: Vào trang của đồng chí đã tạo ra cấu hình này: link đây . Đọc và nhớ các lệnh của plugin và hướng dẫn sử dụng

Bước 4:Vọc thử vài chức năng và tự sướng vì trình độ typing như hacker của mình

Lưu ý:

  • Đối với Arch LinuxCài vim trước, sau đó cài bộ plugin này, rồi mới cài gVim.
  • Để xóa các file liên quan và cài mới dùng lệnh sau:
    
    sudo rm -r .spf13* spf13* .vim*
    
    

Log : 14/05/2013: plugin Powerline bị lỗi. Đễ khắc phục. Vào file .vimrc.bundles vào để comment trước các dòng liên quan đến plugin powerline.

Apr 14, 2013

Macro nho nhỏ hiện các thông báo.


Trong lúc viết đồ án về Chat Reference, mình gặp chút vấn đề về việc xuất các thông báo cho người dùng. Đồ án được thực hiện trên MFC và dùng hàm MessageBox , trong khi đó, lúc lập trình, mình lại thiết kế các module, tức phần bussiness lại thực hiện trên console, dùng hàm printf. Lúc chuyển qua MFC phải chuyển hết các hàm đó ... Vả lại mỗi lần viết hàm lại 1 lần viết chuỗi xuất ra, thành thử nhiều khi không nhất quán.

Macro này giúp giải quyết vấn đề nho nhỏ đó. Đúng ra thì 1 con trỏ hàm, cũng có thể làm được điều này. Nhưng mình lại thích làm trên macro hơn :)) =)). Một vấn đề trong con trỏ hàm là đôi khi các hàm mình cần dùng không cùng chung kiểu khai báo, và như vậy dùng con trỏ hàm sẽ không ổn. Đồng thời việc biến tấu cũng không được gọn.

#define MAX_BUFERROR 255
#define COMMAND_ERROR printf
#define NEWEXCEPTION(mess, code) { \
                        char err[MAX_BUFERROR]; \
                        sprintf(err,mess". CODE: %d.\n", code);\
                        COMMAND_ERROR (err);\
                        fflush(NULL);\
                        }

Chút chú thích cho cái này xíu:

  • MAX_BUFERROR: Độ dài chuỗi tối đã của thông báo
  • COMMAND_ERROR: Tên hàm thực hiện xuất ra chuỗi
  • Yêu cầu phải có thư viện stdio.h cho macro này

Apr 11, 2013

iTools: Phần mềm quản lí iPhone và các thiết bị Apple

Trong một ngày đẹp trời ngồi tìm cách chép nhạc, phim, video và tùy chỉnh các thông tin trên iPhone, mình đã tìm được phần mềm này. Cứu cánh cho các vấn đề nan giải.

Chép nhạc, phim, video sang Iphone

Ưu điểm

  1. Dễ sử dụng, miễn phí và thân thiện với người dùng
  2. Hỗ trợ đầy đủ các tính năng, cập nhật các phiên bản mới của Apple
  3. Quản lí app, file hệ thống, thông tin, các tập tin đa phương tiện dễ dàng và tiện dụng, không cần phải kết nối ITunes
  4. Chép nhạc, phim, video, cũng như xóa các tập tin này trong iPhone một cách dễ dàng và tiện dụng
  5. Tương thích với nhiều phiên bản Windows: Windows 7, Windows 8..

Lưu ý: Phần mềm yêu cầu phải có iTunes cài trong máy. Khi kết nối sẽ tự động sync với thiết bị mà không bị mất dữ liệu.

Download here

Apr 5, 2013

Hàm strtok và những rắc rối xung quanh


Thật bất ngờ và tình cờ vì phải đụng đến em này lúc train thi Thách Thức. Và cũng tò mò là vì sao em này có cách dùng lạ đến vậy. Nhưng trước tiên là một số thông tin hấp dẫn đã.

Cú pháp:


char* strtok ( char *str, const char *delimters); 
 
 

Công dụng: Tách chuỗi str thành các chuỗi con. Các kí tự ngăn cách được định nghĩa trong chuỗi delimters.

Tham số:

  • str: chuỗi cần tách.
  • delimters: chuỗi chứ các kí tự ngăn cách

Các sử dụng: để lấy từ phẩn từ sau khi được cắt bị kí tự phân chia. Ta sử dụng đoạn code sau:

pch = strtok (str," ,.-");
while (pch != NULL)
{
  // Phần tử lấy ra là pch pch
  // Xử lý các thao tác trên pch
 pch = strtok (NULL, " ,.-");
}
return 0;

Nhiều người sẽ thắc mắc: đoạn mã strtok(NULL, " ,.-") nghĩa là gì. Nguyên nhân là trong hàm strtok sẽ tạo 1 biến static là char* - ta tạm gọi là last. Ban đầu nó sẽ được gắn bằng NULL. Sau lần duyệt đầu tiên, last sẽ có giá trị là địa chỉ hiện thời của phần tử đã lấy được. Khi chạy đến hàm strtok thứ 2 nó kiểm tra tham số đầu vào có phải là NULL không. Nếu phải thì nó lấy địa chỉ của chuỗi đem cắt gắn bằng giá trị mà last đang giữ.

Tham khảo:

  1. Source code hàm strtok của Microsoft
  2. Source code hàm strtok của Apple.

Lưu ý: vì hàm này tạo 1 biến static tạm để giữ giá trị vừa cắt nên không dùng được cho xử lý đa nhiệm.

Mar 31, 2013

Lập trình syscall trên nachos

Trong file hướng dẫn của thầy không thực sự cụ thể, và như vậy rất khó cho mọi người thực hành theo, vậy mình sẽ viết lại các qui trình một chút_
Một chút tìm hiểu về quá trình thực thi 1 hàm
Qui trình thực thi các interrupt sẽ được đề cập sau
  1. Xây dựng trong kernel space
    Để xác định user đang gọi cái interrupt nào. Ta cho nó 1 định danh là 1 số nào đó. Khi kernel nhận được số đó thì hiểu là user yêu cầu chuyện gì.
    Ví dụ: Nếu user đưa vô số 11 tức là yêu cầu đọc 1 số nguyên từ console.
  2. Tạo macro:
    Để đỡ phải quên trong việc lập trình, ta sẽ define số đó thành 1 macro.
    Trong syscall.h:
    define SC_ReadInt 11
    Khai báo interface cho end-user:
    Cũng trong syscall.h, ta tạo một hàm để người dùng (end-user) giao tiếp với hệ điều hành, ở đây ta khai báo hàm ReadInt();
    int ReadInt();

    Định nghĩa hàm trong file assembler.
    Khi người dùng gửi đến 1 thông điệp, ví dụ như “đọc 1 số từ console”, đến với hệ điều hành – lúc này hiểu thông điệp là 11 chẳng hạn. Để hệ điều hành nhận được số 11 đó và truyền đến chỗ xử lý các thông điệp, ta cần pass giá trị này qua. Giống như gọi 1 hàm xxx(11) vậy. Trong nachos, công việc này tức là truyền 11 vào biến $2 được qui định trước đó và gọi system call.

    Ta mở các file sau: code/test/start.ccode/test/start.s:
    .globl ReadInt
    .ent ReadInt
    ReadInt:
        addiu $2, $0, SC_ReadInt
        syscall
        j $31
        .end ReadInt
    

    Như vậy, thông điệp “đọc 1 số từ console” đã đến tai hệ điều hành. Giờ là lúc bắt tay vào xử lý công việc đó. Và vì đây là software interrupts, hay còn gọi là 1 exceptions. Nên dĩ nhiên, ta sẽ thêm mã vào file usrprog/exceptions.cc
    ///....
    switch(which)
    {
        case SystemcallException:
            switch(type)
            {
                case SC_ReadInt:
                // Đoạn mã thực thi
                break;
                // Các xử lý khác ...
            }
            / Tăng biến pc lên 1 đơn vị
            machine->Registers[PrevPCReg] = machine->Registers[PCReg];
            machine->Registers[PCReg] = machine->Registers[NextPCReg];
            machine->Registers[NextPCReg] += 4;  
    }
    ///....
    
    
  3. Một số lớp và phương thức được thêm vào trong đồ án:
    1. SynchConsole
      Được cài đặt ở thư mục threads/ giúp truy xuất giữa console và người dùng.
      Trong file threads/system.h, phần định nghĩa macro USER_PROGRAM ta include header file của SynchConsole. Đồng thời khai báo extern cho biến gSynchConsole;
      $ifdef USER_PROGRAM
      #include "synchcons.h"
      extern SynchConsole *gSynchConsole;
      #endif
      Trong file threads/system.cc, cũng trong phần khai báo macro USER_PROGRAM ta khai báo biến gSynchConsole (chỉ khai báo, không có khóa extern).
    2. User2System và System2User

      Mã code của 2 phương thức này được trình bày ở link này: Click vào đây

      Hai hàm này sẽ trở thành phương thức public trong lớp Machine. Khai báo hàm nằm ở machine/machine.h và phần định nghĩa sẽ nằm ở machine/machine.cc hoặc có thể là trong translate.cc. Mình nghĩ là nên đặt vào trong translate.cc hơn, vì nó phần nào thể hiện bản chất: các phương thức liên quan đến vùng nhớ sẽ được đặt ở đó.
  4. Test hàm và chạy thử nghiệm
    Trong thư mục test/, ta tạo một tập tin .c để kiểm tra tính đúng đắn của exception vừa viết. Đó là gọi hàm đó theo tham số đã đề xuất.
    Cấu hình Makefile:
    Để có thể sử dụng lớp SynchConsole, ta mở file Makefile.common và thêm các thông số sau:
    • Tại THREAD_H : ‘../threads/synchcons.h’
    • Tại THREAD_C : ‘../threads/synchcons.cc’
    • Tại THREAD_O : ‘../threads/synchcons.o’
      Cấu hình file test
      Ví dụ ta muốn chạy đoạn mã test.c, qui trình biên dịch và chạy như sau:
    • Trong file test/Makefile:
      all: ... test
      Thêm vào cuối file
      test.o: test.c
          $(CC) $(CFLAGS) -c test.c
      test: test.o test.o
          $(LD) $(LDFLAGS) start.o test.o -o test.coff
          ../bin/coff2noff test.coff test
      
      

      Sau khi make xong, ta chạy lệnh ./usrprog/nachos -rs 1023 -x [Đường dẫn đến file thực thi].

Mar 2, 2013

Cấu hình giao diện cho Eclipse trên Linux

Trong Linux, giao diện của Eclipse có phần bất tiện vì khoảng trắng giữa các icon khá lớn, khiến cho không gian trở nên nhỏ đi. Điều đó gây ra sự bất tiện lớn khi làm việc


Giải pháp cho vấn đề đó như sau:
  • Trong thư mục ~/ mở file .gtkrc-2.0 và chép đoạn mã sau:
    style "gtkcompact" {
     font_name="Sans 8"
     GtkButton::default_border={0,0,0,0}
     GtkButton::default_outside_border={0,0,0,0}
     GtkButtonBox::child_min_width=0
     GtkButtonBox::child_min_heigth=0
     GtkButtonBox::child_internal_pad_x=0
     GtkButtonBox::child_internal_pad_y=0
     GtkMenu::vertical-padding=1
     GtkMenuBar::internal_padding=0
     GtkMenuItem::horizontal_padding=4
     GtkToolbar::internal-padding=0
     GtkToolbar::space-size=0
     GtkOptionMenu::indicator_size=0
     GtkOptionMenu::indicator_spacing=0
     GtkPaned::handle_size=4
     GtkRange::trough_border=0
     GtkRange::stepper_spacing=0
     GtkScale::value_spacing=0
     GtkScrolledWindow::scrollbar_spacing=0
     GtkExpander::expander_size=10
     GtkExpander::expander_spacing=0
     GtkTreeView::vertical-separator=0
     GtkTreeView::horizontal-separator=0
     GtkTreeView::expander-size=8
     GtkTreeView::fixed-height-mode=TRUE
     GtkWidget::focus_padding=0
     }
    class "GtkWidget" style "gtkcompact"
    style "gtkcompactextra" {
     xthickness=0
     ythickness=0
    }
    class "GtkButton" style "gtkcompactextra"
    class "GtkToolbar" style "gtkcompactextra"
    class "GtkPaned" style "gtkcompactextra"
    
  • Lưu file này lại và mở lại Eclipse. Lưu ý: Các chương trình khác dùng giao diện gtk cũng bị ảnh hưởng
Kết quả thu được:

Về vấn đề autocomplete không hoạt động.Giải quyết: Nhấn Alt + W + P. Chọn C/C++ - Editor - Content Assist -- Advanced và tick chọn hết. Về vấn đề tooltip bị nền màu đen hoặc khung Proposals không nhìn được: chọn giao diện hệ thống khác ( gtk theme), hoặc phải cấu hình lại giao diện đó