1. Trang chủ
  2. » Công Nghệ Thông Tin

bài giảng ký thuật lập trình chương 1 nhập môn kỹ thuật lập nguyễn diệu hương

109 948 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 109
Dung lượng 1 MB

Nội dung

• Tăng cường khả năng lập trình • Hiểu chi tiết về: – Thiết kế chương trình – Cấu trúc dữ liệu, giải thuật, ADT – Đa nhiệm – Mạng... Tham số của hàm cần được chỉ rõ 5.. • Gọi hàm – Cung

Trang 1

Kỹ thuật lập trình

Nguyễn Diệu Hương

huongnd@it-hut.edu.vn

huongnd-fit@mail.hut.edu.vn

Trang 2

Mục đích của môn học

• Hỗ trợ xây dựng chương trình

chính xác, hiệu quả, dễ sửa chữa, tái sử dụng code cao.

• Tăng cường khả năng lập trình

• Hiểu chi tiết về:

– Thiết kế chương trình

– Cấu trúc dữ liệu, giải thuật, ADT

– Đa nhiệm

– Mạng

Trang 3

Yêu cầu môn học

• Bài tập lớn môn học: 30-40% Đánh giá dựa trên:

Trang 5

Tài liệu tham khảo

Prentice-Hall.

Kruse et al., Prentice-Hall.

2/e, Brooks/Cole.

Addison-Wesley

A Weiss, 2/e, Addison Wesley.

Addison-Wesley.

Mehta et al, Chapman & Hall/CRC.

Trang 7

1 Các nguyên tắc lập trình

(Kruse, Chương 1)

Reading: C++ Programming Style Guide

Trang 8

1 1 Thiết kế chương trình

Trang 9

Giới thiệu

• Mục đích:

– Giới thiệu phương pháp và công cụ

lập trình cho những chương trình thực tế

– Đi theo một tiếp cận logic, thống nhất– Nguyên tắc thiết kế chương trình

Trang 10

Xác định mục tiêu của bài toán

• Quyết định mục đích chung

• Chỉ rõ những mục đích cụ thể

• Chia công việc thành các bài toán con cho đến khi có kích thước cô đọng

Trang 11

Thiết kế chương trình

• Tổ chức tốt từng phần

• Mã lệnh phải viết rõ ràng, dễ hiểu.

• Lựa chọn cấu trúc dữ liệu phù hợp

• Phân tích thuật toán

Trang 12

1 2 Phong cách lập trình

Trang 14

Một số chú ý khi đặt tên

1 Lựa chọn cẩn thận tên hàm, lớp,

hằng, biến toàn cục

2 Tên biến cục bộ đơn giản

3 Sử dụng tiền tố/hậu tố cho các tên

có cùng kiểu

4 Tránh đặt tên dễ nhầm lẫn, hoặc

thêm phần đuôi không có ý nghĩa

Trang 15

Chuẩn bị tài liệu hướng dẫn

Trang 17

Một số chú ý khi viết TLHD

3 Giới thiệu mỗi đoạn chương trình

(hàm, khối) với chú thích ngắn gọn vềmục đích và ý nghĩa

4 Chỉ rõ kết thúc của mỗi phần

5 Tránh chú thích quá kỹ không cần thiết

6 Giải thích những câu lệnh không rõ

ràng

7 Phần mã lệnh: cách chương trình hoạt

động, TLHD: tại sao chương trình hoạt động, thực hiện công việc gì

8 Chú ý: Khi chương trình thay đổi, cần

đảm bảo TLHD sẽ thay đổi tương ứng

Trang 18

Ví dụ

int main( ) // Program to play Conway’s game of Life.

/* Pre : The user supplies an initial configuration of living

cells.

Post : The program prints a sequence of pictures showing

the changes in the configuration of living cells according to the rules for the game of Life.

Uses: The class Life and its methods initialize( ), print( ),

and update( ).

The functions instructions( ), user_says_yes( ) */

Trang 19

Định dạng chương trình

• Canh lề giúp chương trình dễ hiểu

