Xem bai viet bang font ABC


   

PCWorld VN

Hỏi: Trong Pascal có cách nào sử dụng bộ nhớ mở rộng được không?

Trả lời: Trong chương trình được viết bằng bất kỳ ngôn ngữ nào, bạn cũng có thể sử dụng bộ nhớ bành trướng EMS (Expanded Memory Specification) và/hoặc bộ nhớ mở rộng XMS (Extented Memory Specification) bằng cách gọi các chức năng của nó thông qua điểm nhập int qui định sẵn. Bạn nên dùng bộ nhớ XMS vì nó hiệu quả hơn EMS, điểm nhập truy xuất dịch vụ XMS là int 2f. Bạn có thể tham khảo bài "Bộ nhớ mở rộng và cách truy cập bộ nhớ mở rộng bằng Turbo Pascal" trên Thế Giới Vi Tính số tháng 6/97, trang 72 để biết thêm chi tiết về cách dùng bộ nhớ XMS.

Hỏi: Trong phần mềm VietRes 2.5 có một chương trình viết bằng Pascal dùng để nạp và bỏ font VietSea cho máy tính. Vậy quí báo có thể viết lại dùm em chương trình trên bằng ngôn ngữ C có được không.

    Em đang học Pascal. Em có thể viết một số chương trình đơn giản mà khi chạy có thể hiển thị các câu thông báo bằng tiếng Việt lên màn hình (Chỉ sử dụng được khi đã chạy VietRes trước). Làm thế nào có thể hiển thị chữ tiếng Việt lên màn hình mà không cần chạy VietRes. Thí dụ như dịch sang tập tin chạy được *.exe. Từ dấu nhắc hệ điều hành đánh tên chương trình thì chạy và hiện tiếng Việt.

Trả lời: Để chương trình của bạn hiển thị được tiếng Việt mà không cần phải có trình VietRes (hay một trình quản lý tiếng Việt khác), bạn cần soạn font tiếng Việt theo bảng mã của bạn, rồi trong chương trình Pascal, trước khi hiển thị văn bản, bạn nạp bản mã của bạn vào hệ thống. Lưu ý khi dừng chương trình, bạn nên nạp lại font chuẩn của máy. Sau đây là một chương trình nhỏ minh họa ý tưởng trên:

Program thu_napfont;

Uses Crt, Dos;

Const vcode: Array[1..4096] of Byte = ($00,....); { baón maọ tiùởng Viùồt cuóa baồn }

Var vmode : Boolean;

{ Thu tuc khoi dong bang ma tieng Viet }

Procedure VietInit;

Var R: Registers;

Begin

if (vmode) then exit;

{ Cai bang ma tieng Viet }

R.ax := $1100;

R.bx := $1000;

R.cx := $0100;

R.dx := 00;

R.es := Seg (vcode);

R.bp := Ofs (vcode);

intr($10,R);

vmode := TRUE;

End;

{ Thu tuc phuc hoi bang ma goc}

Procedure VietClose;

Var R : Registers;

Begin

if (NOT vmode) then exit;

{ Phuc hoi bang ma chuan }

R.ax := 3;

intr($10,R);

vmode := FALSE;

End;

Begin

clrscr;

VietInit;

write (?Thử hiển thị tiếng Việt?); readln;

VietClose;

write (?Thử xem còn hiển thị tiếng Việt không??); readln;

End.

    Nếu bạn cần font cho một bảng mã tiếng Việt nào đó, bạn có thể liên hệ với chúng tôi ở địa chỉ : Nguyễn Văn Hiệp, Khoa CNTT ĐH Kỹ Thuật TP.HCM, ĐT : (8) 865 8689 Ext.500 để sao chép.

Hỏi: Cách dùng Pascal 7.0 để lập trình cho 2 phần làm việc song song nhau? Ví dụ như ta có thể làm việc khác ngay khi một vòng tròn đang di chuyển chẳng hạn. Mong quý báo giải thích và cho ví dụ cụ thể.

Trả lời: Để lập trình song song, bạn cần có thư viện hỗ trợ. Thư viện là module phần mềm chứa nhiều thủ tục để phục vụ một dịch vụ nào đó, thí dụ thư viện đồ họa, thư viện gọi thủ tục từ xa RPC, thư viện multimedia, thư viện quản lý process và thread,... Trên những HĐH đơn chương (như MS-DOS), thư viện hỗ trợ này phải được viết trong không gian của chương trình ứng dụng (như thư viện đồ họa của Borland, ...), còn trên các HĐH đa chương thì thư viện này được tích hợp trong HĐH (như Windows, Unix,...). Tóm lại để lập trình song song, bạn nên lập trình trên HĐH đa chương, trong đó Win9x và Win NT là các đại biểu vì chúng là các HĐH multi-process, multi-thread.

    Lưu ý là bằng giải thuật tuần tự ta có thể tạo ra các ảo giác đồng thời cho người dùng, thí dụ ta có thể lập trình tuần tự để tạo ra các chuyển động của nhiều phần tử đồng thời trong một trò chơi nào đó.

Hỏi: Làm thế nào để hiển thị chuột trong 256 màu chế độ phân giải cao (640 x 480, 800 x 600). Hiển thị chuột đồ họa mhiều màu như trò chơi Warcraft II.

    Xin tạp chí hướng dẫn cho tôi cách viết đoạn chương trình điều khiển mouse. Đoạn chương trình dùng để hiện tọa độẩ cột & dòng của mouse, khi mouse di chuyển trên màn hình đồ họa, và tọa độ này thay đổi mỗi khi mouse di chuyển (giống như các phần mềm xử lý ảnh chạy trong Win). Hiện tại tôi đang lập trình bằng ngôn ngữ C. Tôi đã sử dụng ngắt (0x33) và thanh ghi Ax = 3, giá trị trả về dx, cx chỉ số dòng, số cột của mouse, nhưng khi dùng lệnh cout << dx <<"\t" << cx thì trên màn hình chỉ xuất ra giá trị không đúng với tọa độ mouse và khi mouse di chuyển thì tọa độ đó không thay đổi.

Trả lời: Để dùng mouse trong chế độ đồ họa nào đó trên MSDOS, bạn phải khởi động lại các thông số đúng về độ phân giải màn hình cho driver mouse, sau đó dùng chức năng ah=3 của int 33 mới trả về vị trí đúng của mouse. Bạn phải luôn giám sát trạng thái di chuyển mouse để kịp thời hiển thị tọa độ đúng của nó. Bạn nên tham khảo chương trình thí dụ về điều khiển mouse ở PC World VN số 09/98 trang 115, để biết rõ qui trình cơ bản về điều khiển mouse. Bạn cũng có thể thiết kế lại hình dạng và màu sắc của cursor chuột trong chế độ đồ họa.

Hỏi: Cách lập trình xóa tất cả các file có tên: *.pas, *.cpp... bằng cách sử dụng ngắt Bios (không sử dụng ngắt của DOS). (Tôi đang sử dụng C chạy trong DOS).

Trả lời: Khi lập trình, nếu bạn dùng các dịch vụ càng thấp thì càng khó khăn, phức tạp và chương trình càng khó "portable". Do đó để chương trình có thể chạy trên nhiều version MSDOS khác nhau và trên nhiều máy khác nhau, bạn chỉ nên dùng các dịch vụ từ MSDOS (Int 21h) trở lên, thí dụ như các hàm trong thư viện lập trình của các ngôn ngữ lập trình. Với những máy tính có tốc độ rất cao như hiện nay, vấn đề tốc độ thi hành chương trình (nhất là trên nền MSDOS) hầu như không còn cần phải quan tâm nữa.

    Để xóa tất cả các file thuộc 'pattern' nào đó một cách đệ qui, bạn cần phải có một giải thuật duyệt cây đệ qui để mỗi lần gặp một file bạn sẽ thực hiện thao tác tương ứng. Sau đây là một chương trình nhỏ được viết bằng C có chức năng xóa đệ qui như yêu cầu của bạn :

/*????????????????*/

/* Chuong trinh duyet cay de qui de thuc hien mot tac vu */

