Bản thuyết trình đang được tải. Xin vui lòng chờ

Bản thuyết trình đang được tải. Xin vui lòng chờ

Chương 2: Các kỹ thuật xây dựng chương trình phần mềm

Các bản thuyết trình tương tự


Bản thuyết trình với chủ đề: "Chương 2: Các kỹ thuật xây dựng chương trình phần mềm"— Bản ghi của bản thuyết trình:

1 Chương 2: Các kỹ thuật xây dựng chương trình phần mềm
Vũ Hải

2 Nội dung Mở đầu Làm việc với các biến Viết mã chương trình hiệu quả
Thiết kế chương trình Xây dựng hàm/thủ tục

3 1. 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

4 Nguyên tắc chung Đơn giản: Thể hiện giải thuật như nó vốn có 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 ùng các cặp dấu đánh dấu khối lệnh để tránh nhập nhằng

5 Nguyên tắc chung Đơn giản: Thể hiện giải thuật như nó vốn có
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

6 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 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ể

7 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)

8

9

10

11 Chương trình C đơn giản nhất
/* hello.c */ #include <stdio.h> int main() { printf("Xin chao!\n"); return 0; } Chương trình in ra màn hình: Xin chao!

12 Phân tích chương trình ví dụ
Chương trình trên có: Định nghĩa hàm main() Một dòng chú thích Một dẫn hướng biên dịch (dùng thư viện) Một câu lệnh xuất ra màn hình (đầu ra chuẩn) Một câu lệnh trả kết quả Chương trình thực hiện: Yêu cầu máy tính in ra một dòng chữ ra màn hình Trả kết quả về là 0 cho chương trình gọi nó

13 Hàm main() Là hàm dùng để bắt đầu chạy một chương trình C, và bắt buộc phải có Khai báo bằng một trong hai cú pháp: int main() { … } int main(int argc, char* argv[]) { … } Trong C++ có thể khai báo hàm main() với kiểu trả về là void Khi bắt đầu chạy, một số tham số sẽ được truyền cho chương trình; và khi kết thúc, chương trình sẽ trả về một giá trị. VD: C:\>copy /B a.dat b.dat

14 First Program in C++: Printing a Line of Text
Dòng 1,2 : // single-line comment Dòng 3: #include <iostream> // preprocessor directive

15 First Program in C++: Printing a Line of Text
Dòng 4: blank line (trình bày rõ ràng, mạch lạc) Dòng 5: // giải thích trước khi bắt đầu chương trình chính Dòng 6: int main()  bắt đầu một chương trình chính Int Keyword { (dòng 7) ; } (dòng 12): thân chương trình chính Dòng 8: std::cout << "Welcome to C++!\n"; // display message Dòng 10: return 0; // thoát khỏi chương trình chính

16 Một vài lưu ý Good programming: Lỗi hay gặp:
Toán tử newline (\n): được sử dụng để xuống dòng Luôn viết chương trình lùi vào trong dấu { } Lỗi hay gặp: Quên dấu ; cuối mỗi câu lệnh  lỗi cú pháp (syntax error), lỗi khi dịch (compiler error), Quên input/output stream header file <iostream> trong khai báo chương trình

17 Ví dụ 2: Tính diện tích hình tròn
#include <stdio.h> int main() { float R; printf("Ban kinh = "); scanf("%f", &R); printf("Dien tich hinh tron: %.3f\n", 3.14 * R*R); return 0; } Kết quả chạy: Ban kinh = 1 Dien tich hinh tron: 3.140

18 Hiển thị ra màn hình Cú pháp: Các ký hiệu định dạng thường dùng:
printf("Chuỗi định dạng", <các giá trị>); Các ký hiệu định dạng thường dùng: Định dạng: %[flags] [width] [.precision]type Ví dụ: %+15.5f Ký hiệu Kiểu %lf, %f, %e, %g double, float %x int (hex) %d int %o int (oct) %c char %u unsigned int %s chuỗi ký tự %p con trỏ

19 Nhập dữ liệu từ bàn phím Cú pháp: Ví dụ:
scanf("Chuỗi định dạng", <địa chỉ biến>); Ví dụ: int tuoi; scanf("%d", &tuoi); float can_nang; scanf("%f", &can_nang); char ten[20]; scanf("%s", ten);