Thời gian đọc chương trình lớn hơn rất

nhiều so với viết chương trình

Trang 20

Tinh chỉnh và module hóa

• Tinh chỉnh top-down:

– Bắt đầu bằng viết chương trình chính– Quyết định việc chia các công việc (cho lớp, hàm, CTDL)

– Tiếp tục với các hàm, lớp, CTDL

Trang 21

Tinh chỉnh Top-down – Hướng dẫn

1 Sử dụng lớp để mô hình hóa những khái

Trang 22

Tinh chỉnh Top-down – Hướng

dẫn

2 Mỗi hàm chỉ thực hiện một công việc

duy nhất

3 Mỗi hàm/lớp nên che giấu thông tin

4 Tham số của hàm cần được chỉ rõ

5 Các dữ liệu mà hàm sử dụng:

Æ Giữ cho các mỗi liên hệ càng đơn giản

càng tốt Tránh sử dụng biến toàn cục càng nhiều càng tốt

Æ Nếu sử dụng biến toàn cục, viết hướng

dẫn chi tiết

Trang 23

1 3 Cài đặt, kiểm thử, tinh

chỉnh

Trang 24

Hàm giả

return(true ); }

Trang 25

int grid[maxrow + 2][maxcol + 2];

// allows for two extra rows and columns

int neighbor_count(int row, int col);

};

Trang 26

int Life :: neighbor_count(int row, int col)

/* Pre: The Life object contains a configuration, and the

coordinates row and col define a cell inside its hedge.

Post: The number of living neighbors of the specified cell is

returned */