/* Nguoi viet : NGUYEN VAN HIEP, TTDT DHBK Tp.HCM */

/* Ngay viet: 10 - 09 - 1991*/

/* Ngon ngu: Borland C++ */

/*?????????????????*/

#include <dos.h>

#include <io.h>

#include <dir.h>

#include <ctype.h>

#include <stdio.h>

typedef void (*PPROC)(char*, char*, struct ffblk);

void xoaphantu(char* drive, char* directory, struct ffblk pblock);

void duyetcay (char *patern, PPROC action);

int fcount = 0; /* so file bi xoa */

int dcount = 0; /* so directory bi xoa */

// Chuong trinh chinh

void main(int argc, char* argv[])

{

int i;

if (argc < 2) {

printf("Hay danh lenh : xoadq <pattern1> ... <patternn> <Enter>\n");

exit(1);

}

for (i = 1; i <argc; i++) duyetcay(argv[i], xoaphantu);

printf("\t\t\tCo %d thu muc va %d file bi xoa.\n",dcount,fcount);

}

/*?????????????????*/

/* Kiem tra file filename co thuoc pattern patname qui dinh khong ? */

/* Tra ve 1 neu thuoc ve, 0 trong truong hop nguoc lai */

/*????????????????*/

thuocve (char *filename, char *fext, char *patname, char *patext)

{

while (*patname && *filename) { // xet tung ky tu trong phan ten

if (*patname == ?*?) goto kiemtraext; // ten thuoc ve

if (*patname == ??? || (toupper(*patname)==toupper(*filename)))

{ patname++; filename++; continue; }

return 0; // ten khong thuoc ve

}

if (*filename == 0 && *patname == ?*?) goto kiemtraext;

if (*patname || *filename) return 0;

kiemtraext:

if (*fext == 0 && patext[0] == ?.? && patext[1] == ?*?) return 1;

while (*patext && *fext) { // xet tung ky tu trong phan noi rong

if (*patext == ?*?) return 1;

if (*patext == ??? || (toupper(*patext)==toupper(*fext)))

{ patext++; fext++; continue; }

return 0;

}

if (*fext == 0 && *patext == ?*?) return 1;

if (*patext || *fext) return 0;

return 1;

}

/*????????????????*/

/* Duyet cay thu muc va thuc hien chuc nang qui dinh */

/*????????????????*/

void duyetcay (char *patern, PPROC action)

{

char drive[4], directory[100], patname[9], patext[5];

char buff[128], filename[9], file_ext[5];

struct ffblk pblock;

int result;

// tach patern ra ca thanh phan

fnsplit(patern, drive, directory, patname, patext);

// xay dung lai patern can duyet

sprintf(buff,"%s%s*.*",drive, directory);

// tim phan tu dau tien thoa man patern

result = findfirst(buff,&pblock, 0xFF);

while (!result) { // con phan tu

// khong xu ly label, thu muc hien tai va cha cua no

if (pblock.ff_name[0] == ?.? || (pblock.ff_attrib & FA_LABEL))

{ result = findnext(&pblock); continue; }

fnsplit(pblock.ff_name, buff, buff, filename, file_ext);

if(pblock.ff_attrib &FA_DIREC) // thu muc

if(thuocve(filename, file_ext, patname, patext))

{

// xoa tat ca phan tu con cua thu muc

sprintf(buff,"%s%s%s\\*.*",drive, directory,pblock.ff_name);

duyetcay(buff,action);

// thuc hien action tren phan tu nay

action(drive,directory,pblock);

}

else

{ // chi xoa cac phan tu con thoa patern

sprintf(buff,"%s%s%s\\%s%s", drive,directory,

pblock.ff_name,patname, patext); duyetcay(buff,action);

}

else // xu ly file binh thuong

if(thuocve(filename, file_ext, patname, patext))

{

// thuc hien action tren phan tu nay

action(drive,directory,pblock);

}

result = findnext(&pblock);

}

}

/*?????????????????*/

/* Xoa phan tu theo yeu cau.*/

/* Phan tu co the la file hay thu muc trong*/

/*??????????????*/

void xoaphantu(char* drive, char* directory, struct ffblk pblock)

{

char buff[128];

sprintf(buff,"%s%s%s",drive, directory,pblock.ff_name);

if (pblock.ff_attrib & FA_RDONLY)

{ // xoa bit readonly

struct REGPACK rreg;

rreg.r_ax = 0x4301; rreg.r_cx = 0;

rreg.r_ds = FP_SEG(buff); rreg.r_dx = FP_OFF(buff);

intr(0x21, &rreg);

}

if (pblock.ff_attrib & FA_DIREC)

{ // neu la thu muc thi xoa thu muc

printf("rdir %s\n",buff);

rmdir(buff); dcount++;

}

else

{ // neu la file thi xoa file

printf("del %s\n",buff);

remove(buff); // neu khong co dung unlink()

fcount++;

}

}

    Bạn có thể cất chương trình trên vào file xoadq.c, dùng chương trình dịch C++, thí dụ :

bcc -ml xoadq.c để tạo ra file xoadq.exe. Nếu bạn muốn xóa tất cả các file *.pas và *.cpp ở ổ cứng c: và d:, bạn hãy nhập lệnh :

xoadq c:\*.pas c:\*.cpp d:\*.pas d:\*.cpp

    Lưu ý là sức công phá của chương trình trên rất ác liệt, bạn phải rất cẩn thận trong việc nhập thông số vì nếu không tai họa sẽ khó lường (thí dụ nếu bạn nhập lệnh xoadq c:\*.* thì toàn bộ đĩa c: sẽ bị xóa trắng).

Hỏi: Các chương trình được lập trình và dịch bằng những ngôn ngữ lập trình chạy trong Windows (for Windows) thì chạy được trong Windows phải không?

- Những ngôn ngữ lập trình trong Windows (for Windows) nào có chế độ đồ họa phong phú để có thể tạo ra các chương trình có màu đồ họa phong phú?

-Trong thư mục C:\Windows\ System em thấy có rất nhiều file có phần đuôi là .dll. Xin hỏi đó là những file gì, tác dụng, được tạo ra như thế nào?

Trả lời: Đa số các môi trường lập trình trong Windows đều tạo ra chương trình để chạy trong Windows, tuy nhiên cũng có một số ngoại lệ: các môi trường lập trình cũ của hãng Borland cho phép tạo chương trình chạy trên MS-DOS hay trên Windows tùy thuộc vào thông số lúc dịch.

    Các chức năng đồ họa thường được hỗ trợ bởi Windows và các thư viện lập trình, chứ không phụ thuộc vào ngôn ngữ lập trình. Bạn có thể dùng bất kỳ ngôn ngữ nào trong Windows để tạo ra đồ họa có màu sắc phong phú nếu chế độ đồ họa của Windows hiện tại trên máy bạn từ 256 màu trở lên.

    Các file *.dll là các thư viện liên kết động, mỗi file *.dll thường chứa nhiều thủ tục giải quyết một số vấn đề nào đó mà sẽ được dùng bởi các phần mềm khác. Về nguyên tắc, từ chương trình của bạn, bạn có thể gọi bất kỳ thủ tục nào trong một file *.dll nếu bạn biết tên thủ tục và danh sách đối số của thủ tục đó.

    Trình tự để tạo ra một file *.dll cũng giống như trình tự tạo file chương trình: viết source code các thủ tục, dịch source code để tạo ra file *.dll. Trước khi dịch bạn cần khai báo thông số cho chương trình dịch biết kết quả dịch là tạo ra chương trình hay file *.dll.

Hỏi: Đề nghị tòa soạn cho 1 ví dụ cụ thể về lệnh Exec của Pascal, gọi chương trình Vrd.exe của VietRes.

Trả lời: Để chạy trình vrd.exe từ chương trình Pascal, bạn dùng lệnh Exec như sau:

Exec(?c:\vietres\vrd.exe?,??);

    và nếu muốn dừng trình vrd.exe, bạn dùng lệnh Exec(?c:\vietres\vrd .exe?,?/u?);

    Trong thí dụ trên, giả sử file vrd.exe nằm ở thư mục vietres trên đĩa c:\. Bạn nên thêm vào macro khai báo dung lượng bộ nhớ heap nhỏ lại để chương trình vrd.exe chạy được, thí dụ bạn thêm macro sau vào đầu chương trình Pascal của bạn:

{$M $4000,0,0} {16K stack, no heap}

Hỏi: Trong quá trình lập trình trên một số ngôn ngữ như Pascal, C, C++, có một số đoạn chương trình chứa 3, 4 hoặc có nhiều hàm hay thủ tục. Đoạn chương trình này được ứng dụng vào nhiều chương trình khác nhau.

    Làm thế nào để sử dụng đoạn chương trình này vào những chương trình khác nhau mà không phải tốn công viết đoạn chương trình này lại.

Trả lời: Bạn có thể định nghĩa một thủ tục mới chứa đúng những hàng lệnh được dùng bởi nhiều chương trình. Bạn để thủ tục này (và có thể nhiều thủ tục khác) trong một file riêng. Bạn dịch file này ra dạng *.obj có thể dùng được từ bất kỳ chương trình nào. Cách thức gọi thủ tục và liên kết file *.obj sẽ hơi khác nhau trên các ngôn ngữ khác nhau. Thí dụ trong C và C++, bạn chỉ cần khai báo đặc tả (prototype) của thủ tục cần gọi trước khi gọi thủ tục. Trong Pascal, bạn phải khai báo đặc tả thủ tục cần gọi (dùng từ khóa External đi sau lệnh Procedure hay Function) và phải dùng macro để khai báo việc kết nối file *.obj vào chương trình ({$L tenfile.obj}).

Hỏi: Khi xây dựng một chương trình Pascal có sử dụng đồ họa, chọn ra file .exe rồi đem sang máy khác chạy thì chương trình đòi hỏi phải có các file .BGI và TPU. Có cách nào để chỉ cần một file *.exe là đủ hay không?

Trả lời: Thường khi dùng chế độ đồ họa trong Pascal, trước hết bạn gọi thủ tục InitGraph để khởi động chế độ đồ họa, thủ tục này sẽ liên kết động file driver *.bgi tương ứng vào chương trình. Tuy nhiên trong một số trường hợp bạn muốn liên kết tĩnh file *.bgi vào trong file chương trình của bạn (để dễ sao nó sang máy khác,...), Borland có hỗ trợ vấn đề này bằng cách cung cấp unit bgidriv.pas dạng source code Pascal trong thư mục bp7\examples\ dos\bgi, từ thư mục này bạn có thể tạo ra file bgidriv.tpu tương ứng bằng cách nhập lệnh sau từ DOS: make ốfbgidriv. Sau đó chép file bgidriv.tpu vào thư mục units của Pascal (bp7\units). Sau khi có được file bgidriv.tpu, bạn có thể dùng nó trong chương trình bằng lệnh 'Use', và như vậy khi dịch chương trình, driver đồ họa cần dùng sẽ được liên kết tĩnh vào chương trình *.exe của bạn. Sau đây là các lệnh chính yếu trong chương trình đồ họa của bạn:

Program name;

Use graph, bgidriv, ...;

Var GraphDriver, GraphMode : Integer;

....

Begin { chuong trinh chinh }

{ Dang ky driver do hoa can dung }

if RegisterBGIdriver(@EgaVgaDriverProc) < 0 then begin

writeln(?Khong the dang ky BGI driver?);

exit

end;

{ Khoi dong che do do hoa }

GraphDriver:=Detect;

initGraph (GraphDriver, GraphMode,??);

....

END.

Hỏi: Xin PC World VN hướng dẫn cách lập trình trong Turbo Pascal về một số hình học chuyển động trong không gian 3 chiều. Tôi đã cố thử làm nhiều lần nhưng không được.

Trả lời: Để lập trình các hình 3D chuyển động, bạn cần trang bị nhiều kiến thức chuyên môn về lĩnh vực đồ họa (các sách về ỏComputer Graphicsõ). Trong khuôn khổ hạn hẹp của mục trả lời, chúng tôi không thể mô tả cụ thể các kiến thức chuyên môn này. Ngôn ngữ lập trình chỉ là công cụ mô tả giải thuật cho máy tính hiểu, do đó không đóng vai trò quan trọng trong việc viết chương trình. Bạn có thể dùng Pascal, C, C++, Visual Basic hay bất kỳ ngôn ngữ đa dụng nào cũng được.

Hỏi: Hiện em đang lập trình Pascal 7.0. Em có một bộ font bitmap VGA, muốn nạp font này ra máy in ở chế độ văn bản và đồ họa thì làm cách nào (ví dụ bằng thủ tục). Xin quý báo chỉ cách viết chương trình liên kết một ảnh bitmap vào chương trình như các logo của D2, BKAV...

Trả lời: Bạn nên lưu ý rằng font bitmap của màn hình VGA không phải là font của các máy in. Mỗi loại máy in qui định riêng format font chữ của mình, thường thì rất khác nhau giữa máy in kim và máy in laser. Vậy để download font ra máy in, trước hết bạn cần soạn font đúng format qui định của loại máy in đó, rồi dùng các lệnh điều khiển nạp font ra máy in. Bạn cũng có thể in nội dung đồ họa của màn hình đang chứa văn bản tiếng Việt ra máy in bằng lệnh in đồ họa, tuy nhiên chất lượng thường rất thấp.

    Bạn nên xem phần trả lời ở số báo PC World VN tháng 09/97 (trang 129) để biết thêm thông tin về việc download font chữ ra các máy in kim Epson và HP laser. Để chương trình hiển thị được đồ họa mong muốn (tĩnh hay di động), bạn phải viết code cụ thể để điều khiển việc hiển thị này. Trong Borland C hay Pascal, 2 thủ tục đơn giản nhất để cất/ hiển thị lại một vùng đồ họa hình chữ nhật là GetImage và PutImage. PutImage cho phép bạn hiển thị lại một đồ họa hình chữ nhật từ cấu trúc dữ liệu BGI. Để có được cấu trúc này, bạn có thể :

- Dùng thủ tục GetImage để lưu đồ họa đang được hiển thị.

- Dùng chương trình chuyển đổi format từ dạng khác (ví dụ: *.bmp) sang dạng BGI của Borland. Nếu máy có nối mạng Internet, bạn hãy download một chương trình chuyển format đồ họa về dạng BGI ở địa chỉ ftp://ftp.simtel.net/ pub/simtelnet/ msdos/graphics /bmp2bgi1.zip

Hỏi: Em dùng Pascal 7.0 trong DOS. Trong Pascal có phát ra tiếng nói được không. Ví dụ khi chương trình bị lỗi, sẽ có giọng nói phát ra "Có lỗi rồi". Nếu như Pascal phát ra tiếng nói được thì xin tạp chí viết cho em một chương trình cụ thể hoặc chỉ cho em các hàm thủ tục làm công việc trên.

Trả lời: Bất cứ chương trình được viết bằng ngôn ngữ nào và trong môi trường nào (DOS, Windows, OS/2, Unix,...) đều có thể điều khiển xuất âm thanh ra sound card (hay loa nội bộ của máy PC). Việc xuất âm thanh ra sound card rất dễ dàng nếu bạn lập trình trong môi trường Windows vì môi trường Windows đã hỗ trợ multimedia, còn nếu bạn lập trình trên DOS, bạn phải viết module điều khiển xuất tín hiệu ra sound card hay dùng lại module sound card có sẵn. Bạn có thể gọi chương trình thi hành file *.wav từ trong chương trình Pascal của bạn, hầu hết các sound card được bán đều có đĩa mềm kèm theo, trên đĩa đó luôn có một trình 'play' các file âm thanh dạng *.wav. Giả sử chương trình chơi nhạc file *.wav có cú pháp sử dụng là : 'play <tên file wav cần phát>, bạn có thể phát ra thông báo được chứa trong file tbao.wav bằng lệnh Pascal sau:

Exec(?play.exe?,?tbao.wav?);

Hỏi: Các chương trình trò chơi như: Tomb Raider, Doom... viết bằng các chương trình nào, và xin cho biết chức năng của từng chương trình. Nếu trong phối cảnh không gian ba chiều tôi đã vẽ, tôi có thể can thiệp bằng keyboard để luồn lách trong đó được không?

Trả lời: Các trò chơi như Tomb Raider, Doom, ... được viết bằng ngôn ngữ nào không phải là điều quan trọng, điều quan trọng là chúng được viết theo giải thuật nào. Về nguyên tắc, nếu bạn đã biết giải thuật của một ứng dụng, bạn có thể hiện thực ứng dụng đó bằng bất kỳ ngôn ngữ lập trình nào, nếu cần chạy tối ưu một số đoạn code nào đó, bạn có thể viết các đoạn code này bằng ngôn ngữ Assembly.

    Nếu chương trình của bạn đã vẽ được lên màn hình phối cảnh không gian 3 chiều thì chương trình đó cũng có thể cho phép người dùng luồn lách trong phối cảnh đó (hay tổng quát hơn là xử lý phối cảnh) bằng chuột và/hoặc bàn phím.

    Tóm lại tuỳ thuộc chức năng của chương trình mà bạn có thể làm được điều gì, nếu chương trình do chính bạn thiết kế và hiện thực thì bạn hoàn toàn tự do trong việc qui định chức năng của nó.

    Trong trường hợp bạn dùng một phần mềm xử lý đồ họa nào đó để vẽ phối cảnh thì việc luồn lách trong phối cảnh đó bằng bàn phím có được không là tùy thuộc vào chính trình xử lý đồ họa mà bạn dùng.

Hỏi: Hiện em đang lập trình bằng ngôn ngữ C, và em muốn cấp phát bộ nhớ để chạy chương trình với kích thước > 1MB, hay nói cách khác là em muốn sử dụng bộ nhớ mở rộng. Nhưng em không biết làm cách nào để khai báo cả. Em có thể sử dụng hàm farmalloc, nhưng khi chạy biên dịch chương trình & chạy thì cứ bị treo máy. Theo như trong sách ghi là sử dụng hàm farmalloc thì truy cập được bộ nhớ lớn hơn 64 KB, nhưng em không biết tối đa của nó là bao nhiêu? Xin tạp chí trả lời bằng một ví dụ minh họa cụ thể.

Trả lời: Hàm thư viện ỏfarmallocõ của ngôn ngữ C hay C++ cho phép bạn xin cấp phát một khối nhớ liên tục với kích thước bất kỳ, tối đa bằng số bộ nhớ DOS còn trống. Dung lượng bộ nhớ DOS quản lý được là 640KB, do đó hàm farmalloc chỉ có thể phân phối khối nhớ có kích thước tối đa là 640KB, hàm này chỉ dùng bộ nhớ qui ước của DOS chứ chưa sử dụng bộ nhớ mở rộng (extended memory). Nếu muốn dùng không gian trong bộ nhớ mở rộng (vốn có kích thước rất lớn trên các máy PC hiện nay), bạn phải gọi các hàm chức năng của trình quản lý bộ nhớ mở rộng HIMEM.SYS. Chi tiết cụ thể về cách gọi các hàm chức năng của trình quản lý himem.sys được miêu tả trong bài "Bộ nhớ mở rộng và cách truy cập bộ nhớ mở rộng bằng Turbo Pascal" ở trang 72, PC World VN tháng 6/1997.

Hỏi: Tôi viết một chương trình quản lý nhân sự tiền lương bằng Foxpro For DOS, để làm đẹp, tôi dùng hợp ngữ vẽ lại một số mã ký tự (ASCII). Nhưng khi chạy lại chương trình tôi gọi VRD.EXE của VietRes để nhập tiếng Việt thì những ký tự của tôi vẽ lại đã bị VietRes biến đổi (mặc dù trong chương trình hợp ngữ của tôi đã chọn những ký tự mà VietRes không tác động đến).

    Vậy xin quý báo chỉ giùm làm cách nào vừa có thể sử dụng VRD.EXE để nhập liệu bằng tiếng Việt vừa có thể vẽ lại một số ký tự trong bảng mã ASCII theo ý muốn.

Trả lời: Mỗi khi VietRes chạy (vrd.exe), nó sẽ chiếm quyền điều khiển Int 10h và hiệu chỉnh lại toàn bộ font hệ thống (256 ký tự), nếu bạn thay đổi font trước khi chạy VietRes, sự thay đổi của bạn sẽ bị VietRes phá mất. Vậy bạn phải thay đổi font sau khi đã chạy VietRes, tuy nhiên VietRes không thi hành các chức năng liên quan đến việc hiệu chỉnh lại font chữ (để bảo vệ bảng font của VietRes). Nếu muốn gọi Int 10h để thiết lập một số ký tự riêng của mình sau khi đã chạy VietRes, bạn phải biết được địa chỉ trình phục vụ ngắt Int 10h của hệ thống và gọi đúng trình phục vụ này. Trình tự các thao tác như sau :

- Ghi lại vector ngắt Int 10h của hệ thống vào một biến pointer của chương trình.

- Chạy trình VietRes.

- Ghi lại vector ngắt Int 10h (của VietRes) vào một biến pointer khác của chương trình.

- Thiết lập lại vector ngắt Int 10h cũ của hệ thống.

- Gọi Int 10h (cũ của hệ thống) để thiết lập một số mẫu ký tự đặc biệt của riêng mình (dùng chức năng ah=1100h).

- Thiết lập lại vector ngắt Int 10h của VietRes.

- Tiếp tục chương trình của mình, lúc này VietRes tiếp tục chạy nhưng trong bảng mã của nó có một số ký tự được hiển thị theo mẫu của bạn.

- Khi kết thúc chương trình, bạn nên gỡ VietRes ra khỏi hệ thống nếu không muốn dùng nó nữa.

    Trong khung dưới đây là một trình Pascal nhỏ miêu tả qui trình dùng VietRes rồi hiệu chỉnh một vài ký tự theo ý riêng.

Hỏi: Em muốn viết một chương trình dùng để xem các hình ảnh *.bmp hay *.pic bằng Pascal thì phải viết như thế nào?

Trả lời: Bạn cần nắm vững format file ảnh *.bmp và *.pic thì mới có thể viết được chương trình hiển thị các file ảnh này. Sau khi nắm vững format file ảnh, bạn có thể dùng bất kỳ ngôn ngữ nào để viết chương trình. Một cách khác, đơn giản hơn, để hiển thị các hình ảnh bitmap dạng *.bmp hay *.pic là dùng trình chuyển format ảnh về dạng BGI của Borland để nhờ thủ tục PutImage hiển thị ảnh đó lên màn hình.

    Với cách này bạn không cần nghiên cứu một format ảnh nào hết. Nếu máy có nối mạng Internet, bạn hãy download chương trình chuyển format đồ họa về dạng BGI ở địa chỉ ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/bmp2bgi1.zip

Hỏi: Trong thư mục Windows, có một file ở thuộc tính ẩn (hidden) tên là "ttfcache". Xin hỏi đó có phải là file chứa font đã cài cho Win không? Làm cách nào dùng một hàm (function) để cài font trong Visual Basic? Hàm đó tên gì? Cách sử dụng?

Trả lời: Chúng tôi chưa rõ công dụng của file ỏttfcacheõ trong thư mục Windows vì không phải máy nào cũng có, nhưng với tên và nội dung của nó, chắc chắn nó chứa thông tin về font TrueType, nó được tạo vàạ sử dụng bởi một chương trình nào đó nhưng không phải Windows (chúng tôi thử xóa rồi khởi động lại Windows, sử dụng nhiều ngày vẫn không thấy tạo lại).

    Trong chương trình bất kỳ được viết bằng ngôn ngữ nào, bạn cũng có thể thêm font chữ mới (TrueType hay bitmap) vào Windows theo kiểu on-the-fly bằng cách gọi thủ tục ỏAddFontResourceõ.

    Đây là một hàm của Windows, để gọi được trong chương trình Visual Basic, bạn phải khai báo nó như sau:

Declare Function AddFontResourceA Lib "GDI32" (path As String) As Integer

Lúc nào cần thêm font, bạn có thể gọi nó, ví dụ như:á

ketqua = AddFontResourceA ("c:\psfonts\gvgafix.fon")

Đối số duy nhất của hàm AddFontResourceA là đường dẫn mô tả file font resource (dạng *.fon hay *.fot).á

Hỏi: Làm cách nào để biết được một macro đang chạy mang tên gì. Ví dụ một macro tên "Word" được kích hoạt thì bản thân chương trình dùng cách gì để có thể nhận được chuỗi "Word" tức là tên của nó. Tên macro này thường xuyên thay đổi nên nó phải tự biết được hiện tại nó đang mang tên gì. PC World có thể viết dùm em đoạn chương trình tự tìm tên này được không?

Trả lời: Về nguyên tắc, đúng là có thể viết được một macro có khả năng thi hành nhiều tác vụ tùy theo tên gọi. Ví dụ có 2 macro: macro 1 thi hành tác vụ 1, macro 2 thi hành tác vụ 2. Bây giờ ta sửa macro 1, macro 2 thành một macro duy nhất có thể thi hành được cả 2 tác vụ, nếu tên nó là macro 1 nó sẽ luôn thi hành tác vụ 1, cho tới khi đổi tên nó thành macro 2 thì nó sẽ thi hành tác vụ 2.

    Trong Word 97, macro là một thủ tục được viết bằng ngôn ngữ VBA (Visual Basic Application). Trong các ngôn ngữ lập trình cổ điển như C, Pascal,... người ta chỉ cung cấp phương tiện xác định tên chương trình đang chạy (tên file chương trình) chứ không cung cấp phương tiện xác định tên một thủ tục đang chạy.

    Có thể ngôn ngữ VBA cũng có cùng khả năng này, nghĩa là trong các lệnh của một thủ tục nào đó người ta không thể biết tên của thủ tục đang chạy. Điều này không gây phiền hà cho người lập trình. Theo kinh nghiệm, chúng tôi chưa thấy nhu cầu nào dẫn đến việc thay đổi tên macro thường xuyên trong quá trình chạy, hơn nữa, nếu người dùng macro của bạn không phải là bạn thì làm sao họ có thể hiệu chỉnh mã nguồn để đổi tên các macro? Thay vì viết 1 macro có khả năng thực hiện 2 chức năng khác nhau tùy theo tên, bạn nên viết riêng từng macro, phần việc chung được dùng bởi 2 macro sẽ được để trong một hay nhiều thủ tục khác, code trong macro chỉ gọi các thủ tục này để giải quyết vấn đề riêng của mình, như vậy chương trình sẽ trong sáng hơn nhiều so với cách mà bạn muốn viết.

    Trong trường hợp bạn đã viết lỡ macro đó rồi và không muốn sửa lại nhiều thì cách giải quyết như sau: viết thêm 2 macro, mỗi macro chỉ có một lệnh gọi đến thủ tục của bạn, trong lệnh gọi có truyền tên của macro gọi. Code cụ thể như sau:

?Code cua macro thi hanh cong viec 1
Sub macro1()
macro_chung("macro1")
End Sub
? Code cua macro thi hanh cong viec 2
Sub macro2()
macro_chung("macro2")
End Sub
? Code cua macro ma ban da viet
Sub macro_chung(macroname As String)
if macroname = "macro1" then
? Doan code thi hanh cong viec 1
Elseif macroname = "macro2" then
? Doan code thi hanh cong viec 2
Endif
End Sub

Hỏi: Bộ dịch C++ 32 bit cũ nhất, gọn nhẹ nhất là bộ nào?

Trả lời: Có thể đó là trình biên dịch Borland C++, version 3.0. Borland rất nổi tiếng về tính gọn nhẹ hiệu quả của các trình biên dịch của họ. Tuy nhiên, hiện nay bộ ỏVisual Studio 6.0õ của Microsoft đã cung cấp một môi trường lập trình rất mạnh và ổn định trên Windows 32-bit.

Hỏi: Có thể in kết quả của một chương trình viết bằng ngôn ngữ Pascal, C, C++ từ màn hình ra giấy được không? Làm bằng cách nào?

Trả lời: Được, tùy theo môi trường thi hành chương trình và có source code chương trình không? Nếu có source code của chương trình, bạn sẽ thêm vào những lệnh cần thiết để sau khi hiển thị ra màn hình, bạn xuất kết quả ra máy in.

Nếu không có source code, bạn có thể dùng kỹ thuật ỏscreen captureõ để sao lại kết quả đang hiển thị trên màn hình, cất nó vào một file nào đó (thí dụ file của Paint, của Word,...) rồi in nó ra máy in sau đó. Đa số các trình screen capture trên nền MS-DOS và Windows đều có khả năng in trực tiếp ra máy in nội dung màn hình vừa bị capture.

Hỏi: Em thử thay thủ tục WritePixel trong chương trình PC BMP (PCW tháng 5/1995) bằng thủ tục Putpixel của Unit Graph thì thấy tốc độ đọc ảnh tăng lên rõ rệt. Vậy có phải thủ tục Putpixel không ghi ảnh bằng cách thực hiện ngắt không? Nếu đúng như vậy thì thủ tục này ghi điểm ảnh bằng cách nào?

Trả lời: Trong quá trình lập trình, chúng ta sẽ gọi rất nhiều thủ tục trong nhiều thư viện khác nhau. Để gọi được thủ tục trong một thư viện nào đó, ta chỉ cần biết đặc tả (prototype) của thủ tục đó, bao gồm tên thủ tục, số lượng đối số, kiểu của từng đối số và chức năng của thủ tục đó. Người gọi thủ tục không cần biết chi tiết giải thuật cụ thể bên trong thủ tục đó. Thủ tục Putpixel trong thư viện đồ họa của Borland được hiện thực bởi hãng Borland, chúng ta khó lòng biết chi tiết bên trong thủ tục, nhưng như trên đã nói, điều đó không ảnh hưởng gì đến việc sử dụng nó.

Hỏi: - Trong Pascal 7.0, khi em dùng đến unit CRT thì chương trình không chạy được mặc dù máy báo là không có lỗi (khi dịch). Lúc đó hiện lên dòng: "Division by zero" và bắt buộc em phải chọn OK (mặc dù trong chương trình em không hề dùng đến các biểu thức tính toán).

- Khi chạy Turbo Pascal 7.0 để dịch và chạy file có nội dung:

uses crt;

Begin

Writeln;

End

thì bị báo lỗi khi chạy chương trình là lỗi sau:

Error 200: runtime at xxxx : 0091

Error 200: Division by zero

    Còn khi dịch vẫn bình thường. Đem đĩa chứa Turbo Pascal 7.0 đó chạy trên các máy khác vẫn bình thường. Máy em có cấu hình Pentium II 266 MHz, Ram 32MB, chạy bình thường Turbo Pascal 5.5. Với 7.0 nếu bỏ dòng lệnh uses crt hoặc thay các unit khác và không dùng các hàm của unit crt thì chạy bình thường.

Trả lời: Đây là lỗi của Turbo Pascal 7.0: không tương thích với CPU Pentium II. Bạn xem bài: "Khắc phục lỗi "Runtime Error 200" trong TP 7 trên máy PC tốc độ cao" trang 85 trong số báo này.

Hỏi: Làm thế nào để đưa một biểu tượng vào cửa sổ "system tray"? Xin cho ví dụ nhỏ (dùng VBasic 4-43).

