Bài giảng Kỹ thuật lập trình - Chương 3, Phần 2: Các kỹ thuật xây dựng chương trình phần mềm - Vũ Thị Hương Giang

• Với mỗi bài toán, làm thế nào để:  
– Thiết kế giải thuật nhằm giải quyết bài toán đó  
– Cài đặt giải thuật bằng một chương trình máy tính  
- Làm cho chương trình chạy  
đúng trước khi tăng tính hiệu  
quả của chương trình  
- Tăng tính hiệu quả của  
chương trình, đồng thời thể  
hiện tốt phong cách lập trình  
cá nhân  
CHƯƠNG III.  
CÁC KỸ THUẬT XÂY DỰNG  
CHƯƠNG TRÌNH PHẦN MỀM  
I. Mở đầu  
II. Làm việc với biến  
III. Viết mã chương trình hiệu quả  
IV. Thiết kế chương trình  
V. Xây dựng hàm/thủ tục  
IV. CÁC KỸ THUẬT THIẾT  
KẾ CHƯƠNG TRÌNH  
1. Nguyên tắc chung  
2. Thiết kế giải thuật  
3. Thiết kế dữ liệu  
Mở đầu  
• Phẩm chất của 1 chương trình tốt  
– Cấu trúc tốt  
– Logic chương trình + các biểu thức được diễn đạt theo  
cách thông thường  
– Tên dùng trong chương trình có tính chất miêu tả  
– Chú thích hợp lý  
– Tôn trọng chiến lược divide/conquer/association  
• Làm thế nào để tạo ra chương trình có phẩm chất  
tốt  
– Thiết kế top-down  
– Tinh chỉnh từng bước  
1. Nguyên tắc chung  
• Đơn giản:  
– Thể hiện giải thuật như nó vốn có, đừng quá kỳ bí  
– Lựa chọn cấu trúc dữ liệu sao cho việc viết giải thuật bằng NNLT  
cụ thể là đơn giản nhất  
– Tìm cách đơn giản hóa các biểu thức  
– Thay những biểu thức lặp đi lặp lại bằng CTC tương ứng  
• Trực tiếp:  
– Sử dụng thư viện mọi lúc có thể  
– Tránh việc kiểm tra điều kiện không cần thiết  
• Rõ ràng:  
– Dùng các cặp dấu đánh dấu khối lệnh để tránh nhập nhằng  
– Đặt tên biến, hàm, .. sao cho tránh được nhầm lẫn  
– Không chắp vá các đoạn mã khó hiểu mà nên viết lại  
1. Nguyên tắc chung  
• Có cấu trúc tốt:  
– Tôn trọng tính cấu trúc của chương trình theo từng mô  
thức lập trình:  
• Modul: hàm/ thủ tục  
• Hướng đối tượng: lớp  
• Hướng thành phần: thành phần  
• Hướng dịch vụ: dịch vụ  
– Viết và kiểm thử dựa trên cấu trúc phân cấp của chương  
trình  
– Tránh hoàn toàn việc dùng goto  
Nếu cần thì nên viết giải thuật bằng giả ngữ, rồi mới  
viết bằng 1 NNLT cụ thể  
2. Thiết kế giải thuật  
• Chia bài toán ra thành nhiều bài toán nhỏ hơn  
• Tìm giải pháp cho từng bài toán nhỏ  
• Gộp các giải pháp cho các bài toán nhỏ thành giải  
pháp tổng thể cho bài toán ban đầu  
Đơn giản hóa bài toán bằng cách trừu tượng hóa:  
làm cái gì thay vì làm như thế nào  
– Ví dụ: các hàm ở mức trừu tượng  
• Hàm sắp xếp 1 mảng các số nguyên  
• Hàm nhập vào / xuất ra các ký tự: getchar() , putchar()  
• Hàm toán học : sin(x), sqrt(x)  
Bottom-Up Design is Bad  
1 2  
• Bottom-up design   
– Thiết kế chi tiết 1 phần  
– Thiết kế chi tiết 1 phần khác  
– Lặp lại cho đến hết  
…
• Bottom-up design in programming  
– Viết phần đầu tiên của CT 1 cách chi  
tiết cho đến hết  
– Viết phần tiếp theo của CT 1 cách chi  
tiết cho đến hết  
1
2
3
4
…
– Lặp lại cho đến hết  
Top-Down Design is Good  
• Top-down design   
– Thiết kế toàn bộ sản phẩm một cách sơ bộ, tổng thể  
– Tinh chỉnh cho đến khi hoàn thiện  
• Top-down design in programming  
– Phác họa hàm main() (bằng các lệnh giả ngữ -  
pseudocode)  
– Tinh chỉnh từng lệnh giả ngữ  
• Công việc đơn giản => thay bằng real code  
• Công việc phức tạp => thay bằng lời gọi hàm  
1
– Lặp lại sâu hơn, cụ thể, chi tiết hơn  
2
3
– Kết quả: Sản phẩm có cấu trúc phân cấp  
tự nhiên  
…
4
5
Top-Down Design in Reality  
• Thiết kế CT Top-down trong thực tiễn :  
– Định nghĩa hàm main() = pseudocode  
– Tinh chỉnh từng lệnh pseudocode  
• Nếu gặp sự cố Oops! Xem lại thiết kế, và…  
• Quay lại để tinh chỉnh pseudocode đã có, và tiếp tục  
– Lặp lại (mostly) ở mức sâu hơn, cụ thể hơn, cho đến khi  
các hàm đc định nghĩa xong  
1
1’  
1’  
1’’  
2
Oops  
2’  
3
2’  
3
2’’  
3’  
…
4
Oops  
4’  
5
Ví dụ: Text Formatting  
• Mục tiêu :  
– Minh họa good program và programming style  
• Đặc biệt là modul hóa mức hàm và top-down design  
– Minh họa cách đi từ vấn đề đến viết code  
• Ôn lại và mô tả cách xây dựng CTC  
• Text formatting  
– Đầu vào: ASCII text, với hàng loạt dấu cách và phân dòng  
– Đầu ra: Cùng nội dung, nhưng căn trái và căn phải  
• Dồn các từ tối đa có thể trên 1 dòng 50 ký tự  
• Thêm các dấu cách cần thiết giữa các từ để căn phải  
• Không cần căn phải dòng cuối cùng  
– Để đơn giản hóa, giả định rằng :  
• 1 từ kết thúc bằng dấu cách space, tab, newline, hoặc end-of-  
file  
• Không có từ nào quá 20 ký tự  
Ví dụ về Input and Output  
Tune  
Bid every  
Let's all  
every  
heart  
bank withdrawal.  
with our accounts rejoice.  
and  
every  
voice.  
I
N
P
U
T
In funding Old Nassau.  
In funding Old Nassau we spend more money every year.  
Our banks  
shall give, while  
we  
shall  
live.  
We're funding  
Old Nassau.  
O
U
T
P
U
T
Tune every heart and every voice. Bid every bank  
withdrawal. Let's all with our accounts rejoice.  
In funding Old Nassau. In funding Old Nassau we  
spend more money every year. Our banks shall give,  
while we shall live. We're funding Old Nassau.  
Nghiên cứu bài toán  
• Khái niêm “từ”  
– Chuỗi các ký tự không có khoảng trắng, tab xuống dòng, hoặc EOF  
– Tất cả các ký tự trong 1 từ phải đc in trên cùng 1 dòng  
• Làm sao để đọc và in đc các từ  
– Đọc các ký tự từ stdin cho đến khi gặp space, tab, newline, or EOF  
– In các ký tự ra stdout tiếp theo bởi các dấu space(s) or newline  
• Nếu đầu vào lộn xộn thì thế nào?  
– Cần loại bỏ các dấu spaces thừa, các dấu tabs, và newlines từ input  
• Làm sao có thể căn trái - phải ?  
– Ta không biết được số dấu spaces cần thiết cho đến khi đọc hết các từ  
– Cần phải lưu lại các từ cho đến khi có thể in được trọn vẹn 1 dòng  
• Nhưng, bao nhiêu space cần phải thêm vào giữa các từ?  
– Cần ít nhất 1 dấu space giữa các từ riêng biệt trên 1 dòng  
– Có thể thêm 1 vài dấu spaces để phủ kín 1 dòng  
Viết chương trình  
• Các cấu trúc dữ liệu chính  
– Từ - Word  
– Dòng - Line  
• Các bước tiếp theo  
– Viết pseudocode cho hàm main()  
– Tinh chỉnh  
• Lưu ý :  
– Chú thích hàm và một số dòng trống được bỏ qua vì những  
hạn chế không gian  
• Phải tôn trọng các quy tắc trình bày mã nguồn khi viết  
CT thực tế  
– Trình tự thiết kế là lý tưởng  
• Trong thực tế, nhiều backtracking sẽ xảy ra  
Mức đỉnh  
• Phác thảo  
hàm  
int main(void) {  
<Xóa dòng>  
for (;;) {  
main()…  
<Đọc 1 từ>  
if (<Hết từ>) {  
<In dòng không cần căn phải>  
return 0;  
}
if (<Từ không vừa dòng hiện tại>) {  
<In dòng có căn lề phải>  
<Xóa dòng>  
}
<Thêm từ vào dòng>  
}
return 0;  
}
Tinh chỉnh từng bước  
#include <stdio.h>  
enum {MAX_WORD_LEN = 20};  
int main(void) {  
- Đọc 1 từ  
char word[MAX_WORD_LEN + 1];  
int wordLen;  
< Xóa dòng >  
• <Đọc 1 từ> nghĩa là  
gì?  
• Việc này khá phức tạp  
nên cần tách thành 1  
hàm riêng …  
for (;;) {  
wordLen = ReadWord(word);  
if (<Hết từ>) {  
< In dòng không cần căn phải >  
return 0;  
}
if (< Từ không vừa dòng hiện tại >)  
{
}
< In dòng có căn lề phải >  
< Xóa dòng >  
}
< Thêm từ vào dòng >  
}
return 0;  
int ReadWord(char *word) {  
<Bỏ qua whitespace>  
<Lưu các ký tự cho đến MAX_WORD_LEN của từ>  
<Trả về đọ dài từ>  
}
The “End-of-File Character”  
• Các files không kết thúc bằng “EOF character”, vì  
không tồn tại ký tự đó  
• EOF là:  
– Một giá trị đặc biệt được hàm getchar() hoặc các hàm  
liên quan trả về để chỉ ra 1 lỗi vào ra  
– Được định nghĩa trong stdio.h (thường với giá trị -1)  
– Trong môi trường windows, có thể tương đương với mã  
ASCII của cụm phím tắt Ctl + Z  
Using EOF  
• Correct code  
getchar() trả lại giá trị kiểu int cho tất cả các  
ký tự và ký hiệu EOF  
int c;  
c = getchar();  
while (c != EOF) {  
…
c = getchar();  
}
• Equivalent idiom  
int c;  
while ((c = getchar()) != EOF) {  
…
}
• Incorrect code  
char c;  
while ((c = getchar()) != EOF) {  
…
Tại sao ?  
}
Tinh chỉnh từng bước  
- Đọc 1 từ  
• ReadWord() function  
int ReadWord(char *word) {  
int ch, pos = 0;  
/* Bỏ qua whitespace. */  
ch = getchar();  
while ((ch == ' ') || (ch == '\n') || (ch == '\t'))  
ch = getchar();  
/* Lưu các ký tự vào từ cho đến MAX_WORD_LEN . */  
while ((ch != ' ') && (ch != '\n') && (ch != '\t') && (ch != EOF)) {  
if (pos < MAX_WORD_LEN) {  
word[pos] = (char)ch;  
pos++;  
}
ch = getchar();  
}
word[pos] = '\0';  
/* Trả về độ dài từ. */  
return pos;  
}
Tinh chỉnh từng bước  
- Đọc 1 từ  
• Hmmm. ReadWord() chứa 1 vài đoạn code lặp lại  
int ReadWord(char *word) {  
=> tách thành 1 hàm riêng : IsWhitespace(ch)  
int ch, pos = 0;  
Có thật sự phải  
tự viết hàm kiểm  
tra này không ?  
ctype.h cung cấp  
hàm isspace( )  
với chức năng  
tương đương  
/* Bỏ qua whitespace. */  
ch = getchar();  
while (IsWhitespace(ch))  
ch = getchar();  
/* Lưu các ký tự vào từ cho đến MAX_WORD_LEN . */  
while (!IsWhitespace(ch) && (ch != EOF)) {  
if (pos < MAX_WORD_LEN) {  
word[pos] = (char)ch;  
pos++;  
}
ch = getchar();  
int IsWhitespace(int ch) {  
return (ch == ' ') || (ch == '\n') || (ch == '\t');  
}
word[pos] = '\0';  
}
/* trả về đọ dài từ. */  
return pos;  
}
Tải về để xem bản đầy đủ
pdf 135 trang Thùy Anh 17260 Free
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Kỹ thuật lập trình - Chương 3, Phần 2: Các kỹ thuật xây dựng chương trình phần mềm - Vũ Thị Hương Giang", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

File đính kèm:

  • pdfbai_giang_ky_thuat_lap_trinh_chuong_3_phan_2_cac_ky_thuat_xa.pdf