20 2. Biến, kiểu và giá trị

21 Biến (variable) và kiểu (type)
Biến chứa giá trị, có thể thay đổi trong khi chạy Biến cần được khai báo trước khi dùng và có kiểu Phạm vi toàn cục hoặc chỉ trong nội bộ một hàm Trong C chuẩn, biến nội bộ cần được khai báo ở đầu hàm, trước các câu lệnh Khai báo biến: <kiểu> <danh sách các biến>; int a, b, c; unsigned char u; Các kiểu cơ bản: char, int, short, long float, double

22 Câu lệnh gán (assignment)
Thay đổi giá trị của biến bằng giá trị mới Cú pháp: <biến> = <hằng, biến> hoặc <biểu thức> Ví dụ: count = 100; value = cos(x); i = i + 2; Biến có thể được khởi tạo giá trị khi khai báo (nếu không sẽ có giá trị không xác định): int count = 100; char key = 'K';

23 Hằng (constant) Tương tự như biến nhưng giá trị của nó không thể bị thay đổi trong quá trình chạy Khai báo bằng cách thêm từ khoá const ở trước Hằng trong C có chiếm bộ nhớ giống như biến Ví dụ: const double PI = ; const char* name = "Nguyen Viet Tung"; PI = 3.14; /* sẽ báo lỗi */ Cách khác để khai báo hằng: tạo macro  không chiếm bộ nhớ (nhưng không có kiểu) #define PI

24 Các kiểu dữ liệu cơ bản Ký tự trong C được hiểu là số nguyên 8 bit
Toán tử sizeof() tính độ dài của biến hoặc kiểu dữ liệu theo số byte: sizeof(x) sizeof(int) Kiểu Độ dài Loại char 1 Số nguyên, ký tự int (tuỳ thuộc: 2, 4, 8) Số nguyên short 2 long 4 long long 8 float Số thực (dấu chấm động) double void Không có ý nghĩa xác định

25 Ép kiểu (type casting) Là việc chuyển từ một biểu thức có kiểu nào đó sang một kiểu khác Chuyển kiểu ngầm định: float a = 30; int b = 'a'; Chuyển kiểu tường minh: int a = (int)5.6; /* lấy phần nguyên */ float f = (float)1/3; Không phải kiểu nào cũng chuyển được cho nhau char* s = 2.3; /* không dịch được */ int x = "7"; /* dịch được nhưng sai */

26 Kích thước biến, giới hạn giá trị
Số có dấu và không dấu: signed char (8 bits) –128 ~ +127 signed short (16 bits) –32768 ~ signed int (32 bits) – ~ signed long (32 bits) – ~ unsigned char (8 bits) 0 ~ +255 unsigned short (16 bits) 0 ~ unsigned int (32 bits) 0 ~ unsigned long (32 bits) 0 ~ Chú ý: Ngầm định là có dấu Kiểu int có kích thước tuỳ thuộc vào cấu hình

27 Kiểu liệt kê (enum) Dùng để liệt kê các giá trị có thể có của một kiểu
Cú pháp: enum <tên kiểu> { <các giá trị> }; Ví dụ khai báo kiểu: enum DongVat { Meo, Cho, Ho, Bao }; enum Ngay { Thu2 = 2, Thu3, Thu4, Thu5, Thu6, Thu7, CN = 1 }; Sử dụng: enum DongVat dv = Meo; dv = Bao; enum Ngay n = Thu5; An enumeration consists of a set of named integer constants. Meo se tuong duong voi 0. enum DAY /* Defines an enumeration type */ { saturday, /* Names day and declares a */ sunday = 0, /* variable named workday with */ monday, /* that type */ tuesday, wednesday, /* wednesday is associated with 3 */ thursday, friday } workday; saturday va sunday deu co gia tri 0.

28 Kiểu cấu trúc (struct) Khai báo các kiểu phức tạp, chứa các biến con
Cú pháp: struct <tên kiểu> { <các thuộc tính> }; Ví dụ: struct SinhVien { char ten[20]; int nam_sinh; int khoa; }; Sử dụng: struct SinhVien sv = {"Le Duc Tho", 1984, 56}; sv.nam_sinh = 1985; sv.khoa = 54;