Trả lời: Để thêm một biểu tượng chương trình vào cửa sổ ỏSystem Trayõ của Windows 9x hay Win NT, bạn phải gọi hàm API của Windows Shell_NotifyIcon (được chứa trên file thư viện shell32.dll). Qui trình sử dụng hàm này từ Visual Basic để thêm một biểu tượng vào ỏSystem Trayõ khá dài nên không tiện miêu tả ở đây. Muốn biết thông tin chi tiết và cụ thể về vấn đề này, bạn có thể đọc bài "HOW TO: Use the System Tray Directly from Visual Basic 5.0" trong đĩa MSDN số 2 của bộ đĩa Visual Studio 6.0. Nếu bạn quan tâm về lập trình trong môi trường Windows 32-bit bằng các ngôn ngữ của Microsoft (Visual Basic, C++, J++, Visual FoxProà), bạn nên tìm mua hai đĩa MSDN này.

Hỏi: Làm sao để ngăn cho chương trình trong Windows chạy hai lần trong Visual Basic? Em đang làm một chương trình cài font "System Tray" là nơi có biểu tượng loa, máy in ...

Trả lời: Một chương trình Visual Basic bao gồm nhiều form, trong đó có một form chính mô tả chương trình, chương trình bắt đầu chạy từ thủ tục Form_Load() của form này. Nếu bạn muốn chương trình chỉ được phép chạy một bản (instance), bạn có thể kiểm tra thuộc tính PrevInstance của đối tượng App mô tả chương trình, nếu khác không thì chương trình đã chạy ít nhất một bản, trong trường hợp này bạn dừng chương trình. Đoạn lệnh cụ thể như sau:

Private Sub Form_Load()
If App.PrevInstance Then
Unload Me ?Đóng form miêu tả cửa sổ chương trình
End ? Dừng chương trình
End If
?Các lệnh khởi động thông số cho chương trình
End Sub

Hỏi: Có thể tạo một macro trong Microsoft Word hay một chương trình trong Visual Basic để lấy số serial của đĩa mềm (A:, B:) hay không? Xin tạp chí viết một macro hay đoạn chương trình như yêu cầu. (Em thấy trong phiên bản làm việc với Word nếu mở file từ một đĩa mềm nào đấy nhưng chưa đóng lại, sau đó rút đĩa mềm ấy ra để đưa đĩa khác vào thì khi thao tác trên tập tin đã mở thì Word sẽ báo lỗi và yêu cầu ta đút đĩa mềm có số serial... vào, làm thế nào Word biết số Serial của đĩa đã đưa vào ổ ?).

Trả lời: Bạn có thể gọi hàm GetVolumeInformationA trong thư viện của Windows để lấy nhiều thông tin liên quan đến một đĩa mềm (hay đĩa cứng) nào đó, trong đó có số serial của nó. Vì đây là một hàm của Windows nên bạn phải khai báo trước khi dùng trong Visual Basic. Sau đây là một macro đơn giản được viết bằng Visual Basic để hiển thị số serial của đĩa mềm đang ở ổ a:

?Khai bao ham GetVolumeInformationA
Private Declare Function GetVolumeInformation Lib "kernel32" Alias "GetVolumeInformationA" _
(ByVal lpRootPathName As String, _
ByVal lpVolumeNameBuffer As String, _
ByVal nVolumeNameSize As Long, _
ByRef lpVolumeSerialNumber As Any, _
ByRef lpMaximumComponentLength As Any, _
ByRef lpFileSystemFlags As Any, _
ByVal lpFileSystemNameBuffer As String, _
ByVal nFileSystemNameSize As Long) As Boolean
? Thu tuc mo ta macro can viet
Sub ReadSerieNumber()
Dim Path As String
Dim volname As String
Dim fsn As String
Dim volserial As Long
Dim mcl As Long
Dim flag As Long
Path = "a:\"
kq = GetVolumeInformation(Path, volname, 128, volserial, mcl, _
flag, fsn, 256)
MsgBox ("Serial number cua dia mem tren o A: la " + Hex(volserial))
End Sub

Hỏi: Tôi muốn PCW cung cấp thông tin về:

- Header của các file *.exe và chương trình dùng kỹ thuật overlay.

- Cách xác định vị trí, kích thước của module được nạp đối với những chương trình thuộc loại này.

- Tên những tài liệu có các thông tin trên.

Trả lời: File overlay là trường hợp đặc biệt của file *.exe. Header của file *.exe trên MS-DOS là một record gồm nhiều vùng nhằm cung cấp thông tin đầy đủ về file *.exe. Cấu trúc cụ thể của file *.exe được trình bày trong bảng (phần đầu là header, phần sau là nội dung còn lại của file *.exe).

    Microsoft đã nới rộng header trên để miêu tả các file *.exe và *.dll chạy trong môi trường Windows. Nếu muốn biết thêm thông tin trong phần nới rộng này, bạn có thể đọc bài "Executable-File Format" trong đĩa MSDN 2 của bộ Visual Studio 6.0.

Hỏi: Khi cài Borland C (BC) 4.5 nửa chừng máy báo: "Need 386 or better to expand file: scrptsrc.pak". Đó là thông báo gì, và cần phải làm gì? Hiện tôi đang chạy BC 3.0 và bộ BC 4.5 cài nửa chừng. Khi viết chương trình và biên dịch thì có thông báo:

can't open include <io.h>
include <stdio.h>

Vậy đó là các vấn đề gì, có phải do bộ BC bị thiếu gây ra?

Trả lời: CÊu hình tèi thiĨu ®Ĩ cài và sư dơng trình biên dÞch BC 4.5 là máy 386, 4MB RAM trë lên. Vậy bạn hãy kiểm tra lại máy mình xem có thỏa mãn cấu hình tối thiểu không. Nếu máy bạn là 386 hay cao hơn mà BC 4.5 báo lỗi như bạn miêu tả thì đó là chuyện bất thường, đa số trường hợp là do virus gây ra. Nếu BC 4.5 cài chưa thành công thì việc sử dụng nó bị lỗi là chuyện bình thường vì các thông số cấu hình cho chương trình chưa được thiết lập đúng (các thông báo lỗi tìm không được các file include của BC 4.5 như io.h, stdio.h,... là một thí dụ cụ thể). Tóm lại nếu máy bạn là 386, 4MB Ram hay cao hơn, bạn hãy thực hiện trình tự sau đây:

- Khởi động lại máy từ đĩa mềm sạch, diệt virus bằng các trình diệt mới nhất (D2, BKAV...).
- Tạo cấu hình khởi động đơn giản nhất bằng cách hiệu chỉnh lại hai file Config.sys và Autoexec.bat.
- Kiểm tra lại bản gốc BC 4.5 nhất là khi dùng đĩa mềm, rồi cài lại BC 4.5.

Hỏi: Tôi đang sử dụng Windows 98. Xin hỏi làm cách nào để chuyển một chương trình viết bằng Pascal sang tập tin thực thi .Exe có thể chạy trong Windows, Dos (sử dụng Turbo Pascal 7.0). Và làm cách nào để có thể cài đặt Turbo Pascal (TP) vào Windows để khi chạy không còn dòng thông báo "Do you want to continue?"

Trả lời: Để cài đặt TP 7.0 vào máy chạy Windows 98, tốt nhất là bạn thoát ra DOS (hay khởi động ở chế độ ỏCommand Prompt Onlyõ). TP 7.0 có cả hai môi trường lập trình: trên DOS và trên Windows; nó cho phép bạn tạo chương trình chạy ở một trong nhiều chế độ khác nhau, trong đó hai chế độ chính là DOS và Windows.

    Có nhiều cách khác nhau để dịch chương trình nguồn ra tập tin *.exe chạy trên môi trường DOS, hai cách thông thường là:

- Từ dấu nhắc DOS, bạn chạy trình turbo.exe để làm việc với môi trường lập trình trên DOS của Pascal. Sau khi bạn đã mở chương trình nguồn (thí dụ Myprog.pas), bạn chọn menu Compile, rồi chọn mục ỏDestination Memoryõ để chuyển mục này thành ỏDestination Diskõ. Sau đó bạn chọn menu Compile/Make để tạo file Myprog.exe. Tập tin *.exe tạo ra sẽ được lưu ở cùng thư mục chứa chương trình nguồn nếu bạn không định nghĩa tường minh thư mục chứa nó trong menu Options/Directories/EXE Directory.

- Dùng chương trình dịch hàng lệnh bpc.exe để tạo tập tin *.exe như sau : &laquo;bpc -CD Myprog.pas&raquo;. Để biết chi tiết về các tham số của trình bpc.exe, bạn nhập lệnh bpc rồi nhấn Enter, chương trình sẽ hiển thị các tham số mà nó hỗ trợ.

    Tương tự, để tạo ra tập tin *.exe chạy trong Windows, bạn cũng có thể dùng nhiều cách khác nhau, trong đó hai cách thông thường là:

- Chạy trình BPW.exe để làm việc với môi trường lập trình của Pascal trên Windows. Sau khi mở tập tin nguồn (thí dụ Myprog.pas), bạn chọn menu Compile để xem mục ỏTarget..õ có phải là ỏWindowsõ không (chế độ default), nếu không, chọn mục ỏTargetõ để thay đổi thành ỏWindowsõ. Sau đó bạn chọn menu Compile/Make để tạo tập tin Myprog.exe. Tập tin *.exe được tạo ra sẽ lưu ở cùng thư mục chứa tập tin nguồn nếu bạn không định nghĩa tường minh thư mục chứa nó trong menu Options/Directories/EXE Directory.

- Từ dấu nhắc DOS, bạn dùng chương trình dịch hàng lệnh Bpc.exe để tạo tập tin *.exe như sau:

bpc -CW myprog.pas

    Để biết chi tiết về các tham số của trình Bpc.exe, bạn nhập lệnh bpc rồi Enter, chương trình sẽ hiển thị các tham số mà nó hỗ trợ.

    Lưu ý rằng để tạo một chương trình chạy được trên Windows, bạn cần phải viết chương trình theo các qui định của Windows. Để làm quen với cấu trúc chương trình trên Windows, bạn có thể đọc các chương trình mẫu của TP 7.0

Hỏi: Em có một bài toán giải bằng Pascal

Trăm bò trăm cỏ
Trâu đứng ăn năm
Trâu nằm ăn ba
Trâu già ba con ăn một
Tìm số trâu mỗi loại
(Đây là bản gốc của đề, nhưng thầy cho là "Trâu già ăn một")

Em đã dùng Pascal, cấu trúc vòng lặp FOR để giải nhưng không được. Bài của em như sau:

Var a, b, c: integer;
Begin
for a:= 1 to 20 do
for b: = 0 to 35 do
for c: = 0 to 99 do
if (5*a + 3*b + c/3 = 100) and (a+b+c = 100) then writeln (a,b,c);
end.

NÕu viÕt chương trình theo ®Ị cđa thÇy thì sưa dßng if lại

If (5*a + 3*b + c= 100) and (a+b+c = 100) then

Em đã thử nhưng chương trình chạy sai. Em dùng While... do, vẫn vậy. Khi em bỏ đi đoạn "and (a+b+c = 100)" thì chương trình chạy đúng nhưng nó không như đề bài nữa.

Xin tòa soạn giúp em giải bài toán này.

Trả lêi: NÕu bài toán cđa bạn ®ưîc phát biĨu râ ràng như sau: "cã 100 con tr©u ăn 100 bã cá, trong ®ã cã 3 loại tr©u : tr©u ®øng mét con ăn 5 bã, tr©u nằm mét con ăn 3 bã, tr©u già 3 con ăn 1 bã. Hãy tìm tất cả các tổ hợp về số trâu của mỗi loại thoả mãn bài toán" thì chương trình Pascal giải bài toán này sẽ được viết đơn giản như sau:

Program timsotrau;
Var std, stn, stg : Integer;
Begin writeln(?Cac kha nang co the co la :?);
for std := 0 to 20 do { toi da co 100/5=20 trau dung }
for stn := 0 to 33 do { toi da co 100/3=33 trau nam }
for stg := 0 to 100 do { toi da co 100 trau gia }
if (std*5+stn*3+ stg div 3 = 100) and
(std+stn+stg=100) and (stg mod 3 = 0) then
writeln(?std=?,std,? stn=?,stn,? stg=?,stg);
readln;
end.

    Sau khi dịch và chạy chương trình ta có kết quả hiện lên màn hình như sau:

Cac kha nang co the co la:
std=0 stn=25 stg=75
std=4 stn=18 stg=78
std=8 stn=11 stg=81
std=12 stn=4 stg=84

    Bạn có thể kiểm chứng lại từng khả năng. Lưu ý là chương trình trên chưa được tối ưu về mặt thời gian thi hành, nhưng trên các máy tính hiện nay thì chương trình trên chạy hầu như tức thời nên có lẽ cũng không cần tối ưu nó làm gì.

Hỏi: Em có viết một đoạn chương trình như sau:

Var: I: Integer;
a,b,:Real;
St: String;
f:Text;
Gd,Gm:Integer;
Begin
Gd:=Detect;
Ini Graph(Gd,Gm.?C:\Tp\Bgi?);
If GraphResult <> grOK then
Halt(1);
...
a:=Port[$3F8];
Str(a:10:2,st);
outtextxy(10,10,st);
...
closegraph;
End.

    Chương trình này chạy nhưng không thể điều khiển như ý muốn được, không thể đọc liên tục biến 'a' vào từ cổng COM, chuỗi 'St' khi in ra nếu có từ 2 lần in thì bị đè lên nhau (hai giá trị khác nhau) trong môi trường đồ họa. Xin được chỉ dẫn.

Trả lêi: Bạn cã thĨ ®äc/ghi mét ô nhí theo nhÞp ®iƯu cđa bạn, nhưng bạn phải nhËp/xuÊt mét thanh ghi cđa card giao tiÕp I/O theo ®Æc ®iĨm và trạng thái cđa card I/O ®ã. Thường card I/O có các loại thanh ghi sau: thanh ghi trạng thái, thanh ghi lệnh, thanh ghi dữ liệu xuất và thanh ghi dữ liệu nhập. Sẽ không có nghĩa khi bạn ghi nội dung ra thanh ghi trạng thái hay thanh ghi nhập dữ liệu. Tương tự, việc đọc nội dung thanh ghi lệnh hay thanh ghi xuất dữ liệu là không có nghĩa. Việc đọc nội dung của thanh ghi nhập liệu chỉ có nghĩa (và cần thiết) sau khi dữ liệu được gửi từ thiết bị I/O đến thanh ghi nhập liệu của card giao tiếp tương ứng. Thí dụ chỉ khi người dùng ấn một phím, mã scan của phím ấy mới được gửi về máy tính và được đưa vào thanh ghi nhập liệu keyboard ở port 60h. Lúc này (nhờ tín hiệu ngắt quảng thông báo) bạn mới nên đọc nội dung của thanh ghi này để biết được mã phím vừa nhấn. Sau đó bạn phải xuất ra thanh ghi điều khiển ở port 61h để tạo tín hiệu phản hồi (acknowledgement) về cho keyboard để nó có thể gởi tiếp mã scan khác khi có phím được nhấn kế tiếp.

    Riêng đối với lệnh OuttextXY trong thư viện đồ họa Pascal trên nền DOS, nó không xóa dữ liệu trước khi hiển thị nội dung mới, do đó sẽ dẫn đến việc ghi chồng lên nội dung cũ và khiến người dùng khó lòng đọc được.
Để tránh việc ghi chồng này, bạn cần phải xóa nội dung trước đó (bằng lệnh Bar(...) chẳng hạn) trước khi gọi hàm OuttextXY để hiển thị nội dung mới.

Hỏi: Tôi tự học FoxPro và Access. Trong FoxPro, khi tính tiền tồn quỹ của tập tin TienMat.DBF có các trường: Ngay, Chung_Tu, Dien_Giai, Thu, Chi, Ton_Quy theo công thức: Tồn quỹ tại thời điểm Chung_tu(i) = Tồn quĩ tại thời điểm Chung_tu(i -1) + Thu(i) - Chi(i). Tôi viết chương trình TienMat.PRG tính Ton_Quy như sau:

Set talk off
Clear
Use TienMat.DBF
tq=ton_quy
do while !eof()
replace ton_quy with tq+thu-chi
tq=tq+thu-chi
skip
enddo
browse
return

    Chương trình trên tính được Ton_quy theo yêu cầu. Làm cách nào giải quyết yêu cầu này bằng Access?

Trả lời: Nếu bạn đã học và nắm được đặc tính của Access thì việc dùng Access để giải quyết bài toán của bạn sẽ gần giống như FoxPro giải quyết:

- Mỗi tập tin cơ sở dữ liệu (CSDL) của Access chứa nhiều loại phần tử: table, query, form, report, macro và module, trong đó mỗi table (tương ứng với một tập tin CSDL của FoxPro) gồm nhiều mẩu tin (record) với một cấu trúc nào đó theo yêu cầu.

- Ngôn ngữ chính để viết chương trình ứng dụng trong Access là VBA (Visual Basic for Applications).

    Thí dụ sau đây miêu tả một cách làm cụ thể để giải quyết vấn đề bạn nêu:

- Chạy Access, chọn nút Create blank database để tạo một database mới.

- Chọn nút Tables, chọn New, chọn mục Datasheet view. Khi cửa sổ trình bày một bảng trống hiện lên, bạn chọn các cột từ Field1 tới Field6 rồi đặt tên lại cho chúng là: Ngay, Chung_tu, Thu, Chi, Ton_Quy, Dien_Giai. Sau đó, đặt tên cho bảng này là Thuchi.

- Nhập dữ liệu theo thứ tự từng record với từng field theo yêu cầu (dùng field Ton_Quy của record đầu để chứa giá trị tồn quỹ ban đầu, có thể là 0).

- Chọn lại cửa sổ database, chọn nút Forms, chọn New, chọn mục Design view. Khi xuất hiện một form trống, chọn công cụ Command Button trong cửa sổ Toolbox để tạo một nút lệnh trong form. Nhấn chuột phải vào nút vừa tạo để làm hiển thị thực đơn rồi chọn Properties, đặt lại tên cho nút lệnh này là tinhtonquy và Caption là Tinh ton quy. Kết hợp biến cố (event) OnClick của nút lệnh với thủ tục sau đây để tính tồn quỹ theo yêu cầu của bạn:

Private Sub tinhtonquy_Click (Cancel As Integer)
Dim Thu As Database
Dim Thuchi As Recordset
Dim tq As Double
Set Thu = CurrentDb
Set Thuchi = Thu.OpenRecordset("Thuchi")
With Thuchi
tq = !tonquy
.MoveNext
Do While Not .EOF
.Edit
!tonquy = tq + !Thu - !Chi
tq = !tonquy
.Update
.MoveNext
Loop
.Close
End With
End Sub

- Sau khi bạn đã tạo ra form đơn giản có một button lệnh như trên, Access sẽ yêu cầu bạn đặt tên cho nó chẳng hạn như fmtinhtonquy. Từ đây, bạn có thể chạy form này bất kỳ lúc nào bạn muốn bằng cách vào cửa sổ database, chọn nút Forms rồi nhấn đúp fmtinhtonquy.

Hỏi: Tôi viết chương trình bằng AutoLisp cho AutoCAD. Các tập tin chương trình này được viết dưới dạng văn bản (text) nên người dùng có thể sửa đổi được chương trình. Tôi được biết có một số tập tin LSP có thể được đổi sang dạng mã máy mà AutoCad có thể đọc được (các tập tin LSP này được Protected). Xin cho biết cách hoặc chương trình nào để bảo vệ các tập tin Autolisp này.

Trả lời: Bình thường thì các tập tin chương trình AutoLisp ở dạng văn bản nên bất kỳ ai cũng có thể tham khảo nội dung. Nếu muốn "che dấu" nội dung của nó, bạn cần đổi nó sang một dạng mã khó đọc. Tuy nhiên không có tiện ích nào đi kèm theo bộ phần mềm AutoCAD cho phép bạn thực hiện việc này cả. Mặc dù vậy, có nhiều người chuyên dùng AutoCAD đã viết tiện ích này, trong đó có các thầy ở Khoa Cơ Khí Trường ĐH Kỹ Thuật Tp. HCM. Để biết thông tin cụ thể về tiện ích này, bạn có thể liên hệ trực tiếp với thầy Vũ Tiến Đạt theo điện thoại số 823 2691.

Hỏi: 1. Em muốn hiện một file .bmp nhanh trên Turbo Pascal 7.0 thì làm cách nào?

2. Một chương trình Pascal (Ver 7.0) có dùng thủ tục EXEC của Unit Dos để gọi chương trình ngoài (EXEC('C:\VPIC.Exe','C:\Anh.BMP'), vì file Anh.bmp khá lớn nên khi gặp lệnh này thì chương trình dừng lại để đọc đĩa, điều này ngoài ý muốn. Vậy có cách nào để đưa cả 2 file: Anh.bmp và VPIC.exe (file xem ảnh) vào Ram để khi gặp lệnh trên thì chương trình chỉ tìm chúng trong Ram để giảm thời gian truy xuất đĩa (khi kết thúc chương trình thì các file trên cũng được giải phóng).

Trả lời: (1&2). Trên DOS không có cách nào cho phép bạn nạp trước chương trình và dữ liệu của chương trình đó vào RAM để khi cần sẽ chạy nhanh hơn. Thực vậy, khi cần thi hành chương trình, DOS mới tìm file chương trình trên đĩa và nạp nó vào RAM. Lúc chương trình chạy, tùy thuộc vào giải thuật, nó sẽ đọc dữ liệu khi cần thiết. Riêng trường hợp của bạn, do chương trình bạn gọi trình vpic.exe để nhờ nó hiển thị file ảnh anh.bmp nên bạn không thể can thiệp vào quá trình hiển thị ảnh của vpic.exe được. Để chủ động trong quá trình nạp file ảnh vào RAM cũng như hiển thị nó lên màn hình, bạn nên xử lý trực tiếp file ảnh. Để xử lý trực tiếp được ảnh *.bmp, bạn phải:

- Hoặc nắm vững cấu trúc file ảnh *.bmp. Có rất nhiều tài liệu giới thiệu cấu trúc file *.bmp, bạn có thể đọc bài "Bitmap Storage" và các bài báo liên quan trong CDROM MSDN kèm theo bộ Visual Studio 6.0 của Microsoft.
- Hoặc dùng tiện ích chuyển format file từ *.bmp sang dạng đồ họa BGI của Borland rồi dùng hàm putimage() để hiển thị lên màn hình khi cần thiết. Một trong những tiện ích chuyển format ảnh từ *.bmp sang *.bgi là trình bmp2bgi.exe, bạn có thể download nó từ Internet ở địa chỉ ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/bmp2bgi1.zip

Hỏi: Trong Pascal ở chế độ đồ họa mỗi khi thực hiện chương trình hàm GraphResult sẽ trả lại mã lỗi của chương trình đồ họa đó. Muốn biết được thông báo lỗi này ta dùng hàm GraphErrorMsg. Còn ở chế độ văn bản khi thực hiện gọi một trong các thủ tục trong Unit Dos hoặc thực hiện các lời gọi vào ra... thì mã lỗi lưu trong biến Dos Error hoặc hàm IOResult. Hỏi có cách nào biết được câu thông báo lỗi mà hàm IOResult hay biến DosError trả lại không.

Trả lời: Biến DosError trong unit Dos hay hàm IOResult chỉ trả về mã lỗi sai để bạn xử lý (dạng số nguyên), Pascal không cung cấp hàm nào cho phép đổi mã lỗi sai thành chuỗi văn bản sai tương ứng. Nếu bạn cần yêu cầu này, bạn có thể tạo một dãy n String, String i chứa chuỗi lỗi tương ứng với mã lỗi i. Bạn có thể vào phần Help của Pascal, tìm mục "Run-time error messages" để biết tất cả mã lỗi và các chuỗi lỗi tương ứng.


   

PcLeHoan 1996 - 2002
Mirror : http://www.pclehoan.com
Mirror : http://www.lehoanpc.net

Mirror : http://www.ktlehoan.com