{

int i, j;

int count = 0;

for (i = row − 1; i <= row + 1; i++)

for (j = col − 1; j <= col + 1; j++)

count += grid[i][j]; /* Increase the count if

Trang 27

void Life :: update( )

/* Pre: The Life object contains a configuration.

Post: The Life object contains the next generation of configuration */

{

int row, col;

int new_grid[maxrow 2][maxcol 2];

for (row = 1; row <= maxrow; row )

for (col = 1; col <= maxcol; col )

for (row = 1; row <= maxrow; row )

for (col = 1; col <= maxcol; col )

grid[row][col] = new_grid[row][col];

}

Trang 28

void Life :: initialize( )

/* Pre: None.

Post: The Life object contains a configuration specified by the user */

{

int row, col;

for (row = 0; row <= maxrow 1; row )

for (col = 0; col <= maxcol 1; col )

grid[row][col] = 0;

cout << "List the coordinates for living cells." << endl;

cout << "Terminate the list with the the special pair -1 -1" << endl;

cin >> row >> col;

while (row != -1 || col != -1) {

if (row >= 1 && row <= maxrow)

if (col >= 1 && col <= maxcol)

Trang 29

void Life :: print( )

/* Pre: The Life object contains a configuration.

Post: The configuration is written for the user */

{

int row, col;

cout << " \nThe current Life configuration is:" << endl; for (row = 1; row <= maxrow; row ) {

for (col = 1; col <= maxcol; col )

Trang 30

for (row = 1; row <= maxrow; row ){

for (col = 1; col <= maxrow; col )

cout << iConfig.neighbor_count(row,

col) ; cout << endl;

}

}

Trang 32

Nguyên tắc kiểm thử chương trình

• Chọn dữ liệu kiểm thử: chất lượng quan trọng hơn số lượng

• 3 phương pháp kiểm thử:

– Hộp đen (Black-box)

– Hộp kính (Glass-box)

– Hộp tíc tắc (Ticking-box)

Trang 33

1 4 Bảo trì chương trình

Trang 34

Bảo trì

• Sau khi chương trình đã đưa vào

sử dụng.

• Sửa đổi và phân tích chương trình

để đáp ứng yêu cầu mới.

• Bảo trì chiếm >50% tổng số công việc.

Trang 35

3 Giao diện thân thiện? Đầu vào/ra?

Nhiều chức năng thay thế? Trợ giúp rõ ràng?

4 Chương trình viết rõ ràng, logic? Cấu

trúc dữ liệu hợp lý?

5 Tài liệu hướng dẫn rõ ràng? (tên, đầu

vào, đầu ra, giải thích)

6 Thời gian chạy và bộ nhớ hiệu quả?

Trang 36

2 Hàm và biến

(Deitel, Chương 6)

Trang 37

• Gọi hàm

– Cung cấp tên hàm và các tham số

– Hàm thực hiện các thao tác và các phéptoán

– Hàm trả lại giá trị kết quả

Trang 39

Biến cục bộ và toàn cục

• Phạm vi biến là vùng (block)

chương trình mà biến được khai báo Không thể truy cập biến địa phương ngoài vùng chương trình này

• Biến toàn cục: phạm vi biến từ vị trí khai báo đến hết chương trình

Trang 40

Sự khác nhau giữa biến cục

bộ và toàn cục

Trang 41

Biến static

• Được khởi tạo ở lần chạy đầu tiên Phạm vi sử dụng:

– Khai báo trong hàm: phạm vi là hàm

mà nó khai báo Nhưng được giữ

nguyên khi ra khỏi hàm và có thể sửdụng lại khi hàm được thực hiện trởlại

– Khai báo ngoài hàm: phạm vi là từ khi khai báo đến cuối file chương trình

Trang 42

1 /* Fig 5.12: fig05_12.c

2 A scoping example */

3 #include <stdio.h>

4

5 void useLocal( void ); /* function prototype */

6 void useStaticLocal( void ); /* function prototype */

7 void useGlobal( void ); /* function prototype */

8

9 int x = 1 ; /* global variable */

10

11 /* function main begins program execution */

12 int main( void )

18 { /* start new scope */

19 int x = 7 ; /* local variable to new scope */

20

21 printf( "local x in inner scope of main is %d\n" , x );

22 } /* end new scope */

23

Global variable with file scope

Variable with block scope

Variable with block scope

Trang 43

24 printf( "local x in outer scope of main is %d\n" , x );

25

26 useLocal(); /* useLocal has automatic local x */

27 useStaticLocal(); /* useStaticLocal has static local x */

28 useGlobal(); /* useGlobal uses global x */

29 useLocal(); /* useLocal reinitializes automatic local x */

30 useStaticLocal(); /* static local x retains its prior value */

31 useGlobal(); /* global x also retains its value */

39 /* useLocal reinitializes local variable x during each call */

40 void useLocal( void )

46 printf( "local x in useLocal is %d before exiting useLocal\n" , x );

47 } /* end function useLocal */

48

Variable with block scope

Trang 44

49 /* useStaticLocal initializes static local variable x only the first time

50 the function is called; value of x is saved between calls to this

59 printf( "local static x is %d on exiting useStaticLocal\n" , x );

60 } /* end function useStaticLocal */

61

62 /* function useGlobal modifies global variable x during each call */

63 void useGlobal( void )

64 {

65 printf( "\nglobal x is %d on entering useGlobal\n" , x );

66 x *= 10 ;

67 printf( "global x is %d on exiting useGlobal\n" , x );

68 } /* end function useGlobal */

Static variable with block scope

Global variable

Trang 45

local x in outer scope of main is 5

local x in inner scope of main is 7

local x in outer scope of main is 5

local x in useLocal is 25 after entering useLocal

local x in useLocal is 26 before exiting useLocal

local static x is 50 on entering useStaticLocal

local static x is 51 on exiting useStaticLocal

global x is 1 on entering useGlobal

global x is 10 on exiting useGlobal

local x in useLocal is 25 after entering useLocal

local x in useLocal is 26 before exiting useLocal

local static x is 51 on entering useStaticLocal

local static x is 52 on exiting useStaticLocal

global x is 10 on entering useGlobal

global x is 100 on exiting useGlobal

local x in main is 5

Trang 46

2 3 Kiểu tham chiếu

Trang 47

Kiểu tham chiếu (reference)

• Tham chiếu là một tên khác của biến

• Được xem như một con trỏ hằng

– không được tham chiếu tới một biến khác

int ival = 1024;

int &refVal = ival; // ok

int &refVal; // error: tham chiếu phải được khởi tạo

// tới một biến nào đó

refVal += 2;

refVal = someVal;

int *p = &refVal; // khởi tạo p là địa chỉ của refVal

Trang 48

int **e = &d;

Dữ liệu của mảng a[ ] sau khi thực hiện những câu lệnh sau?

Trang 49

2 4 Truyền tham số

Trang 50

Truyền tham số

• Có 2 cách truyền tham số:

– Truyền theo giá trị (call/pass by value)– Truyền theo tham chiếu (call/pass by reference)

Trang 51

Truyền theo giá trị và truyền

theo tham chiếu

Truyền theo giá trị:

• Một bản copy của biến được truyền vào tham số của hàm

Truyền theo tham chiếu:

• làm việc với tham số gốc của lời gọi hàm

Trang 52

void SwapWrong( short , short );

Trang 53

Truyền theo tham chiếu

void SwapRef( short &, short & );

Trang 54

Tham biến là kiểu con trỏ

• Cung cấp địa chỉ của biến

• Cho phép thay đổi giá trị của tham số

Trang 55

Ví dụ

The code

void doubleIt( int x,

int * p ) {

p (8200)

x (8196)

16 a

a = 18

Trang 56

Tham biến là con trỏ

void SwapPtr( short *, short * );

Trang 57

Tham số mặc định được chỉ ra trong hàm mẫu

Trang 59

Tham số mặc định

Trang 60

Ví dụ

void modifyArray( int [], int );

int main ()

{

const int arraySize = 5; // size of array a

int a[ arraySize ] = { 0, 1, 2, 3, 4 }; // initialize array a

// pass array a to modifyArray by reference

modifyArray( a, arraySize );

// in function modifyArray, "b" points to the original array "a"

void modifyArray( int b[], int sizeOfArray )

{

// multiply each array element by 2

for ( int k = 0; k < sizeOfArray; k++ ) b[ k ] *= 2;

Trang 61

// In function tryToModifyArray, "b" cannot be used // to modify the original array "a" in main.

void tryToModifyArray( const int b[] )

Trang 62

Hàm trả lại giá trị con trỏ

Trang 63

Chồng hàm – Ví dụ

• Các hàm được chồng:

void getDimensions( int , int ); // 2 void getDimensions( int , double ); // 3 void getDimensions( double , double ); // 4

• CTD sẽ gọi hàm như sau:

int length, width;

double base, height;

getDimensions(length, height); // 3

Trang 66

3 Đệ quy

(Kruse, Chương 5, Sedgewick, Chương 5)

Trang 67

3.1 Tổng quan về đệ quy

Trang 68

Kỹ thuật Đệ quy

• Là một kỹ thuật giải quyết bài toán quan

trọng trong đó:

– Phân tích đối tượng thành các thành phần

nhỏ hơn mang tính chất của chính đối tượng đó.

• Ứng dụng:

– Cú pháp của ngôn ngữ lập trình

– Các thuật toán tìm kiếm và sắp xếp

– Lý thuyết trò chơi (Game theory)

– …

Trang 69

Gọi hàm và Bộ nhớ Stack

Biến địa phương Địa chỉ trở về Các tham số

Activation

Record

Activation Frame

Trang 70

Khung stack cho các lời gọi hàm

M M

A

M A B

M

A

M A C

M A C D

M A C

M A

Stack được cấp phát cho dữ liệu

Thời gian

M M

D

M D D

M D D D

M D D

M D

M

Trang 71

Cây lời gọi hàm

Trang 72

Bài toán Tính giai thừa

• Hàm tính giai thừa cho một số

Trang 73

Chương trình tính giai thừa

Trang 74

Điều kiện của đệ quy

• Giải thuật đệ quy phải thỏa mãn 2

điều kiện:

– Phải có điểm dừng

– Phải làm cho kích thước bài toán thu

nhỏ hơn

Trang 76

Thiết kế giải thuật đệ quy

1 Tìm cách phân rã bài toán

2 Tìm điều kiện dừng

3 Viết sơ bộ thuật toán

4 Kiểm tra sự kết thúc

5 Vẽ cây đệ quy

Trang 77

Cài đặt đệ quy

• Một processor.

• Đồng bộ trên nhiều processor:

Trang 78

Chia để trị

• Giải quyết một bài toán:

– chia công việc thành các phần nhỏ hơn,

– mỗi phần phải dễ giải quyết hơn bài toán ban đầu

Trang 79

Thông số hóa bài toán

void move(int n, int start, int finish, int temp);

/* Pre: There are at least n disks on the tower

start The top disk (if any) on each of

towers temp and finish is larger than any

of the top n disks on tower start.

Post: The top n disks on start have been

moved to finish; temp (used for

temporary storage) has been returned to its starting position

*/

Trang 80

move(n-1, start, temp, finish);

cout << “ Move disk “ << n << “ from ”<<start

<< “ to ”<<finish <<endl;

hanoi(n-1, temp, finish, start);

}

}

Trang 81

Các nhà sư phải chuyển 64 đĩa Giả sử mỗi lần chuyển mất 1 giây, các nhà sư sẽ phải mất 5 * 10 11 năm = 25 lần tuổi của vũ trụ Khi chuyển xong chồng đĩa thì đã đến ngày tận thế!

11

Trang 82

Dãy số Fibonacci

• Dãy số Fibonacci:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34,

trong đó mỗi số là tổng của 2 số đứng trước nó.

• Định nghĩa theo đệ quy:

Trang 85

Tìm kiếm nhị phân

// Tìm kiếm trên một mảng có thứ tự

int bsearchr( const int data[], // input: mảng

int first, // input: chỉ số đầu

int last, // input: chỉ số cuối

int value) // input: giá trị cần tìm // output: chỉ số của phẩn tử tìm được, nếu không trả lại –1

{ int middle = (first + last) / 2;

if (data[middle] == value)

else

}

Trang 86

3.4 Đệ quy đuôi

Trang 87

Đệ quy đuôi

• Hành động cuối cùng của hàm là lời gọi đệ quy tới chính nó

Trang 88

Đệ quy đuôi

Trang 89

Xóa đệ quy đuôi

void move( int n, int start, int finish, int temp)

{

int swap; // temporary storage to swap towers

while (n > 0) { // Replace the if statement with a loop.

move(n − 1, start, temp, finish); // first recursive call

cout << " Move disk " << n << " from " << start

<< " to " << finish << endl;

n−−; // Change parameters to mimic the

// second recursive call.

Trang 90

3.5 Khử đệ quy

Trang 92

for (int i=2; i<= n; i++)

f[i] = f[i-1] + f[i-2];

}

Trang 93

Đệ quy và Vòng lặp

• Hàm đệ quy chỉ có một lời gọi đệ quy

tới chính nó:

• Nhiều lời gọi đệ quy chồng nhau:

• Mọi giải thuật đệ quy đều có thể thay

thế bằng một giải thuật không đệ quy

• Khử đệ quy:

Trang 94

3.6 Kỹ thuật quy hoạch

động

Trang 95

Quy hoạch động – Dynamic Programming

• Là một kỹ thuật để tránh phải tính toán lại cho các giải thuật đệ quy.

• Giải pháp:

Trang 96

Quy hoạch động từ dưới lên

{

f[0] = 0; f[1] = 1;

f[i] = f[i-1] + f[i-2];

}

Trang 97

Quy hoạch động từ trên xuống

// Note: knownF is a global array initialized all zero

int Fib ( int i)

{

if (knownF[i]!=0) return knownF[i]; // First action

if (i < 0) return i; // parameter error

else if (i==0) return knownF[0] = 0;

else if (i==1) return knownF[1] = 1;

else return known[i] = Fib(i-1) + Fib(i-2); // last action

}

Trang 98

Ví dụ

• Tính các hệ số nhị thức:

– Số các tập con gồm k phần tử từ tập gồm N phần tử

Ngày đăng: 19/10/2014, 18:20

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w