Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 12 kết quả

Đề tài: Kiến thức cơ bản cho lập trình (Tư tưởng để bắt đầu lập trình)

  1. #1
    Ngày gia nhập
    07 2006
    Nơi ở
    Hanoi, Vietnam
    Bài viết
    2,750

    Mặc định Kiến thức cơ bản cho lập trình (Tư tưởng để bắt đầu lập trình)

    1.Giải thuật là gì?

    1 cách cơ bản, có thể coi giải thuật là 1 tập các thủ tục, hàm, cấu trúc điều khiển theo 1 trình tự thực hiện nào đó nhằm thực hiện bài toán được đặt ra cho chương trình. Người ta thường chia ra 2 loại giải thuật cơ bản:

    + Giải thuật xác định: là các loại giải thuật được áp dụng cho những vấn đề mà lời giải có thể biểu diễn được dưới dạng toán học 1 cách rõ ràng. Trong loại giải thuật này các bước để thực hiện, số lần lặp... đã được xác định trước và rất dễ dàng để tính toán chi phí phải bỏ ra cho nó. Và thường thì loại giải thuật này ít khi có chứa cấu trúc điều khiển rẽ nhánh.

    Vd: Vẽ 100 điểm ngẫu nhiên trên màn hình.

    + Giải thuật không xác định: loại giải thuật này áp dụng cho những vấn đề mà lời giải chưa có sẵn mà được lựa chọn qua 1 số lần chọn lựa những khả năng có thể nào đó ở những bước nào đó.

    Vd: Cho 1 hình chữ nhật cụ thể. Vẽ các điểm có giá trị tọa độ x,y được phát sinh ngẫu nhiên cho tới khi điểm ngẫu nhiên nằm ngoài hình chữ nhật thì dừng.

    + Chắc bạn cũng thấy thì trong thực tế, các vấn đề thường nằm dưới dạng bài toán không xác định là chính.

    + Ngoài ra còn 1 loại giải thuật heuristic: nói 1 cách dễ hiểu thì đây là 1 loại giải thuật mang tính "may mắn" rất nhiều. Loại thuật toán này dựa trên 1 thứ "cảm tính" (được trừu tượng hoá thành 1 hàm đánh giá heuristic) nào đó của con người trong việc giải quyết vấn đề. Bạn cảm thấy giải quyết bài toán theo hướng nào là tốt hơn thì đi theo hướng đó. Và nếu "cảm tính" của bạn sai thì bài toán có thể trở thành dài hoặc đi vào lối cụt. Nhưng nếu "cảm tính" của bạn đúng thì bài toán có thể được giải quyết rất nhanh.

    Vd: Cho 1 tập các trạm điện thoại và khoảng các giữa các trạm đã được xác định. Hãy tìm 1 cách nối dây để các trạm được nối với nhau và tốn ít dây nhất. Thì có 1 loại heuristic theo nguyên lí "tham lam" là: chọn ra trong các trạm chưa nối, dây trạm có khoảng cách ngắn nhất tới trạm đang xét. (Thật ra thuật toán này có thể thực hiện được 1 cách tối ưu bằng cách "vét cạn" tất cả các đường dây có thể tạo ra rồi chọn đường ngắn nhất, nhưng trong trường hợp số trạm là quá nhiều thì giải thuật này sẽ không hiệu quả do tốn quá nhiều thời gian, chi phí tính toán, chi phí lưu giữ kết quả...)

    Bài viết được gửi bởi hot_snow
    Email: admin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
    Phone: 0972 89 7667 (Office: 04 6329 2380)
    Yahoo & Skype: dreaminess_world (Vui lòng chỉ rõ mục đích ngay khi liên hệ, cảm ơn!)

    Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó. Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp!

  2. #2
    Ngày gia nhập
    07 2006
    Nơi ở
    Hanoi, Vietnam
    Bài viết
    2,750

    Mặc định Mối liên hệ giữa giải thuật và cấu trúc dữ liệu:

    Như câu "slogan" của Niklaus Wirth mà snow đã nhắc tới, 2 thứ để cấu thành chương trình là Cấu trúc đữ liệu + Giải thuật. Và giải thuật thì hoạt động dựa trên cấu trúc dữ liệu. Như vậy sẽ có 1 sự ảnh hưởng qua lại giữa CTDL mà bạn chọn lựa và thuật toán.

    Nếu ngay từ đầu bạn chọn 1 CTDL "ngon lành", thích hợp thì việc viết giải thuật sẽ rất đơn giản và tốc độ của giải thuật cũng nhanh hơn. Còn nếu bạn chọn lựa 1 CTDL không tốt thì giải thuật của bạn sẽ có thể rất rườm rà và rắc rối, ảnh hưởng tới tốc độ.

    +Cho nên yêu cầu của 1 CTDL trong giải thuật là phải đơn giản, tiết kiệm tài nguyên hệ thống nhưng đầy đủ và biểu diễn được bài toán. Đồng thời những toán tử, những hàm xử lí trên dữ liệu đó phải đảm bảo đơn giản và được thực hiện nhanh chóng. Để làm được điều này đòi hỏi ở người lập trình viên những bước phân tích lúc ban đầu rất quan trọng. Bạn phải hiểu rõ những yêu cầu của đề bài, phải thấy rõ bản chất, cũng như phải biết cách thu gọn, đơn giản hoá bài toán. Cũng như bạn phải biết rõ những thao tác nào sẽ thường xuyên được thực hiện trên CTDL về sau, đây là 1 yêu cầu rất quan trọng để bạn có thể cân nhắc CTDL cho hợp lí. (Điểm này thì thút thật là snow còn phải học hỏi dài dài...)

    Ví dụ: 1 ví dụ đơn giản là bài toán 8 con hậu. Cho 1 bàn cờ vua 8x8. Hãy liệt kê ra tất cả các cách đặt 8 con hậu trên bàn cờ sao cho trên mỗi hàng hoặc mỗi cột của bàn cờ chỉ có duy nhất 1 con hậu mà thôi.

    Phân tích đề bài thì bạn thấy vì bài toán yêu cầu liệt kê tất cả nên chắc chắn nó sẽ được giải bằng phương pháp "vét cạn". Vấn đề còn lại là bạn cần lưu lại kết quả của những lần "vét cạn" như thế nào.

    Ở đây đơn giản nhất ta sẽ nghĩ ngay tới 1 mô hình mô phỏng rất tốt bàn cờ đó là 1 mảng 2 chiều 8x8. Các ô trống ko đặt quân cờ sẽ được đặt giá trị là False (0). Các ô có đặt quân cờ sẽ được đặt giá trị là True (1).

    Nhưng vấn đề là, như vậy mỗi một trường hợp tìm được bạn lại phải lưu nó bằng 1 mảng 2 chiều 8x8 là rất tốn bộ nhớ, thứ 2 là việc duyệt trên 1 mảng 2 chiều sẽ khiến cho thuật giải của bạn trong mỗi lần duyệt kiểm tra sẽ phải tốn chi phí (n*n) làm ảnh hưởng tới tốc độ của bài toán.

    Vậy bạn sẽ phải tìm ra 1 CTDL tốt hơn là mảng 2 chiều đề biểu diễn bài toán này. Nhìn đi nhìn lại tự nhiên bạn thấy "người anh em" của mảng 2 chiều là mảng 1 chiều sao mà "dễ sương" quá à... Vậy là bạn sẽ bắt đầu nghĩ xa hơn 1 chút với mảng 1 chiều và bạn sẽ tìm được 1 cách biểu diển tiết kiệm hơn nhiều.

    Đó là bạn chỉ cần 1 mảng 1 chiều 8 phần tử. Mỗi phần tử của mảng được coi là biểu diễn toạ độ của lần lượt 8 con cờ trên bàn cờ theo qui ước sau: chỉ số của phần tử a[i] sẽ biểu diễn cho toạ độ hàng. Giá trị lưu trong mổi một phần tử sẽ biểu diễn cho toạ độ cột của các con hậu.
    a[3]=5 <=== con hậu trên dòng thứ 3 được đặt trên cột thứ 5.

    Như vậy việc lưu giữ kết quả sẽ được tiết kiệm tài nguyên bộ nhớ hơn và việc duyệt kiểm tra cũng nhanh hơn do chỉ duyệt trên 1 mảng 1 chiều 8 phần tử mà thôi.

    +Ngoài ra như snow đã nói ở bài trên các kiểu dữ liệu càng phức tạp thì các toán tử làm việc trên nó sẽ phức tạp và chậm hơn.

    Vd: khi làm việc với các con số bạn phải hạn chế việc sử dụng kiểu số thực (float) nếu không cần thiết thì bạn nên thay nó bằng kiểu nguyên (integer) nếu có thể...

    Vd: 1 ví dụ khác cho việc chọn kiểu dữ liệu. Chẳng hạn bạn cần xây dựng 1 chương trình quản lí các nhân viên cho 1 công ty nào đó. Các nhân viên có thông tin Tên, Số điện thoại, địa chỉ.

    Nếu bạn chỉ dừng ở đây mà không biết cách tự phát triển tiếp, bạn sẽ ngay lập tức tạo ra 1 cấu trúc như sau (trong C):

    C Code:
    1. struct NhanVien
    2. {
    3.    char Ten[255];
    4.    char DiaChi[255];
    5.    int DT[7]; /* thật ra là có hơi "hoang" như nad đã nói vì int tới 2 byte trong 1 mỗi một số trong số điện thoại chỉ có từ 0 -> 9 tức chưa vượt quá 1 byte. Vậy ta có thể chọn kiểu là char (trong C char còn có thể coi là 1 kiểu số nguyên 1 byte) */
    6. };

    Nhưng sau đó khi bước vào xây dựng các hàm, các chương trình làm việc trực tiếp với CTDL này bạn sẽ thấy ngay ra 1 vấn đề khó khăn. Bạn sẽ thấy thao tác thường xuyên thực hiện trên CTDL NhanVien nhất là tìm kiếm. Nhưng khi tìm kiếm 1 nhân viên bạn sẽ dựa trên khoá là gì?
    Nếu theo như struct mà bạn tạo ở trên thì khoá đó sẽ là Ten. Nhưng bạn cần hiểu 1 điều là Ten vốn có kiểu là chuỗi kí tự string (trong C string được coi là mảng 1 chiều của kiểu kí tự char). Mọi thao tác trên chuỗi kí tự luôn đòi hỏi 1 sự phức tạp và tốn kém. Bao gồm việc so sánh các kí tự, độ dài chuỗi, kết thúc chuỗi, các trường hơp upper case và lower case (kí tự viết hoa hoặc thường, thường thì bạn phải chuyển tất cả kí tự trong 2 chuỗi về cùng là upper case hoặc lowercase trước khi xét)... nói chung sẽ ảnh hưởng rất nhiều đến tốc độ và tên càng dài thì càng chậm (do tên không có kích thước cố định trước...).
    Cũng có vài cải tiến nho nhỏ trong các hàm có thể giúp cho việc tìm kiếm nhanh hơn. Chẳng hạn như đầu tiên bạn so sánh chiều dài 2 chuỗi tên, nếu thấy ko dài bằng nhau thì bỏ qua không cần so sánh... Nhưng bản thân hàm kiểm tra độ dài chuỗi cũng đã mất 1 chi phí O(n) do phải duyệt đếm từ đầu đến cuối chuỗi kí tự để tìm kí tự đặc biệt đánh dấu cho việc kết thúc chuỗi (hoặc lấy địa chỉ kí tự đầu, trừ địa chỉ kí tự cuối rồi chia cho kích thước kiểu kí tự). Theo snow biết ngay cả những ngôn ngữ "sừng sỏ" trong việc xử lí chuỗi hiện nay cũng còn phải "sợ" các chuỗi kí tự mặc dù vẫn chạy tốt nhưng vẫn chậm và ảnh hưởng tới tốc độ chung của chương trình (như SQL trong cơ sở dữ liệu, mặc dù có các hàm xử lí chuỗi rất tốt, nhưng 1 lập trình viên tốt trên SQL luôn tránh né chuyện so sánh các chuỗi có độ dài ko xác định nếu có thể...).

    Tóm lại là bạn thấy việc dùng Ten làm khoá so sánh là điều bất khả thi và chậm. Như vậy bạn phải nghĩ tới chuyện cải tiến lại CTDL của mình 1 tí và bạn nghĩ là bạn phải "thêm thắt" gì đó vào struct ban đầu để cho nó "hay ho" hơn.

    Nếu để ý thì chắc bạn thấy rằng các nhân viên trong 1 công ty ngoài Tên thì thường có thêm 1 thông tin nữa là Mã Số Nhân Viên. Vậy ta có thể có 2 kiểu struct Nhân Viên sau đây (snow sẽ phân tích từng kiểu 1):

    C Code:
    1. struct NhanVien1
    2. {
    3.    char Ten[255];
    4.    char MSNV[10];
    5.    char DiaChi[255];
    6.    int DienThoai[7];
    7. };

    hoặc

    C Code:
    1. struct NhanVien2:
    2. {
    3. char Ten[255];
    4. int MSNV;
    5. char DiaChi[255];
    6. int DienThoai[7];
    7. };
    Chắc bạn dễ dàng nhận thấy sự khác nhau giữa 2 struct trên là 1 cái có MSNV là kiểu chuỗi, 1 cái là kiểu số nguyên. Bây giờ snow nói cụ thể từng kiểu:

    Thấy struct NhanVien1 có MSNV kiểu là string, chắc bạn rủa thầm: "Vớ vẩn quá nha!!! Vậy có khác gì tránh vỏ dưa gặp vỏ dừa đâu, tránh cái Ten kiểu string bằng 1 cái MSNV kiểu string thì có gì khác nhau đâu?".
    Thật ra là có khác nhau đó! Thứ nhất đây là MSNV do bạn tạo ra nên nó phải tuân theo 1 số qui tắc nhập mà bạn buộc cho nó và user buộc phải tuân thủ trong quá trình nhập cũng như tìm kiếm. Các qui tắc đó bao gồm độ dài (mã số gồm bao nhiêu kí tự), tất cả phải là upper case hoặc cùng là lower case, các con số nằm ở vị trí nào, kí tự nằm ở vị trí nào...(khác hẳn với tên vốn không có qui định độ dài, kí tự...)
    Text Code:
    1. Ví dụ:
    2. HA02321
    3. HA03435
    thì các vị trí số và kí tự vốn đã được qui định sẵn như trên.

    Với việc đã có qui tắc nhập vào này thì việc kiểm tra, tìm kiếm của bạn sẽ trở nên dễ dàng hơn và không cần 1 số thủ tục như kiểm tra độ dài chuỗi, chuyển đổi về upper case hay lower case trước khi xét... (Kiểu làm này thì bạn có thể thấy rất nhiều trong cơ sở dữ liệu. Ko phải ngẫu nhiên mà trong các Table thường có cột MãSố dùng làm Primary Key hoặc Foreign Key thay cho Tên và các câu truy vấn SQL)

    Nhưng thật ra làm như vậy vẫn còn "dính dáng" tới chuỗi kí tự nên snow không khoái lắm. Snow thích kiểu struct NhanVien2 hơn. Bạn cho MSNV là 1 con số nguyên, vậy thì việc so sánh tìm kiếm sẽ trở nên nhanh gọn hơn nhiều. Mỗi lần nhập 1 nhân viên mới thì chương trình sẽ tự tìm 1 con số thích hợp rùi gán cho nhân viên đó. Vấn đề chỉ là bạn phải dự đoán được số nhân viên có thể tăng tới bao nhiêu để chọn ra 1 kiểu dữ liệu đủ lớn cho MSNV.

    +Ngoài ra bạn còn phải cân nhắc tới các toán tử làm việc trên dữ liệu (điều này snow đã từng đề cập trước đó). Các toán tử cơ bản do các ngôn ngữ lập trình cung cấp cho bạn vốn có những chi phí thực hiện khác nhau (điều này mang tính chất hệ thống). Nếu chương trình của bạn đòi hỏi có nhiều xử lí và tính toán thì khi sử dụng các toán tử bạn phải cân nhắc sao cho toán tử phải có chi phí "nhẹ" nhàng để tốc độ tính toán nhanh nhất có thể.

    Vd:
    x=y*2+1;

    bạn nên hiểu là trong kiến trúc máy tính có các mạch shift, nhớ giải mã, đảo bit .... là các mạch cơ bản (snow đã đề cập trước đây rùi). Các mạch khác như mạch cộng và mạch nhân chủ yếu được cấu thành từ tổ hợp các mạch cơ bản này, Tức là mạch nhân phức tạp và tốn nhiều chi phí hơn mạch shift (dịch bit).

    Như vậy với ví dụ trên, nếu muốn cho nó nhanh hơn, trong C snow sẽ viết nó lại như sau:

    x=y<<1+1;

    y<<1 tức là dịch giá trị chứa trong biến y sang trái 1 bit, điều này tương đương với nhân y cho 2 (bạn xem mô hình số nhị phân là thấy ngay). Khi đó đoạn lệnh tính toán trên sẽ được thực hiện nhanh hơn.

    Chị hot_snow nói là còn tiếp đó, nhưng mà có thể chị ấy đã phải đi lấy chồng, nên đã 'thau vàng rửa tay', Dreaminess không thấy có bài viết của chị ấy nữa.
    Email: admin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
    Phone: 0972 89 7667 (Office: 04 6329 2380)
    Yahoo & Skype: dreaminess_world (Vui lòng chỉ rõ mục đích ngay khi liên hệ, cảm ơn!)

    Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó. Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp!

  3. #3
    Ngày gia nhập
    07 2006
    Nơi ở
    Hanoi, Vietnam
    Bài viết
    2,750

    Nhưng có một bài khác của một người nào đó đã viết Merge Sort, cũng được lắm đó. Cùng xem nhé:

    Nếu dùng mảng để lưu các con số thì việc lập trình rất dễ và chạy nhanh
    Nếu dùng dạng list thì ta phải bỏ nhiều công sức hơn trong lập trình vì ta chỉ có thể duyệt tuần tự để tìm một vị trí nào đó (mà ở trong pp sort này thì phải tìm vị trí giữa ) --> chạy chậm hơn rất nhiều .

    Còn về việc chọn cột ( thuộc tính ) nào để làm khóa thì có rất nhiều tiêu chí để đánh giá (cái này sẽ kg trình bày rõ ở đây vì khá dài ) và xây dựng khóa như thế nào để nó đạt chuẩn 3 và tránh được những khó khăn trong việc thêm bớt người .
    Chẳng hạn snow nhìn thấy số intger thuận lợi đúng không . Nhưng giả sử ta xây dựng mã số cho một sv như sau
    3 03 44444 ( mã số khoa (số đầu tiên ) , năm ( 2 số kế tiếp ) , mã số của sinh viên (các số còn lại ) )
    Bảng sv có các cột như sau
    MSSV Tên Lớp MSKHOA Năm học
    Khi xây dựng bảng này thì đã có sự phụ thuộc hàm vào một phần
    Những khóa có dạng này sẽ làm cho quan hệ không đạt được chuẩn 3 ( khóa này là khóa thông minh ) ---> sẽ có sự dư thừa dữ liệu (Trong bản thân khóa đã có năm ,MSKhoa ) . Đây là điều nên tránh trong thiết kế CSDL . Nhưng thực tế người ta chấp nhận sự dư thừa dữ liệu vì một số lý do (Chẳng hạn với mã số này thì SV dễ dàng biết được ai học lớp nào khóa nào và thuộc khoa nào )
    Có rất nhiều cái để nói về khóa (ở đây sẽ không trình bày )

    Còn tại sao người ta hạn chế dùng khóa dạng string (VD lấy tên để làm khóa ) vì bên cạnh việc chậm (hẳn nhiên ) thì lý do quan trọng nó là khóa thông minh . Giả sử lấy tên khoa làm khóa đi . Thì khi khoa đó mất đi hoặc đổi tên thì sao ? Chẳng lẽ ta phải thay đổi khóa hay bỏ khóa đó đi trong bảng CSDL . Điều này vi phạm tính chất khóa không đựơc thay đổi ( ta có thể thấy lý do đơn giản là có khóa ngoại . Nếu thay đổi thì phải kiếm trên tất cả các bảng để thay đổi .Công việc không mấy hay ho )

    Còn việc optimize code thì có nhiều mức optimize lắm . VD viết thuật toán thật nhanh . Sau khi đã có thuật toán tối ưu thì ta sẽ tối ưu các lệnh (do trình biên dịch làm , vd như a=b ; b= c ; b không được dùng ở đâu nữa thì khi dịch compiler chỉ cần dịch a = c , hoặc vd a*2 == a << 2) rồi tới mức assembly ( sắp xếp các lệnh move , jump , cmp .... để tránh các hazzard trong lập trình phân bố hoặc tối ưu việc sử dụng các thanh ghi .... ) . Hiện nay việc tối ưu phần thấp , các compiler làm tốt . Chúng ta sẽ không cần quan tâm đến việc a*2 phải chuyển sang a << 2 nữa . Chỉ nên quan tâm đến giải thuật . Mà thậm chí chỉ nên nghĩ đến việc tối ưu giải thuật sau khi đã thiết kế cho giải thuật chạy đã (dù nó chạy củ chuối )
    Email: admin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
    Phone: 0972 89 7667 (Office: 04 6329 2380)
    Yahoo & Skype: dreaminess_world (Vui lòng chỉ rõ mục đích ngay khi liên hệ, cảm ơn!)

    Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó. Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp!

  4. #4
    Ngày gia nhập
    07 2006
    Nơi ở
    Hanoi, Vietnam
    Bài viết
    2,750

    Mặc định Tiến trình trừu tượng của lập trình

    Một loại bài tiếp theo đây được sưu tầm, nhưng tác giả thì không rõ là ai? Hãy cảm ơn những người đã có tư tưởng vì mọi người viết ra những bài viết rất có ích này:

    OOP 1 : Tiến trình trừu tượng của các ngôn ngữ lập trình

    Mọi ngôn ngữ lập trình (NNLT) đều mang một mức độ trừu tượng nhất định. Mức độ phức tạp của mỗi vấn đề/bài toán (cần giải quyết bằng phương pháp lập trình) thực tế phụ thuộc vào mức độ trừu tượng này. Hợp ngữ (assembly) là một sự trừu tượng từ ngôn ngữ máy (mã máy được sinh ra khi ta biên dịch các đoạn code assembly - vốn gồm các từ khóa "gần giống tiếng Anh"). Những NNLT như Fortran, BASIC hay C là một mức độ trừu tượng cao hơn (có cấu trúc) của hợp ngữ. Những NNLT này là sự cải tiến lớn so với hợp ngữ; tuy nhiên ở mức độ trừu tượng của những NNLT này, lập trình viên (LTV) vẫn phải tư duy về cấu trúc máy tính hơn là cấu trúc vấn đề cần giải quyết. Tức là LTV phải thiết lập sự liên hệ giữa mô hình máy tính và mô hình vấn đề thực tế. Điều này đem đến nhiều thách thức trong công việc coding cũng như bảo trì code.

    Thay thế cho việc mô hình hóa máy tính là sự mô hình hóa vấn đề cần giải quyết. Những ngôn ngữ như LISP hay APL đem đến cách nhìn nhận vấn đề từ khía cạnh khác (chẳng hạn như "mọi vấn đề cuối cùng cũng chỉ là những danh sách" hay "mọi vấn đề đều có tính giải thuật"). Tương tự như vậy, PROLOG quan niệm mọi vấn đề là "chuỗi những quyết định". Mỗi ngôn ngữ trên được thiết kế riêng (và là phương án tốt) cho mỗi loại bài toán; tuy nhiên, nếu để giải quyết một loại bài toán có đặc tính cơ bản khác hẳn thì tiêu liền.

    Tiếp cận vấn đề bằng phương pháp lập trình hướng đối tượng (object-oriented programming - OOP) là một bước nhảy vọt trong tư duy lập trình. Lập trình hướng đối tượng là động tác mô hình hóa các thành phần trong miền vấn đề (problem space). Sự mô hình hóa này có tính tổng quát đủ để giải phóng LTV ra khỏi sự ràng buộc về kiểu/loại vấn đề/bài toán. Người ta gọi những thành phần trong miền vấn đề khi được mô hình hóa là những đối tượng (objects). Mỗi đối tượng, tương tự như các đối tượng trong thế giới thực, có những thuộc tính và hành vi riêng của mình. Do phương pháp tư duy OOP rất gần với cách thức tư duy của con người, LTV sẽ được tự do chú trọng vào cấu trúc vấn đề - điều cần giải quyết - hơn là cấu trúc máy. Thực tế, OOP mang đến một mức độ trừu tượng mềm dẻo và mạnh mẽ hơn những cách tiếp cận trước đây.

    Alan Kay rút ra được 5 tính chất cơ bản của SmallTalk – NNLT OO phổ biến đầu tiên, đó là :

    1. Mọi thứ đều là đối tượng (everything is an object). Hãy xem như mỗi đối tượng là một biến đặc biệt. Một đối tượng ngoài việc mang dữ liệu (như các biến thường), còn có thể "được yêu cầu, ra lệnh" từ LTV.
    2. Một chương trình là một lô một lốc các đối tượng có thể "nói chuyện" với nhau bằng cách gửi các thông điệp (a program is a bunch of objects telling each other what to do by sending message). Để "ra lệnh" cho một đối tượng, LTV "gửi một thông điệp" đến đối tượng đó. Cụ thể hơn, một thông điệp cũng giống như một câu gọi hàm (hàm của đối tượng).
    3. Mỗi đối tượng có vùng nhớ riêng được tạo nên từ những đối tượng khác (each object has its own memory made up of other objects). Có thể hiểu là, một đối tượng có thể được cấu thành từ nhiều đối tượng có sẵn khác. Vì vậy, LTV có thể xây dựng một chương trình mà mức độ phức tạp được ẩn giấu sau sự giản dị (dễ dùng) của các đổi tượng.
    4. Mọi đối tượng có một kiểu nhất định (every object has a type). Mỗi đối tượng là một phiên bản của một lớp/kiểu/loại. Ví dụ như đối tượng con Kiki nhà tôi là một phiên bản của lớp chó, hay con Kiki thuộc lớp chó.
    5. Mọi đối tượng cùng kiểu đều có thể nhận cùng thông điệp (all object of a particular type can receive the same messages). Ví dụ như mọi con thuộc lớp chó đều biết cách sủa, con Kiki cũng không ngoại lệ.

    Booch đề xuất một cách mô tả súc tích hơn về đối tượng : Một đối tượng có trạng thái, có hành vi và được định danh (an object has state, behaviour and identity )
    Email: admin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
    Phone: 0972 89 7667 (Office: 04 6329 2380)
    Yahoo & Skype: dreaminess_world (Vui lòng chỉ rõ mục đích ngay khi liên hệ, cảm ơn!)

    Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó. Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp!

  5. #5
    Ngày gia nhập
    07 2006
    Nơi ở
    Hanoi, Vietnam
    Bài viết
    2,750

    Mặc định Giao diện của đối tượng (Interface of object)

    OOP 2 : Giao diện của đối tượng (Interface of object)

    Aristotle chắc hẳn là người đầu tiên nghiên cứu khái niệm type (kiểu); ông đã từng phát biểu về "chủng loài cá và chủng loài chim" (the class of fishes and the class of birds). Ý tưởng "mọi đối tượng, ngoài tính đơn nhất, luôn là một thành phần của một chủng loài, có những tính cách và hành vi chung" đã được áp dụng vào NNLT hướng đối tượng đầu tiên là Simula-67, với từ khóa cơ bản class đã giới thiệu một "kiểu" mới cho LTV.

    Class (lớp) có thể hiểu như là bản mô tả tập hợp những object (đối tượng có những thuộc tính (thành phần dữ liệu) và hành vi (chức năng) như nhau. Một class thực tế là một kiểu dữ liệu đặc biệt mà mỗi biến được khai báo từ đó ngoài việc mang dữ liệu, còn có những chức năng xử lý dữ liệu của bản thân. Cái hay ho là LTV định nghĩa một class (tạo một kiểu dữ liệu mới) để giải quyết vấn đề chứ không bị buộc phải lệ thuộc vào những kiểu dữ liệu có sẵn (được các nhà thiết kế NNLT thiết kế theo đơn vị lưu trữ trên máy tính). LTV có thể mở rộng ngôn ngữ bằng cách định nghĩa thêm các kiểu dữ liệu đặc thù cho vấn đề của riêng mình.

    Một khi LTV định nghĩa thành công một class, LTV có thể tạo bao nhiêu object tùy thích (hmm, dĩ nhiên tớ đang cố ý quên không xét đến những giới hạn của phần cứng), rồi thì tha hồ chơi bời với chúng như thể chúng là những thành phần tồn tại trong vấn đề bạn giải quyết. Thực tế, một trong những thách thức của OOP là công việc thiết lập sự tương quan giữa những object trong phạm vi vấn đề cần giải quyết (bài toán) và những object trong phạm vi giải pháp (giải pháp).

    Làm cách nào "bắt" object hành động ? Chắc chắn phải có một cách nào đó để LTV "ra lệnh" cho object, kêu nó làm cái gi đó; chẳng hạn như với object Form, kêu nó "biến" đi cho khuất mắt hay bắt nó dịch chuyển ra góc màn hình. Mỗi object chỉ có thể hiểu được những "yêu cầu" nhất định, tùy thuộc vào hệ thống class mà nó được sinh ra; ví dụ như với object Dogs thì ta kêu nó "bark" (sủa) được, chứ kêu nó "fly" (bay) thì nó chịu chết (tất nhiên nếu bác LTV nào hứng lên viết cho class Dogs một method fly thì ta sẽ có một loài chó biết bay). Trở lại vấn đề, những yêu cầu có thể đối với một object được định nghĩa bởi giao diện (interface) của nó; và, chính "kiểu" quyết định giao diện này.

    Ví dụ ta đã định nghĩa một class Light với hai chức năng là TurnOn (thực hiện bật đèn) và TurnOff (thực hiện tắt đèn). Cú pháp code giống như C++, tuy nhiên tớ nghĩ dễ hiểu cả với người chưa biết C++.

    C++ Code:
    1. // khai báo một object mylight thuộc class Light
    2. Light mylight = new Light();
    3. // tới đây ta có một cái đèn tên là mylight
    4.  
    5. // bật đèn mylight lên cho sáng
    6. mylight.TurnOn(); // --> đèn sáng
    7.  
    8. // tắt đèn mylight tiết kiệm điện mùa khô
    9. mylight.TurnOff(); // --> đèn tắt

    Giao diện quyết định những yêu cầu nào có thể đưa ra cho một object. Tuy nhiên, rõ ràng là phải có code ở đâu đó được thực hiện khi object nhận yêu cầu. Code này, cùng với những dữ liệu ẩn, là những đặc tả implementation. Với những bạn có kiến thức về lập trình thủ tục (procedural programming), có thể hiểu như là mỗi "kiểu" có những hàm (function) liên đới, tương ứng với mỗi yêu cầu. Khi object nhận được yêu cầu, hàm tương ứng sẽ được gọi. Tiến trình này thường được tổng quát hóa bằng cách mô tả LTV "gửi một thông điệp" (send a message/make a request) đến một object, và object đó biết phải làm gì (execute code) với thông điệp này.
    Trong ví dụ trên, tên của "kiểu"/class là Light, và mylight là tên một object cụ thể thuộc class Light. Bạn có thể thấy rằng, với những object thuộc class Light, những yêu cầu hợp lý có thể là TurnOn (bật), TurnOff (tắt), MakeBrighter (chỉnh sáng), MakeDimmer (chỉnh tối) v.v... Đoạn code Light mylight = new Light() thực hiện việc đăng ký vùng nhớ cho một object kiểu Light, thực hiện khởi tạo object (initialization, sẽ bàn sau) và gán một tham chiếu (reference) tên mylight đến object đó. Để dễ hiểu hơn, bạn hãy tưởng tượng object kiểu Light (chiếm một vùng nhớ trên bộ nhớ) như là một cái đèn xịn, biến tham chiếu mylight như là một cái remote (đèn xịn mà lị). Mỗi khi cần gì, bạn không phải chạy lại chỗ cái đèn mà chỉ cần bấm cái remote mylight là xong. Chính vì tham chiếu mylight đại diện cho object đèn nên có thể nhập nhằng gọi mylight là một object cũng được (ta hiểu là đang nói đến object mà mylight tham chiếu tới). Cú pháp gọi method (phương thức/chức năng/hành vi) ở trên là <tên object>.<tên method>; đoạn code mylight.TurnOn() thực hiện gửi yêu cầu "bật đèn" đến object mylight

    Chú ý: Mặc dù những gì ta làm khi lập trình hướng đối tượng là "tạo những kiểu dữ liệu mới" (create new data types), thực tế mọi ngôn ngữ lập trình hướng đối tượng sử dụng từ khóa "class". Khi bạn đọc từ "kiểu" (type), hãy xem như "lớp" (class); và ngược lại.
    Email: admin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
    Phone: 0972 89 7667 (Office: 04 6329 2380)
    Yahoo & Skype: dreaminess_world (Vui lòng chỉ rõ mục đích ngay khi liên hệ, cảm ơn!)

    Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó. Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp!

  6. #6
    Ngày gia nhập
    07 2006
    Nơi ở
    Hanoi, Vietnam
    Bài viết
    2,750

    Mặc định Kiến thức cơ bản cho lập trình (Tư tưởng để bắt đầu lập trình)

    OOP 2 Service Pack 1 : Review & Relax

    [Khẩu hiệu : Relax today is more important than Review]

    Ôn lại một chút, bạn phân biệt được class và object hay không ? Hy vọng bạn còn nhớ class giống như một bản thiết kế mô tả các tính năng và thông số yêu cầu; còn object chính là sự hiện sinh của bản thiết kế ấy. Với class trong tay, người ta có thể sinh ra bao nhiêu object cũng được (lúc đó object sinh ra được gọi là instance* của class). Các object có tương ứng các thuộc tính/tính chất (properties) và phương thức/hành vi (methods). Một cách ngắn gọn, class là trừu tượng (abstract), còn object là cụ thể (concrete). Sau đây là các ví dụ :

    * instance thường được các dịch giả Ngọc Anh Thư Press (FPT-Aptech đại diện Aptech khởi kiện về việc ăn cắp tác quyền quyển OOP with Java - Aptech) dịch là minh dụ. Tớ thấy ngớ ngẩn làm sao ấy nhưng lại cũng không tìm được từ tiếng Việt thích hợp nên xin phép không dịch từ này.

    1. Các nhà thiết kế ôtô đưa ra một bản thiết kế loại xe LOOF mui trần tuyệt đẹp, nhà sản xuất Tlik dựa trên bản thiết kế ấy xuất xưởng hai chiếc Katrina (màu xanh) và Phoenix (màu đỏ). Nếu như bản thiết kế có mô tả rằng loại xe LOOF này ngoài các chức năng bình thường còn có thể chạy Twin Turbo mode (TTM) thì thề có Chúa, chắc chắn cả Katrina lẫn Phoenix đều chạy được TTM. Dễ thấy, bản thiết kế xe là một class (được đặt tên là LOOF), còn hai chiếc Katrina và Phoenix là 2 objects được sinh ra từ class LOOF, tuân theo những tiêu chuẩn được mô tả bởi mẫu LOOF. Tuy nhiên đừng cho rằng 2 object này giống hệt nhau mà lầm, vì giá trị các thuộc tính của ‘họ’ khác nhau (ví dụ : màu xe).

    2. Chúa sau khi thiết kế (design) class Male và khởi tạo (initialize) một object Adam, đã thiết kế ra một class khác hấp dẫn sinh động hơn nhiều. Người gọi lớp này là Female, và khởi tạo ngay một object Eva. Chúng ta chẳng hơi đâu mà xem xét đến ông Adam lẫn class Malecủa ổng, hãy để sức mà quan tâm đến class Female, cụ thể là bản thiết kế rút gọn sau :

    Text Code:
    1. Class Female
    2. (properties)
    3. Height
    4. Weight
    5. Hair
    6. SkinColor
    7. Mood
    8. VoiceTone
    9. VoiceRange
    10. SensType
    11. ...
    12. (methods)
    13. Scream
    14. Shout
    15. Cry
    16. Moan
    17. Smile
    18. ...
    19. (events - cái này sẽ được nói về sau,nôm na là các biến cố)
    20. BeUnderSunShine
    21. BeCriticized
    22. BeBrokenUp
    23. ...
    24. End Class

    Chúa tạo ra hàng tỷ tỷ phụ nữ trên trái đất, và mỗi phụ nữ dù ở đâu hay thuộc dân tộc gì cũng đều là... phụ nữ (ý tớ là thuộc class Female). Mấy chị châu Phi có property SkinColor = Black trong khi các cô châu Âu có property SkinColor = White. Ca sĩ Ánh Tuyết có property VoiceTone = VeryHigh nên giọng mới cao như vậy. Giả sử cô Hot_snow nhà ta (cũng thuộc class Female) mà rơi vào 'biến cố' bị kick thì event BeBrokenUp sẽ được raise, từ đó có thể phát sinh ra các methods Moan hay Cry tuỳ giá trị property SensType. Nếu các cô các chị đi nắng thì event BeUnderSunShine sẽ được raise lên, dẫn đến kết quả là màu da giảm độ sáng (SkinColor = SkinColor - 1).

    Kết luận : với các objects được sinh ra từ cùng một class thì các tính chất và hành vi tổng thể là như nhau, nhưng được phân biệt bởi các giá trị thuộc tính đặc thù của mỗi object.


    OOP 3 : Hidden Implementation

    [Để đổi không khí và Anh ngữ hoá thuật ngữ, tớ thay LTV bằng programmer nhé. Nghe pro hơn và cũng oai hơn nhiều. Một số thuật ngữ khác xin được phép giữ nguyên, để hỗ trợ cho các bạn trong "công cuộc kháng chiến trường kỳ" với English IT books.]

    Trong thế giới OOP, người ta phân programmers làm 2 nhánh : class creators và client programmers. Vậy class creators là gì ? Đó là mấy cha chuyên lo thiết kế các classes. Còn client programmers chính là mấy người xài những classes do class creators thiết kế. Mục tiêu của client programmers là thu thập những classes hữu dụng để phát triển nhanh ứng dụng cho đề án của họ. Mục tiêu của class creators là thiết kế những classes cung cấp những chức năng cần thiết (trong khi giữ kín những thành phần khác). Những thành phần "ẩn" này là những thành phần tinh tế bên trong mỗi object, sẽ dễ bị sai lạc do những bất cẩn của client programmer nếu như được hiển thị. Vì thế, làm ẩn đi những thành phần thực thi sẽ giảm thiểu program bugs.

    Nếu mọi thành phần của một class được để lộ "trần trùi trụi", client programmer sẽ có thể nghịch tới bến với class đó -> vô phương để áp đặt các quy tắc (bảo vệ) lên class -> cần thiết phải có các nguyên tắc điều khiển truy xuất (access control) cho class.

    Nguyên tắc access control là "cách ly" client programmer khỏi các thành phần "tế nhị" của class. Nè, đừng nghĩ access control sẽ hạn chế sự linh hoạt của client programmer. Chính nó mang lại những nhiều tiện ích cho client programmer bởi nó làm giản đơn việc điều khiển class thông qua một giao diện (lớp bọc) giữa class và client programmer. Những thành phần nào private của class, client programmer sẽ không thể truy xuất đến được. Thử nghĩ về cái TV nhà bạn xem, giao diện của TV là các nút bấm volume +/-, channel +/- v.v... bạn chỉ (cần) thấy mấy cái nút đó là đủ sử dụng TV rồi, đâu cần phải biết các bóng đèn, mạch điện bên trong (hidden/private code/implementation - những thành phần "tế nhị"). Nếu TV nhà bạn không có vỏ (không có access control) thì mấy đứa nhỏ táy máy chọc tay/chân/cây vô nghịch mấy cái mạch thì không những dễ tiêu TV mà cả tụi nhóc cũng thế. -> bảo đảm những nguyên tắc (an toàn) điều khiển class.

    * C++/Java/C# cung cấp các từ khóa cho access control (gọi là access modifiers) như public, protected, private. Ngoài ra còn có friend, internal, protected internal.

    Với access control, nhà thiết kế thư viện có thể thay đổi mã thực thi (thường là sửa lỗi hay cải tiến) trong class mà không làm ảnh hưởng đến công việc của client programmer (vì giao diện class không đổi). Ví dụ nhé : ngoài chiếc Honda Custom 50cc maxspeed 60 kmph, hãng HONDA còn thiết kế loại Honda Custom 70cc maxspeed 90 kmph với vẻ ngoài và cách thức điều khiển xe như nhau. Bạn với các kỹ năng điều khiển xe không thay đổi, có thể chuyển từ HC50 sang HC70 dễ dàng. Điều này giống như sự thay đổi hidden implementation (độ phân khối) mà vẫn không ảnh hưởng client programmer (người sử dụng xe) do giao diện điều khiển là không đổi. -> class creators dễ cải tiến chương trình mà không (mấy) ảnh hưởng đến client programmers.
    Email: admin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
    Phone: 0972 89 7667 (Office: 04 6329 2380)
    Yahoo & Skype: dreaminess_world (Vui lòng chỉ rõ mục đích ngay khi liên hệ, cảm ơn!)

    Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó. Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp!

  7. #7
    Ngày gia nhập
    07 2006
    Nơi ở
    Hanoi, Vietnam
    Bài viết
    2,750

    Mặc định Tái sử dụng mã - Code Reusability

    OOP 4 : Tái sử dụng mã - Code Reusability

    Mỗi class sau khi được thiết kế và kiểm tra (test) cẩn thận được xem như một đơn vị code hữu dụng. Client programmer sử dụng những class này cho các ứng dụng của họ (xài chùa hay mua lại). Như vậy một class được viết ra có thể được dùng lại rất rất nhiều lần ở các ứng dụng khác. Tính "tái dụng mã" (code reusability) là một trong những thế mạnh lớn nhất mà những NNLT hướng đối tượng cung cấp.

    Phương pháp tái dụng mã đơn giản nhất là khởi tạo trực tiếp một object từ class có sẵn. Điều này giống như bạn đi xin (nếu được, nhưng chắc phải mua) bản thiết kế nhà (class có sẵn) của người khác, đem về thiết kế một cái nhà (object) cho riêng mình.

    Cách khác là thiết kế một class cho riêng bạn, mà trong class này sử dụng object của class có sẵn (gọi là tạo object thành viên - member object). Liên hệ ra đời sống : giống như mấy nhà máy sản xuất xe máy ở VN, nguyên cả cái xe máy là của mình thiết kế, nhưng một vài bộ phận khó thì chịu, đến khi sản xuất xe (tạo object) thì mấy bộ phần này phải nhập (object member) -> xe máy VN. Cách này được gọi là composition hay tổng quát hơn là aggregation. Quan hệ giữa class mới và class có sẵn là quan hệ "có"/"has-a" (xe máy VN "có" động cơ Campuchia).

    Composition mang lại sự linh hoạt tuyệt vời. Thường thì các member objects trong class mới sẽ được đặt là private -> vô hình đối với client programmer. Nếu các member objects được thay đổi (thường là được nâng cấp, xảy ra khi class của các member objects được nâng cấp) thì class mới của bạn cũng được hưởng lợi.

    Lập trình hướng đối tượng được đặc trưng bởi một cái... bánh 3 miếng. Không lạ, không lạ đối với những OO programmers, đó là Polymorphism (tính đa hình), Inheritance (tính thừa kế) và Encapsulation (tính đóng gói) -> 3 miếng hợp thành một cái bánh (PIE). Chương này bàn về code reusability nên chúng ta sẽ xem xét miếng Inheritance trước, hai miếng còn lại để dành ăn sau.

    Thừa kế (inheritance) là khái niệm muôn đời quan trọng của lập trình hướng đối tượng. Những nhà lập trình OO tương lai nên luôn tâm niệm rằng, tận dụng được inheritance là các bạn đã có sức mạnh to lớn của OOP. Đương nhiên, cũng như thực tế, được thừa kế, tức không làm mà có xài chơi thì ai mà hổng khoái ? Nhưng, hãy nhớ rằng inheritance ngoài cung cấp khả năng tái dụng mã còn cho phép class creators thiết lập hệ thống cấp bậc cho các class.

    Giả sử Chúa thiết kế được class Horse như sau :

    Text Code:
    1. class Horse
    2. (properties)
    3. ...
    4. (methods)
    5. Gallop
    6. Whinny
    7. ...
    8. end class

    một ngày nọ, Chúa bỗng muốn có một loài ngựa biết bay cho thế giới thêm màu sắc. Nếu như thiết kế lại từ đầu một loài ngựa mới có các tính chất và hành vi như ngựa thường, thêm vào khả năng bay thì quả là tốn nhiều công sức. Thế nên, phương pháp thừa kế được Người sử dụng như sau :

    Text Code:
    1. class Pegasus inherits from Horse
    2. (methods)
    3. Fly
    4. end class

    Với phương pháp này, loài Pegasus này sẽ thừa hưởng tất cả những gì loài Horse có, ngoài ra loài này còn có thêm khả năng riêng là "bay". Class Pegasus được gọi là sub/child/derived/inherited class, còn class Horse được gọi là super/base/parent class. Quan hệ giữa base class và sub class là quan hệ "là"/"is-a". Ta có thể nói một con Thiên Mã (Pegasus) là một con Ngựa (Horse), đơn giản vì nó rút cuộc cũng chỉ là một con ngựa, cho dù nó biết bay.

    Các NNLT hướng đối tượng chạy qua hệ nền trung gian (và có cơ chế lượm rác - Garbage Collector) như Java hay C# (không có OOPL nào là thực sự OO pure) chỉ hỗ trợ thừa kế đơn (tuy nhiên hỗ trợ đa giao diện - multi-interface - sẽ bàn sau). Tức là mỗi sub class chỉ thừa kế trực tiếp từ tối đa một base class mà thôi. Điều này được quy định để hỗ trợ cho cơ chế lượm rác hoạt động, thoạt xem có vẻ như hạn chế công tác lập trình nhưng thực chất là góp phần cho code được sáng sủa. Còn, hic, C++ thì bất chấp, một sub class có thể được thừa kế từ nhiều base class. Một ví dụ đa thừa kế :
    code:

    Text Code:
    1. class Horse (xem phía trên)
    2.  
    3. class Bird
    4. (properties)
    5. ...
    6. (methods)
    7. Fly
    8. Sing
    9. ...
    10. end class
    11.  
    12. class Pegasus inherits from Horse and Bird
    13. end class

    với những gì thừa hưởng từ hai loài Horse và Bird, loài Pegasus có khả năng phi nước đại (gallop), hí (whinny), bay (fly) và thậm chí... hót (sing).
    Email: admin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
    Phone: 0972 89 7667 (Office: 04 6329 2380)
    Yahoo & Skype: dreaminess_world (Vui lòng chỉ rõ mục đích ngay khi liên hệ, cảm ơn!)

    Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó. Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp!

  8. #8
    Ngày gia nhập
    08 2006
    Bài viết
    2

    C Code:
    1. struct NhanVien2:
    2. {
    3.    char Ten[255];
    4.    int MSNV;
    5.    char DiaChi[255];
    6.    int DienThoai[7];
    7. };
    ban viet nhu the thi van ton bo nho qua.nen sua thanh
    C++ Code:
    1. struct NhanVien2:
    2. {
    3.    char Ten[255];
    4.    char DiaChi[255];
    5.    int MSNV;
    6.    int DienThoai[7];
    7. };

  9. #9
    Ngày gia nhập
    11 2007
    Nơi ở
    Biết để làm gì?
    Bài viết
    827

    ủa,chỉ thấy cho int MSNV xuống dười mà giàm được bộ nhớ à?
    Cánh Chym ứ mỏi

  10. #10
    Ngày gia nhập
    07 2006
    Nơi ở
    Hanoi, Vietnam
    Bài viết
    2,750

    sizeof của một struct hoặc union bao gồm cả padding, vì thế, bạn muốn biết giảm hay không bạn có thể sử dụng sizeof để kiểm tra.

    Bài viết đã có thể đưa vào viện bảo tàng tuy nhiên, tư tưởng của bài viết này vẫn còn nhiều giá trị. Kevin lúc mới học cũng chịu ảnh hưởng của bài viết này khá nhiều, nhưng không phải là tất cả.
    Email: admin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
    Phone: 0972 89 7667 (Office: 04 6329 2380)
    Yahoo & Skype: dreaminess_world (Vui lòng chỉ rõ mục đích ngay khi liên hệ, cảm ơn!)

    Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó. Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp!

Các đề tài tương tự

  1. [Kiếm Thế] Kiếm Thế Ngạo Thiên Kiếm Chạy Thử Nghiệm vào 10h ngày 15/09
    Gửi bởi c0jskull trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 5
    Bài viết cuối: 29-09-2013, 10:45 AM
  2. [Kiếm Thế] Kiếm Thế Kiếm Linh Chạy Thử Nghiệm vào 10h ngày 4/7
    Gửi bởi c0jskull trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 1
    Bài viết cuối: 05-07-2013, 12:16 PM
  3. [Kiếm Thế] Kiếm Thế Kiếm Linh Chạy Thử Nghiệm vào 10h ngày 4/7
    Gửi bởi c0jskull trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 0
    Bài viết cuối: 03-07-2013, 10:30 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn