Xin hỏi có thể tìm hiểu thuật toán giải hệ phương trình bậc nhất n ẩn số ở đâu?

Xin hỏi có thể tìm hiểu thuật toán giải hệ phương trình bậc nhất n ẩn số ở đâu Bạn có thể tìm hiểu giải thuật giải hệ phương trình bậc nhất n ẩn số trong các sách giáo trình môn đại số của các trường đại học kỹ thuật. Bạn cũng có thể tìm source code (bằng Pascal, C++...) miêu tả giải thuật giải hệ phương trình n ẩn số trên Internet. Tôi lập trình bằng Delphi 6, có sử dụng các hàm trong thư viện liên kết động (*.dll). Tôi muốn hỏi về 2 phương pháp gọi hàm động và tĩnh trong thư viện *.dll. 1. Nếu dùng phương pháp tĩnh thì phải khai báo tất cả các hàm sau đó mới dùng được nhưng rất tốn bộ nhớ. 2. Nếu dùng phương pháp động thì dùng hàm nào? nếu mở thư viện *.dll và sử dụng các hàm sau đó kết thúc chương trình mới đóng lại thì có tốn bộ nhớ như phương pháp tĩnh không? 3. Liệu có thể kết hợp cả 2 phương pháp cùng 1 lúc được không? 4. Xin hướng dẫn lập trình điều khiển thiết bị trong WinXP bằng thư viện *.dll.
tran van hai
tran van hai
Trả lời 15 năm trước
Có 2 phương pháp liên kết code của chương trình ứng dụng với code của các hàm thư viện mà nó dùng: đó là phương pháp liên kết tĩnh và phương pháp liên kết động (hay còn gọi là liên kết muộn tại thời điểm chạy). 1. Trong phương pháp liên kết tĩnh, tại thời điểm dịch và liên kết chương trình, code của các hàm thư viện sẽ được trích ra từ file thư viện và được chèn trực tiếp vào file chương trình (y như do người dùng viết chúng vậy). Sau đó các lệnh gọi hàm thư viện trong chương trình ứng dụng sẽ được hiệu chỉnh lại để thể hiện sự gọi trực tiếp các hàm thư viện này (lúc này nằm cục bộ trong file chương trình ứng dụng). Ưu điểm của phương pháp này là tính đơn giản, dễ hiểu, nhưng phương pháp này có khá nhiều khuyết điểm làm nó không được dùng trong các môi trường hiện đại: • Làm dung lượng chương trình lớn lên 1 cách không cần thiết vì có thể có nhiều hàm thư viện được nhân bản và được để vào file chương trình nhưng trong nhiều lần chạy chương trình, các hàm thư viện không được gọi lần nào (do luồng thi hành chương trình không đi qua đoạn code chứa lời gọi hàm thư viện). • Lãng phí tài nguyên bộ nhớ ngoài (đĩa) và bộ nhớ trong (RAM) vì đoạn code của hàm thư viện đã bị nhân bản từ file thư viện và được đặt trực tiếp trong n file phần mềm có gọi hàm đó, nếu số lượng n file này là lớn thì sự lãng phí về dung lượng đĩa (để chứa n file chương trình) và dung lượng RAM (để chạy các chương trình này đồng thời) càng lớn. • Hành vi của chương trình ứng dụng không thay đổi động khi các hàm thư viện mà nó gọi đã được nâng cấp. Thật vậy, khi file thư viện đã được nâng cấp ta phải dịch và liên kết chương trình với file thư viện mới, nếu không, ứng dụng vẫn gọi version cũ của hàm thư viện chứ không phải version hiện hành của file thư viện. 2. Trong phương pháp liên kết động, lệnh gọi hàm thư viện trong file chương trình chưa được liên kết với hàm tại thời điểm dịch. Khi chương trình chạy, mỗi khi cần phải thực thi 1 lệnh gọi hàm thư viện, hệ thống mới dừng lại, xác định file thư viện nào và nếu nó chưa được nạp vào bộ nhớ trước đó thì hệ thống sẽ nạp vào (nhưng thường được để trong không gian bộ nhớ dùng chung để có thể "share" cho nhiều chương trình gọi nó). Sau khi đã nạp file thư viện vào bộ nhớ, hệ thống mới liên kết lời gọi hàm thư viện với hàm đó rồi cho chương trình chạy tiếp. Với cách làm này, sự liên kết giữa lời gọi và hàm thư viện chỉ xảy ra 1 lần, lần đầu tiên lệnh gọi hàm được chạy. Phương pháp liên kết động có rất nhiều ưu điểm nên được sử dụng chủ yếu trong các môi trường hiện nay như Windows, Linux... Trên Windows, việc liên kết lời gọi hàm với hàm thư viện có thể được thực hiện tường minh bởi người lập trình tại vị trí xác định trong chương trình với đoạn code "template" như sau: //định nghĩa biến pointer đến hàm thư viện typedef int FAR (*ATMBEGINFCHANGE)(void); ATMBEGINFCHANGE ATMBeginFontChange, ATMEndFontChange; //load file thư viện chứa hàm cần gọi vào bộ nhớ dùng chung hATMLIB = LoadLibrary((LPCSTR)"atmlib.dll") ; if (hATMLIB == NULL) MessageBox(NULL,"Load atmlib.dll Error","Error",MB_OK ); //xác định địa chỉ đầu của hàm thư viện cần gọi ATMBeginFontChange = (ATMBEGINFCHANGE)GetProcAddress(hATMLIB, "ATMBeginFontChange"); if (ATMBeginFontChange == NULL) MessageBox(NULL,"Khong the tim ham ATMBeginFontChange","Error",MB_OK); ... //khi cần, gọi hàm thông qua biến pointer ATMBeginFontChange(); Đoạn code thực hiện liên kết động 1 cách tường minh như trên khá rườm rà, một mặt gây khó khăn cho người viết, mặt khác gây khó khăn cho người đọc lại đoạn code để hiểu nó. Chính vì vậy, khi dịch file thư viện, các tool biên dịch và liên kết trên Windows như Borland C++, VC++, ... luôn tạo ra 2 file thư viện khác nhau: • file *.dll chứa các hàm thư viện đã được dịch. • file *.lib chứa các đoạn code thực hiện liên kết động cho từng hàm thư viện (giống như đoạn code trên). Khi dịch và liên kết chương trình ứng dụng, chương trình liên kết sẽ dịch lời gọi hàm thư viện thành lời gọi hàm tương ứng trong file *.lib và hàm này thực hiện liên kết động với hàm thư viện. Ở đây bạn cần lưu ý là chương trình dịch dùng phương pháp liên kết tĩnh với đoạn code trong file *.lib, chỉ có đoạn code này mới thực hiện liên kết động với hàm trong file *.dll. Một lưu ý khác là để 1 file source C++ gọi được 1 hàm nằm trong file khác (thường là thư viện), ta phải khai báo trước đặc tả sử dụng hàm cần gọi rồi sau đó mới gọi nó. Lệnh khai báo đặc tả sử dụng 1 hàm sẽ miêu tả tên hàm, danh sách từng tham số, mỗi tham số thuộc kiểu dữ liệu nào, và đặc tả chức năng của hàm đó. Thường các lệnh khai báo đặc tả hàm được để trong file *.h, file source C++ sẽ dùng lệnh "#include" để chèn nội dung file *.h vào file source. Khi dịch, các lệnh khai báo chỉ cung cấp thông tin cho chương trình dịch chứ không được dịch ra mã máy nên không hề tốn bộ nhớ cho chúng. 3. Về nguyên tắc, bạn có thể dùng kết hợp 2 phương pháp liên kết tĩnh và động trong cùng 1 phần mềm. Tuy nhiên thường người ta sẽ chọn dùng 1 phương pháp để đảm bảo tính nhất quán và dễ theo dõi. 4. Chúng tôi đã trả lời vấn đề này trên các số báo trước, xin nhắc lại WinXP có cơ chế bảo vệ tài nguyên rất chặt chẽ, các lệnh trong file ứng dụng không được phép truy xuất trực tiếp các tài nguyên của máy (thí dụ truy xuất các cổng I/O của các card chức năng). Nếu muốn, bạn phải xây dựng 1 device driver theo định dạng của WinXP, device driver này sẽ chứa các đoạn code truy xuất trực tiếp tài nguyên và nó được chạy ở cấp ưu tiên cao nhất như các đoạn code của HĐH. Chi tiết về việc xây dựng device driver được trình bày trong CD DDK (Device Development Kit). Trong VB.NET tôi có khai báo hàm như sau: Private Sub ShowImage(ByVal position As Integer, ByVal index As Integer) Dim a_label As New Label a_label.Name = "lblCell" & position.ToString Nếu index = 0 thì xoá hình khỏi a_label If index = 0 Then a_label.Image = Nothing a_label.Refresh() Else Select Case position Case 0 Or 6 a_label.Image = Image.FromFile("D:\My Documents\My Projects\Visual Studio Projects\O_Quan\Images\quan1" & index.ToString & ".jpg") a_label.Refresh() Case 1 To 5 a_label.Image = Image.FromFile("D:\My Documents\Mư Projects\Visual Studio Projects\O_Quan\Images\" & index.ToString & "r.jpg") a_label.Refresh() Case 7 To 11 a_label.Image = Image.FromFile("D:\My Documents\Mư Projects\Visual Studio Projects\O_Quan\Images\" & index.ToString & "b.jpg") a_label.Refresh() End Select End If a_label.Refresh() a_label.Update() End Sub Các Label lblCellposition đã có sẵn trên form. Nhưng khi chạy chương trình thì hình ảnh trên lblCellposition không có thay đổi gì cả. Xin hỏi có phải khai báo hàm trên sai ở chỗ gán "a_label.Name" không? Xin chỉ cách khắc phục. Đúng, hơn nữa, bạn còn mắc phải 1 số lỗi khác nữa: • lệnh Case 0 Or 6 tương đương với lệnh Case 0 vì kết quả tính biểu thức "0 Or 6" sẽ là 0. Do đó nếu muốn miêu tả 2 trường hợp 0 và 6, bạn nên dùng 2 lệnh "Case 0" và "Case 6" riêng biệt. • Các đoạn code mà bạn thực hiện để thiết lập ảnh bitmap cho các label thực sự chỉ tác động trên đối tượng a_label mà đối tượng này được tạo động bằng chương trình và chưa liên kết với form giao diện. Lưu ý để truy xuất 1 đối tượng giao diện nào đó, bạn phải dùng biến tham khảo đến nó (thí dụ a_label). Bạn có 12 label với tên lần lượt là lblCell0 đến lblCell12, muốn truy xuất label nào, bạn phải dùng đúng tên biến tương ứng, biến này chính là thuộc tính "Name" mà bạn đã thiết lập tại thời điểm thiết kế trực quan. Tóm lại để có thể thay đổi được ảnh bitmap của các label, bạn có thể hiệu chỉnh đoạn code của mình thành: Private Sub ShowImage(ByVal position As Integer, ByVal index As Integer) Dim filename As String Xác định file chứa ảnh cần dùng Select Case position Case 0 filename = "D:\My Documents\My Projects\Visual Studio Projects\O_Quan\Images\quan1" & index.ToString & ".jpg" Case 6 filename = "D:\My Documents\My Projects\Visual Studio Projects\O_Quan\Images\quan1" & index.ToString & ".jpg" Case 1 To 5 filename = "D:\My Documents\Mư Projects\Visual Studio Projects\O_Quan\Images\" & index.ToString & "r.jpg" Case 7 To 11 filename = "D:\My Documents\Mư Projects\Visual Studio Projects\O_Quan\Images\" & index.ToString & "b.jpg" End Select Select Case index Nếu index = 0 thì xóa ảnh khỏi label Case 0 Select Case position Case 0 lblCell0.Image = Nothing Case 1 lblCell1.Image = Nothing Case 2 lblCell2.Image = Nothing ... Case 11 lblCell11.Image = Nothing End Select Nếu index = 1 thì thiết lập ảnh cho label tương ứng Case 1 Select Case position Case 0 lblCell0.Image = Image.FromFile(filename) Case 1 lblCell1.Image = Image.FromFile(filename) Case 2 lblCell2.Image = Image.FromFile(filename) ... Case 11 lblCell11.Image = Image.FromFile(filename) End Select End Select End Sub Cho hỏi trong VB.Net, làm sao để "Extract" một icon từ những file *.exe? Bạn có thể gọi hàm API của Windows tên là ExtractIcon() để đọc icon từ 1 file khả thi nào đó (*.exe, *.dll, *.ocx...). Lưu ý 1 file khả thi có thể chứa nhiều icon khác nhau, mỗi icon được nhận dạng thông qua chỉ số từ 0 đến n. Đoạn code VB .Net sau sẽ đọc icon đầu tiên trong file *.exe (thường đó là icon miêu tả chương trình ứng dụng) rồi hiển thị nó lên ở góc trên trái của form hiện hành : khai báo hàm API cần dùng Private Declare Function ExtractIcon Lib "shell32.dll" Alias "ExtractIconA" (ByVal hInst As Integer, ByVal lpszExeFileName As String, ByVal nIconIndex As Integer) As System.IntPtr khai báo biến quản lý icon Dim hIcon As System.IntPtr Dim ic As Icon đọc icon đầu tiên (chỉ số 0) của file *.exe vào hIcon = ExtractIcon(VB6.GetHInstance.ToInt32, "c:\windows\prog.exe", 0) tạo đối tượng Icon tương ứng ic = Icon.FromHandle(hIcon) hiển thị icon lên góc trên trái của form hiện hành Me.CreateGraphics.DrawIcon(ic, 0, 0) Chúc bạn thành công!