29 Định nghĩa tên mới cho kiểu (typedef)
Để dùng với tên mới ngắn gọn hơn, hoặc mang ý nghĩa khác Cú pháp: typedef <kiểu gốc> <tên kiểu định nghĩa>; Ví dụ: typedef double ChieuCao; typedef unsigned char byte; typedef enum DongVat DV; typedef struct { … } SinhVien; Khai báo biến ChieuCao d = 165.5; byte b = 30; DV dv = Cho;

30 Kiểu mảng (array) Chứa các phần tử cùng kiểu trên một vùng nhớ liên tục. Bản chất của mảng là con trỏ tĩnh. Cú pháp: <kiểu> <tên> [ <số phần tử> ]; Ví dụ: int tuoi[6] = { 23, 50, 18, 40, 25, 33 }; Truy xuất phần tử: số thự tự tính từ 0 tuoi[3] = 20; Mảng hai chiều (và nhiều chiều): float ma_tran[10][20]; ma_tran[5][15] = 1.23;

31 Một số kiểu khác Kiểu boolean: Kiểu chuỗi ký tự: Kiểu union
Không có trong C Dùng int/char hoặc enum để thay thế: typedef int bool; typedef enum {false, true} bool; Kiểu chuỗi ký tự: char* ho_ten = "Nguyen Viet Tung"; Kiểu union Chứa các biến thành phần ở cùng một địa chỉ bộ nhớ union color { struct s_color {unsigned char R,G,B,A;}; unsigned int i_color; };

32 Kiểu hợp Có thể định nghĩa kết hợp giữa các kiểu cùng loại hoặc khác loại typedef struct { char ho_ten[20]; unsigned int tuoi; enum {Nam, Nu} gioi_tinh; struct { char thanh_pho[20]; char duong[20]; int so_nha; } dia_chi; } SinhVien;

33 Hàm (function)

34 Khái niệm Hàm là một khối các câu lệnh thực hiện một nhiệm vụ nhất định, và có thể được gọi khi cần Mỗi hàm có một tên (các hàm trong C không được trùng tên nhau), một số tham số, và một giá trị trả về Sử dụng hàm giúp: Chia nhỏ chương trình thành nhiều bài toán con Sử dụng lại trong một hoặc nhiều chương trình Cách khai báo: <kiểu trả về> <tên hàm>(<danh sách các tham số>) { Khai báo các biến dùng cho hàm Các câu lệnh của hàm } Toán tử return dùng để thoát khỏi hàm và trả kết quả

35 Ví dụ Hàm tính tổng hai số
double sum(double x, double y) { double z = x+y; return z; } int main() { double x = 10, y = sum(2,3); printf("x + y = %g", sum(x,y)); return 0; Các tham số và biến nội bộ chỉ giới hạn trong phạm vi của hàm

36 Phạm vi của biến, hằng Biến toàn cục: được khai báo ở ngoài các hàm, có phạm vi trong toàn chương trình và tồn tại trong suốt quá trình chạy Biến địa phương: được khai báo ở trong một hàm hoặc một khối lệnh, chỉ có phạm vi trong hàm/khối đó, và bị huỷ sau khi kết thúc chạy hàm/khối đó Khai báo biến địa phương sẽ “che” mất biến cùng tên khác có phạm vi rộng hơn Trong C, biến địa phương phải được khai báo ở đầu hàm hoặc khối lệnh Ví dụ biến địa phương của hàm: int x = 10, y = 20; /* phải khai báo trước hàm sum() */ int sum() { int z = x+y; return z; } int main() { int x = 1, y = 2; int z = sum(); /* trả về: */ return 0;

37 Biến trong khối lệnh Trong một khối lệnh { … } ta có thể khai thêm biến, biến đó chỉ tồn tại từ khi chương trình chạy vào tới khi thoát khỏi khối lệnh đó Ví dụ: int x = 1, y = 2; int sum(int x, int y) { return x+y; } int a = 1000, b = 2000; int main() { int x = 10, y = 20; { int x = 100, y = 200; x+y; sum(a,b); return 0; EE3490: Kỹ thuật lập trình – HK1 2015/2016 Đào Trung Kiên, cập nhật bởi Nguyễn Việt Tùng – ĐH Bách khoa Hà Nội

38 Biến trong khối lệnh: vòng lặp
Chỉ có phạm vi trong một lần chạy của vòng lặp, mỗi lần lặp sẽ tạo ra biến mới và khởi tạo lại Ví dụ: int x = 20; for (i=0; i<10; i++) { int y = 20; x++; y++; printf("%d %d\n", x, y); } Lop thu 6 het slide nay.

39 Biến static Là biến chỉ có phạm vi địa phương nhưng vẫn tồn tại ngay cả khi chưa vào hoặc đã thoát khỏi hàm/khối Khai báo bằng cách thêm từ khoá static int callCount() { static int count = 0; count++; return count; } Cũng có biến static toàn cục: thuộc nội bộ của một file nguồn static int tic_time = 0; void tic() { tic_time = clock(); int toc() { return clock() - tic_time; Hàm static: tự tìm hiểu thêm

40 Câu lệnh return Kết thúc hàm và trả về một giá trị cho nơi gọi nó
int find(int number, int a[], int n) { int i; for (i=0; i<n; i++) if (number == a[i]) return i; return -1; } Hàm void: không trả về giá trị gì void copy(int *a, int *b, int n) { if (a==NULL || b==NULL || a==b || n==0) return; for (; n>0; n--) *a++ = *b++; Câu lệnh return không có tham số Không cần lệnh return ở cuối hàm

41 Tham số kiểu giá trị và kiểu tham chiếu
Tham số của hàm là biến tạm thời, tạo ra khi gọi và huỷ khi hàm kết thúc  thay đổi giá trị của tham số không ảnh hưởng tới biến nơi gọi void assign10(int x) { x = 10; } int main() { int a = 20; assign10(a); printf("a = %d", a); return 0; } Muốn thay đổi giá trị của biến ở nơi gọi: Dùng con trỏ void assign10(int *x) { *x = 10; } assign10(&a); Tham số con trỏ thường được dùng như một cách khác để trả về thêm giá trị, vì mỗi hàm chỉ có một giá trị trả về theo đúng nghĩa x (int) a copy a x (int*) &a copy

42 Hàm trả về con trỏ int* sum() { } int* sum() { }
Vấn đề với hàm trả về biến địa phương int* sum(int x, int y) { int z = x+y; return &z; } int* p = sum(2, 3); /* sai */ Cấp phát bộ nhớ trong hàm int* z = (int*)malloc(sizeof(int)); *z = x+y; return z; int* p = sum(2, 3); /* ... */ free(p); p z int* sum() { } copy địa chỉ p z int* sum() { } copy *z

43 Nguyên mẫu (prototype) của hàm
Là việc khai báo hàm trước, nội dung của nó được triển khai sau  thường khai báo ở đầu file hoặc trong file .h Ví dụ: double tong(double x, double y); double tich(double x, double y); int main() { double x = 5., y = 10.; tong(x, y); tich(x, y); return 0; } double tong(double x, double y) { return x+y; } double tich(double x, double y) { return x*y; } EE3490: Kỹ thuật lập trình – HK1 2015/2016 Đào Trung Kiên, cập nhật bởi Nguyễn Việt Tùng – ĐH Bách khoa Hà Nội

44 Hàm đệ quy (recursive function)
Là hàm có câu lệnh gọi chính nó Ví dụ 1: giai thừa một số n unsigned int giai_thua(unsigned int n) { if (n <= 1) return 1; return n * giai_thua(n-1); } Ví dụ 2: x mũ n double mu(double x, unsigned int n) { double y; if (n == 0) return 1; y = mu(x, n/2); if (n%2 == 0) return y*y; return y*y*x; Không hiệu quả nếu sinh quá nhiều lệnh gọi  hạn chế

45 Con trỏ hàm Là con trỏ trỏ tới một hàm  là một kiểu dữ liệu trong C, thường được dùng để gọi một hàm chưa biết trước double (*SomeOpt)(double, double); typedef double (*OptFunc)(double, double); OptFunc SomeOpt; Ví dụ: double sum(double x, double y) { return x+y; } double mul(double x, double y) { return x*y; } int main() { double (*SomeOpt)(double, double) = ∑ SomeOpt(2., 5.); /* sum(2., 5.); */ SomeOpt = mul; (*SomeOpt)(2., 5.); /* mul(2., 5.); */ return 0; } Phép gán có thể dùng & hoặc không, gọi cũng có thể dùng * hoặc không

46 Macro Macro là đoạn mã được đại diện bằng một tên, mà mỗi khi tên đó xuất hiện trong chương trình thì sẽ được thay thế bằng đoạn mã tương ứng Định nghĩa macro: dùng #define #define ERROR { printf("Error, exit now!"); exit(-1); } int main(int argc, char* argv[]) { if (argc != 3) ERROR /* … */ return 0; } Macro có thể được thay thế khi định nghĩa macro khác cùng tên Huỷ bỏ macro đã định nghĩa: #undef ERROR Kiểm tra xem macro đã định nghĩa chưa #ifdef ERROR /* ... */ #else #endif

47 Macro (tiếp) Macro có thể có tham số  đôi khi được dùng như hàm
#define MIN(x,y) x<y ? x:y z = MIN(2,4); /* z = 2<4 ? 2:4; */ #define PI #define AREA(R) R*R*PI z = AREA(5); /* z = 5*5*3.1415; */ Chú ý các hiệu ứng phụ #define MUL(x,y) x*y z = MUL(2,4); /* z = 2*4; */ z = MUL(2+1,4); /* z = 2+1*4; */ z = 8/MUL(1+1,2); /* z = 8/1+1*2; */ #define MUL(x,y) ((x)*(y)) z = MUL(2+1,4); /* z = ((2+1)*(4)); */ z = 8/MUL(1+1,2); /* z = 8/((1+1)*(2)); */ #define SQR(x) ((x)*(x)) z = SQR(i); /* z = ((i)*(i)); */ z = SQR(i++); /* z = ((i++)*(i++)); */

48 Thư viện hàm

49 Thư viện hàm Một chương trình có thể được chia nhỏ làm nhiều file, mỗi file chứa một nhóm những hàm liên quan tới một phần của chương trình Một số hàm có thể được dùng trong nhiều chương trình khác nhau  thư viện hàm Một thư viện hàm gồm 2 phần: File header có đuôi .h chứa prototype các hàm có thể dùng được của thư viện File mã nguồn có đuôi .c chứa nội dung các hàm, hoặc file .obj, .lib nếu đã được dịch ra các dạng tương ứng Dùng thư viện hàm trong một file mã nguồn: #include <ten_file.h> /* trong đường dẫn mặc định */ #include "ten_file.h" /* cùng thư mục với file dịch */ Dẫn hướng #include có tác dụng như chèn nội dung file được khai báo vào file đang dịch ở vị trí xuất hiện

50 Lưu ý với tạo và sử dụng file .h
Trong file abcd.h Để tránh lỗi khi bị #include nhiều lần, thêm vào đầu và cuối #ifndef __ABCD_H__ #define __ABCD_H__ /* Nội dung file abcd.h */ #endif Các biến toàn cục phải được khai báo trong file .c, nếu muốn được export thì trong file .h khai báo thêm bằng extern: extern int bien_toan_cuc; Sử dụng file abcd.h #include "abcd.h" /* .h cùng thư mục */ #include <abcd.h> /* .h trong thư mục thư viện */

51 Ví dụ: Thư viện tính diện tích các hình
dientich.h #ifndef __DIENTICH_H__ #define __DIENTICH_H__ extern const double PI; double dt_tron(double r); double dt_elip(double r1, double r2); double dt_vuong(double l); double dt_chu_nhat(double l1, double l2); #endif dientich.c const double PI = ; double dt_tron(double r) { return r*r*PI; } double dt_elip(double r1, double r2) { return r1*r2*PI; } double dt_vuong(double l) { return l*l; } double dt_chu_nhat(double l1, double l2) { return l1*l2; }

52 Một số thư viện chuẩn Tên Chức năng stdio.h
Xuất, nhập với màn hình, file, bàn phím,… ctype.h Kiểm tra các lớp ký tự (chữ số, chữ cái,…) string.h Xử lý chuỗi và bộ nhớ math.h Một số hàm toán học stdlib.h Chuyển đổi dữ liệu số-chuỗi, cấp phát bộ nhớ,… time.h Các hàm về thời gian


Tải xuống ppt "Chương 2: Các kỹ thuật xây dựng chương trình phần mềm"

Các bản thuyết trình tương tự


Quảng cáo bởi Google