1. Trang chủ
  2. » Giáo án - Bài giảng

Kỹ thuật lập trình 2 Bậc cao đẳng

77 3 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

Tiêu đề Kỹ Thuật Lập Trình 2
Trường học Trường Cao Đẳng Công Nghệ Thủ Đức
Chuyên ngành Công Nghệ Thông Tin
Thể loại tài liệu giảng dạy
Năm xuất bản 2016
Thành phố Thủ Đức
Định dạng
Số trang 77
Dung lượng 1,93 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Tài liệu giảng dạy Trang i LỜI TÁC GIẢ Quyển giáo trình này được biên soạn dựa theo đề cương môn học “Kỹ thuật lập trình 2” của Khoa Công nghệ thông tin Trường Cao đẳng Công nghệ Thủ Đ

Trang 1

TRƯỜNG CAO ĐẲNG CÔNG NGHỆ THỦ ĐỨC

TÀI LIỆU GIẢNG DẠY | BẬC CAO ĐẲNG

KỸ THUẬT LẬP TRÌNH 2

| 2016 – Lưu h{nh nội bộ |

Trang 3

Tài liệu giảng dạy Trang i

LỜI TÁC GIẢ

Quyển giáo trình này được biên soạn dựa theo đề cương môn học “Kỹ thuật lập trình 2” của Khoa Công nghệ thông tin Trường Cao đẳng Công nghệ Thủ Đức Giáo trình không tránh khỏi những sai sót về nội dung lẫn hình thức, nhóm biên soạn rất mong nhận được sự g p chân thành từ qu thầy cô và các em

sinh viên để giáo trình hoàn thiện hơn

Trang 4

Tài liệu giảng dạy Trang ii

GIỚI THIỆU

Đ}y là học phần cơ sở chuyên ngành tiếp theo học phần Kỹ thuật lập trình 1, giúp sinh viên ngành Công nghệ thông tin, ngành Truyền thông & Mạng máy tính nâng cao kiến thức, kỹ năng cơ bản về lập trình Từ đó sinh viên ph|t triển tư duy về lập trình và có khả năng giải một số bài toán nâng cao trên máy tính Thông qua các hoạt động học tập, sinh viên còn có thể hoàn thiện dần tính chủ động, tích cực, khả năng tự học, tư duy hệ thống, kỹ năng l{m việc nhóm và thói quen tuân thủ c|c quy định làm việc trong môi trường chuyên nghiệp

Quyển gi|o trình n{y được biên soạn dựa theo đề cương môn học “Kỹ thuật

lập trình 2” của Khoa Công nghệ thông tin Trường Cao đẳng Công nghệ Thủ

Đức

Trang 5

Tài liệu giảng dạy Trang iii

MỤC LỤC

1 1 GIỚI THIỆU M NG HAI CHI U 21.1|

KHAI B O M NG 21.2|

KHỞI TẠO TRỊ B ĐẦU 31.3|

TRUY XUẤT M NG 41.4|

TRUY N M ĐẾN HÀM 71.5|

2 B Ế 9 KHÁI NIỆM CON TR , ĐỊA CHỈ TRONG BỘ NHỚ 102.1|

KHAI BÁO, KHỞI TẠO BIẾN CON TR 102.2|

CÁC PHÉP TOÁN TRÊN CON TR 122.3|

CẤP PHÁT BỘ NHỚ ĐỘNG 152.4|

Ệ VÀ M NG 172.5|

3 ĐỆ 21 KHÁI NIỆ ĐỆ QUI 223.1|

THIẾT KẾ À ĐỆ QUI 243.2|

Ư ƯỢ Đ ỂM CỦ À ĐỆ QUI 263.3|

4 CHUỖI KÍ TỰ 27 KHÁI NIỆM CHUỖI 284.1|

KHAI BÁO BIẾN CHUỖI 284.2|

NHẬP, XUẤT CHUỖI 294.3|

MỘT SỐ HÀM XỬ LÝ CHUỖI 324.4|

CON TR VÀ CHUỖI 364.5|

5 Ấ 38 KHÁI NIỆM CẤU TRÚC 395.1|

KHAI BÁO BIẾN CẤU TRÚC 395.2|

TRUY XUẤT CÁC PHẦN TỬ TRONG CẤU TRÚC 415.3|

CON TR KIỂU CẤU TRÚC 465.4|

6 Ậ 52 KHÁI NIỆM TẬP TIN 536.1|

TRUY XUẤT TẬP TIN TUẦN TỰ 546.2|

TRUY XUẤT TẬ 666.3|

TÀI LIỆU THAM KH O 71

Trang 7

Tài liệu giảng dạy Trang 1

Chương n{y nhằm giới thiệu cho sinh viên các khái niệm vè mảng hai chièu, khai báo và khởi tạo giá trị, truy xuát các phàn tử tre n mảng hai chièu, sử dụng mảng hai chièu làm tham só cho hàm

Trang 8

Tài liệu giảng dạy Trang 2

GIỚI THIỆU MẢNG HAI CHIỀU

1.1|

Mảng là biến lưu trữ một nhóm các phàn tử có cùng kie u dư lie ̣u

Mảng hai chiều (Ma trận) thực chất là mảng một chiều trong đó mỗi phần tử của mảng là một mảng một chiều v{ được truy xuất bởi hai chỉ số dòng và cột

Mảng hai chiều thường dùng để biểu diễn dữ liệu kiểu bảng, kiểu dữ liệu này rất thích hợp cho c|c b{i b{i liên quan đến đồ thị, biểu diễn ảnh, …

Mảng nhiều chiều là mảng có từ hai chiều trở lên

Ví dụ: Mảng 2 chiều các số nguyên có 2 dòng, 3 cột (int arrM[2][3]) biểu diễn trong bộ nhớ máy tính là một vùng nhớ liên tục như sau:

arrM[0][0] arrM[0][1] arrM[0][2] arrM[1][0] arrM[1][1] arrM[1][2]

Dạng biểu diễn trên là một mảng một chiều có hai phần tử, mỗi phần tử này

là một mảng một chiều có 3 phần tử Tất cả tạo thành sáu vùng nhớ liên tục nhau trong bộ nhớ máy tính

Tuy nhiên, ta thường biểu diễn theo dạng bảng để dễ quan sát chỉ số dòng và cột hơn như sau:

arrM[0][0] arrM[0][1] arrM[0][2]

arrM[1][0] arrM[1][1] arrM[1][2]

float arrB[3][3], arrC[2][3];

Cách 2: typedef <kiểu ữ ệ > <tên kiểu>[<số dòng>][<số cột>];

<tên_kiểu> <tên biến>;

Trang 9

Tài liệu giảng dạy Trang 3

<tên_kiểu> <tên biến 1>, <tên biến 2>;

Ví dụ:

typedef int arrA10x20[10][20];

typedef float arrA5x10[5][10];

arrA10x20 a, b; //Ma trận a, b là ma trận số nguyên có 10 dòng, 20 cột

<Kiểu cơ s ><Tên biến mảng>[<Số dòng>][<Số cột>]

= {{tập giá trị dòng 0}, {tập giá trị dòng 1},…, {tập giá trị n-1}};

Ví dụ 3: Khai báo mảng ký tự có tên là arrChar gồm 3 dòng và 2 cột

char arrChar[3][2] = {{‘A’ , ‘B’} , {‘C’ , ‘D’} , {‘E’ , ‘F’}};

Ví dụ 4: Khai báo mảng số thực có tên là arrDouble gồm 6 dòng và 5 cột; phần tử đầu tiên arrDouble[0][0] được khởi tạo là 2.0; các phần tử còn lại có giá trị khởi tạo là 0.0

double arrDouble[6][5] = {2.0};

Trang 10

Tài liệu giảng dạy Trang 4

Câu lệnh sẽ tạo ra mảng arrDouble có 30 phần tử kiểu số thực Phần tử đầu tiên arrDouble[0][0] có giá trị là 2.0, các phần tử còn lại có giá trị là 0

GÁN TRỰC TIẾP GIÁ TRỊ/BIỂU THỨC CHO TỪNG PHẦN TỬ

Trang 11

Tài liệu giảng dạy Trang 5

Truy xuất trực tiếp đến bất kỳ phần tử trong mảng

Ví dụ: Câu lệnh cout << arrA[2][3]; cho phép ta truy xuất ngay đến phần tử ở dòng thứ 2, cột thứ 3 của mảng để lấy giá trị và in ra màn hình

TRUY XUẤT TUẦN TỰ

Truy xuất từng cột theo hướng từ trên xuống dưới và từ trái sang phải -

for (int j = 0; j < nCot; j++)

Ta dùng hai vòng lặp for lồng nhau v{ thay đổi các biến điều khiển vòng lặp

để có c|c hướng duyệt đúng theo yêu cầu bài toán

Trang 12

Tài liệu giảng dạy Trang 6

while (nColumn < 2)

{

while (nRow < 3) {

cout << arrMatrix[nRow][nColumn] << “ “;

nRow++;

} //end while nColumn++;

nRow = 0;

cout << endl;

} //end while

Hiển thị giá trị các phần tử trong mảng arrMatrix ra màn hình theo 3 dòng

và 2 cột theo cách duyệt mảng theo từng cột

Ví dụ 2: Sử dụng vòng lặp for để duyệt mảng theo từng dòng

for (int nColumn = 0; nColumn < 5; nColumn += 1)

cout << arrMatrix [nRow][nColumn] << “\t”;

//end for nRow += 1;

cout << endl;

Trang 13

Tài liệu giảng dạy Trang 7

Có thể sử dụng mảng hai chiều như l{ một tham số cho hàm

Tham số kiểu mảng trong khai báo hàm giống như khai b|o biến mảng -

Ví dụ: void nhapMaTran(int a[50][100]);

Tham số kiểu mảng truyền cho h{m chính l{ địa chỉ của phần tử đầu tiên

void nhapMaTran(int a[][100]);

Số lượng phần tử thực sự truyền qua biến khác

-Ví dụ:

void xuatMaTran(int a[50][100], int m, int n);

void xuatMaTran(int a[][100], int m, int n);

Với m, n lần lượt là số dòng và số cột của ma trận

Lời gọi hàm

void nhapMaTran(int a[][100], int &m, int &n);

void xuatMaTran(int a[][100], int m, int n);

Chương trình sau cho phép nhập và xuất mảng orders Thao tác nhập và

xuất mảng được viết thành hai hàm con với tham số truyền vào là mảng

orders

#include <iostream>

using namespace std;

#define MAXR 30 //số dòng lớn nhất của mảng là 30

#define MAXC 20 //số cột lớn nhất của mảng là 20

Trang 14

Tài liệu giảng dạy Trang 8

//Khai bao prototype

void inputMatrix(int arrA[][MAXC], int nBranch, int nMonth);

void outputMatrix(int arrA[][MAXC], int nBranch, int nMonth);

int main()

{

//khai báo mảng có nbranch dòng và nmonth cột

int arrOrders[MAXR][MAXC];

int nBranch = 0, nMonth = 0;

cout << "Enter number of branches: ";

cin >> nBranch;

cout << "Enter number of months: ";

cin >> nMonth;

inputMatrix(arrOrders, nBranch, nMonth);

outputMatrix(arrOrders, nBranch, nMonth);

for (int i = 0; i < nBranch; i++)

for (int j = 0; j < nMonth; j++) {

cout << "Number of orders for Branch "

//hàm xuất mảng hai chiều

void outputMatrix(int arrA[][ MAXC], int nBranch, int nMonth)

}//end for

}

Trang 15

Tài liệu giảng dạy Trang 9

Chương n{y nhằm giới thiệu cho sinh viên các khái niệm vè con trỏ, địa chỉ bộ nhớ, nội dung trong bộ nhớ; khai báo và sử dụng con trỏ để cấp phát bộ nhớ động; dùng con trỏ làm tham só cho hàm; điều khiển mảng một chiều và mảng hai chiều bằng con trỏ

Trang 16

Tài liệu giảng dạy Trang 10

KHÁI NIỆM CON TRỎ, ĐỊA CHỈ TRONG BỘ NHỚ

2.1|

Con trỏ là một biến chứa địa chỉ của biến khác Nếu pa là con trỏ chứa địa chỉ của biến a ta gọi pa trỏ tới a và a được trỏ bởi pa Thông qua con trỏ ta có thể làm việc được với nội dung của những ô nhớ mà pa trỏ đến

Hình 1: Minh họa biến pa trỏ đến biến a

KHAI BÁO, KHỞI TẠO BIẾN CON TRỎ

2.2|

CÚ PHÁP KHAI BÁO

2.2.1|

<kiể được trỏ> <*tên biến>;

Như vậy khai báo biến con trỏ cũng giống như khai b|o một biến thường ngoại trừ cần thêm dấu * trước tên biến (hoặc sau tên kiểu)

2.2.2.1| Toán tử địa chỉ &

Địa chỉ của biến là số thứ tự của byte đầu tiên trong một dãy các byte liên tiếp mà máy dành cho biến

Trang 17

Tài liệu giảng dạy Trang 11

Trong C/C++, toán tử & là toán tử một ngôi trả về địa chỉ của biến sau nó Ví

Trang 18

Tài liệu giảng dạy Trang 12

 Nếu x l{ mảng ta viết: p = x hoặc p = &x[0], nghĩa l{ p chứa gi| trị l{ địa chỉ phần tử đầu tiên của mảng x

Không gán p cho một hằng địa chỉ cụ thể Ví dụ viết p = 200 là sai

-Phép toán * cho phép lấy nội dung nơi p trỏ đến, ví dụ để gán nội dung nơi

-p trỏ đến cho biến f ta viết f = *-p

Nếu p = &x thì x = *p Từ đó nếu p trỏ đến x thì bất kỳ nơi n{o xuất hiện x

-đều có thể thay được bởi *p v{ ngược lại

Không nên sử dụng con trỏ khi chưa được khởi tạo vì kết quả sẽ không

-lường trước được

CÁC PHÉP TOÁN TRÊN CON TRỎ

2.3|

PHÉP TOÁN GÁN

2.3.1|

Gán địa chỉ một biến cho con trỏ: p = &x;

Phép gán giữa hai con trỏ: p = q; (sau phép toán gán này p, q chứa cùng một địa chỉ, cùng trỏ đến một vùng nhớ)

Ví dụ:

int i = 10; // khai b|o v{ khởi tạo biến i = 10

int *p, *q, *r; // khai b|o 3 con trỏ nguyên p, q, r

Trang 19

Tài liệu giảng dạy Trang 13

p += 5;

cout << *p; // *p = a[5] = 6;

q = p - 4;

cout << *q; // q = a[1] = 2;

for (int i = 0; i < 100; i++)

cout << *(p + i);// in toàn bộ mảng a

2.3.2.2| Phép toán ++, :

p++, p , ++p, p: tương tự p+1 và p-1, có chú ý đến tăng (giảm) trước, sau

Ví dụ sau minh hoạ kết quả kết hợp phép tự tăng giảm với lấy giá trị nơi con trỏ trỏ đến a là một mảng gồm 2 số, p là con trỏ trỏ đến mảng a Các lệnh

dưới đ}y được q ước à độc lập với nhau (tức lệnh sau không bị ảnh

hưởng bởi lệnh trước, đối với mỗi lệnh p luôn luôn trỏ đến phần tử đầu (a[0]) của a

int a[2] = {3, 7};

int *p = a;

(*p)++; // tăng (sau) gi| trị nơi p trỏ: tăng a[0] th{nh 4

++(*p); // tăng (trước) giá trị nơi p trỏ: tăng a[0] thành 4

*(p++); // lấy giá trị nơi p trỏ (3) v{ tăng trỏ p

*(++p); // tăng trỏ p, p->a[1] và lấy giá trị nơi p trỏ (7)

 Phân biệt *(p++) và *(++p):

o Các phép toán tự tăng giảm cũng l{ một ngôi, mức ưu tiên của chúng l{ cao hơn c|c phép to|n hai ngôi kh|c v{ cao hơn phép lấy giá trị (*) Cụ thể:

Ví dụ:

int i, j; // khai báo 2 biến nguyên i, j

int *p, *q; // khai báo 2 con trỏ nguyên p, q

p = &i; // cho p trỏ tới i

q = &j; // cho q trỏ tới j

Trang 20

Tài liệu giảng dạy Trang 14

cout << &i; // hỏi địa chỉ biến i

cout << q; //hỏi địa chỉ biến j (thông qua q)

*q = 5; // gán j bằng 5 (thông qua q)

i++; cout << i; // tăng i v{ hỏi i, i = 3

(*q)++; cout << j; // tăng j (thông qua q) v{ hỏi j, j = 6

(*p) = (*q) * 2 + 1; // gán lại i (thông qua p)

cout << i; // 13

Qua ví dụ trên ta thấy mọi thao tác với i l{ tương đương với *p, với j l{ tương đương với *q và ngược lại

2.3.2.3| Hiệu của 2 con trỏ

Phép toán này chỉ thực hiện được khi p và q là hai con trỏ cùng trỏ đến các phần tử của một dãy dữ liệu n{o đó trong bộ nhớ (ví dụ cùng trỏ đến mo ̣t mảng dữ liệu) Khi đó hiệu p - q là số phần tử giữa p và q (chú ý p - q không phải là hiệu của hai địa chỉ mà là số phần tử giữa p và q)

Ví dụ: giả sử p và q là 2 con trỏ nguyên, p có địa chỉ 200 v{ q có địa chỉ 208 Khi đó p - q = -4 và q - p = 4 (4 là số thành phần nguyên từ địa chỉ 200 đến 208)

2.3.2.4| Phép toán so sánh

C|c phép to|n so s|nh cũng được áp dụng đối với con trỏ, thực chất là so sánh giữa địa chỉ của hai vùng nhớ được trỏ bởi các con trỏ này Thông thường các phép so sánh <, <=, >, >= chỉ áp dụng cho hai con trỏ trỏ đến phần tử của cùng một mảng dữ liệu n{o đó Thực chất của phép so sánh này chính là so sánh chỉ số của hai phần tử được trỏ bởi hai con trỏ đó

Trang 21

Tài liệu giảng dạy Trang 15

CẤP PHÁT BỘ NHỚ ĐỘNG

2.4|

CẤP PHÁT ĐỘNG VÀ CẤP PHÁT TĨNH

2.4.1|

Cấp phát tĩnh (static memory allocation): khi khai báo biến, mảng, cấu

trúc bắt buộc phải khai b|o trước cần bao nhiêu dung lượng bộ nhớ để lưu trữ Trong suốt quá trình thực thi chương trình, khối lượng bộ nhớ này sẽ bị chương trình chiếm dụng và không thể thay đổi kích thước Điều này dẫn đến việc hao tốn bộ nhớ m|y tính khi chương trình sử dụng không hết hoặc chương trình không thể tiếp tục chạy trong trường hợp dung lượng bộ nhớ d{nh cho chương trình đ~ bị dùng hết

Cấp phát động (dynamic memory allocation): khắc phục được hạn chế

của việc cấp ph|t tĩnh, khi dùng kỹ thuật cấp ph|t động lập trình viên không cần phải khai b|o trước kích thước biến mảng, cấu trúc Khi chương trình cần bao nhiêu sẽ cấp phát bấy nhiêu và có thể giải phóng bộ nhớ khi không cần dùng đến nữa

Trang 22

Tài liệu giảng dạy Trang 16

q = new float[100]; // cấp phát vùng nhớ chứa được 100 số thực

Khi gặp toán tử new, chương trình sẽ tìm trong bộ nhớ một lượng ô nhớ còn trống và liên tục với số lượng đủ theo yêu cầu và cho p trỏ đến địa chỉ (byte đầu tiên) của vùng nhớ này Nếu không có vùng nhớ với số lượng như vậy thì việc cấp phát là thất bại và p = NULL (NULL là một địa chỉ rỗng, không xác định) Do vậy ta có thể kiểm tra việc cấp phát có thành công hay không thông qua kiểm tra con trỏ p bằng hay khác NULL

2.4.1.2| Toán tử thu hồi bộ nhớ delete

Để giải phóng bộ nhớ đ~ cấp phát cho một biến (khi không cần sử dụng nữa)

ta sử dụng câu lệnh delete

delete p; // p là con trỏ được cấp phát bằng toán tử new

v{ để giải phóng toàn bộ mảng được cấp pháp thông qua con trỏ p ta dùng câu lệnh:

int *head, *p, *q, n, tam;// head trỏ đến (đ|nh dấu) đầu dãy

cout << "Cho biết số số hạng của dãy: ";

cin >> n;

head = new int[n]; // cấp phát bộ nhớ chứa n số nguyên

for (p = head; p < head + n; p++) // nhập dãy

Trang 23

Tài liệu giảng dạy Trang 17

{

for (q = p + 1; q < head + n; q++)

if (*q < *p) {

2.5.1.1| Con trỏ trỏ đến mảng một chiều

int a[MAX]; //khai báo mảng một chiều a

int *p; //khai báo con trỏ p

p = a; // hoặc p = &a[0]: p đến phần tử a[0]

2.5.1.2| Con trỏ trỏ đến mảng hai chiều

int a[MAXR][MAXC]; //khai báo mảng hai chiều a

int *p; //khai báo con trỏ p

Tương tự, nếu p trỏ đến mảng a thì p+i l{ địa chỉ thành phần thứ i của mảng

a v{ do đó *(p+i) = a[i] = *(a+i)

Nếu i = 2 thì *(p + 2) = a[2] = *(a + 2) = giá trị phần tử thứ ba của mảng a

Trang 24

Tài liệu giảng dạy Trang 18

Hình 3: Minh họa con trỏ trên mảng một chiều

Để in toàn bộ mảng thông qua con trỏ, ta viết như sau:

C|ch 2: thay đổi p

-for (p = a; p <= a + 4; p++) cout << *p;

Đối với cách 2 con trỏ sẽ dịch chuyển dọc theo mảng a bắt đầu từ địa chỉ a (phần tử đầu tiên) đến phần tử cuối cùng Tại bước thứ i, p sẽ trỏ vào phần

tử a[i], do đó ta chỉ cần in giá trị *p Để kiểm tra khi n{o p đạt đến phần tử cuối cùng, ta có thể so sánh p với địa chỉ cuối mảng chính l{ địa chỉ đầu mảng cộng thêm số phần tử trong a và trừ 1 (tức a+4 trong ví dụ trên)

SỬ DỤNG CON TRỎ ĐỂ TRUY XUẤT CÁC PHẦN TỬ TRÊN MẢNG

2.5.3|

HAI CHIỀU

Thực tế, bộ nhớ m|y tính lưu trữ các phần tử của mảng hai chiều thành một dãy các ô nhớ liên tiếp giống như mảng một chiều Vì vậy, việc sử dụng con trỏ để điều khiển mảng hai chiều có m dòng và n cột tương tự như với mảng một chiều có mxn phần tử

Cho p trỏ đến mảng hai chiều a[3][3].Như vậy:

Trang 25

Tài liệu giảng dạy Trang 19

Như vậy để truy cập đến phần tử thứ a[i][j] ta dùng phép toán *(p+ i*m + j),

Ví dụ: ta viết lại ứng dụng của Công ty Mambo trong chương 1 mục 1.5 nhưng sử dụng con trỏ p để thao tác trên mảng mảng thay vì là thao tác trực tiếp trên mảng orders Như vậy giá trị phần tử orders[region][month] sẽ được thay bằng *( *(p+region*3+month)

for (int nRegion = 0; nRegion < 4; nRegion += 1)

for (int nMonth = 0; nMonth < 3; nMonth += 1)

Trang 26

Tài liệu giảng dạy Trang 20

cout << "Region " << nRegion + 1

system("pause");

return 0;

}

Trang 27

Tài liệu giảng dạy Trang 21

Chương n{y nhằm giúp sinh vie n có the pha n loại đe ̣ quy, nha ̣n biét các bài toán đe ̣ quy và sử dụng ky thua ̣t đe ̣ quy đe giải mo ̣t só bài toán đơn giản

Trang 28

Tài liệu giảng dạy Trang 22

KHÁI NIỆM ĐỆ QUI

Ví dụ, bài toán tính tổng từ 1 đến n, với n là số nguyên không âm:

Tính S (n) = 1 + 2 + 3 + … + (n – 1) + n

Ta nhận thấy: 1 + 2 + 3 + … + (n – 1) = S (n – 1)

 S (n) = S (n – 1) + n: Bước đệ qui

Hơn nữa, S (0) = 0: Điều kiện dừng

Vậy, bài toán tồn tại bước đệ qui v{ có điều kiện dừng

Một h{m được gọi l{ đệ qui nếu bên trong thân của h{m đó có lời gọi hàm lại chính nó một cách trực tiếp hay gián tiếp

Khi thực hiện một h{m đệ qui, hàm sẽ phải chạy rất nhiều lần, trong mỗi lần chạy chương trình sẽ tạo một tập biến cục bộ mới trên ngăn xếp (c|c đối số, các biến riêng khai b|o trong h{m) độc lập với lần chạy trước đó, do đó dễ g}y tr{n ngăn xếp Vì vậy đối với những bài toán có thể giải được bằng phương ph|p lặp thì không nên dùng đệ qui

PHÂN LOẠI ĐỆ QUI

… … Lời gọi Hàm2 …

… … }

ĐQ gián tiếp

… Hàm2(…) {

… … Lời gọi Hàmx …

… … }

Trang 29

Tài liệu giảng dạy Trang 23

Trang 30

Tài liệu giảng dạy Trang 24

Bước 1 - Phân tích: Ph}n tích b{i to|n th{nh b{i to|n đồng dạng nhưng đơn

giản hơn v{ dừng lại ở b{i to|n đồng dạng đơn giản nhất có thể x|c định ngay kết quả

Bước 2 - Thế ngược: Xác định kết quả b{i to|n đồng dạng từ đơn giản đến

phức tạp để có kết quả cuối cùng

CẤU TR C HÀM ĐỆ QUI

3.2.3|

Một h{m thông thường gồm 2 phần sau:

<Kiểu_trả_về> <Tên hàm>(<Tham số>)

Trang 31

Tài liệu giảng dạy Trang 25

{

if (<Điều kiện dừng>)

{

… return <Giá trị>;

Phần đệ qui (recursion step): phần sử dụng thuật

to|n đang được định nghĩa

Để tính n! ta có thể dùng phương ph|p lặp như sau:

long tinhGiaiThua (int n)

if (n==0) return 1; //điều kiện dừng

return tinhGiaiThua(n-1)*n; // bước đệ qui

if (n==0) return 1; //điều kiện dừng

return tinhGiaiThua(n-1)*n; // bước đệ qui

}

int main()

{

Trang 32

Tài liệu giảng dạy Trang 26

 Tiết kiệm thời gian thực hiện m~ nguồn

 Một số b{i to|n rất khó giải nếu không dùng đệ qui

Nhược điểm:

- Tốn nhiều bộ nhớ, thời gian thực thi l}u

 Một số tính to|n có thể bị lặp lại nhiều lần

Trang 33

Tài liệu giảng dạy Trang 27

Trang 34

Tài liệu giảng dạy Trang 28

KHÁI NIỆM CHUỖI

4.1|

Chuỗi ký tự là một mảng một chiều mà mỗi phần tử trong mảng là một ký tự

HẰNG CHUỖI

4.1.1|

Hằng chuỗi là một hoặc một số các ký tự đặt trong cặp dấu nháy kép Trong

bộ nhớ hằng chuỗi được lưu th{nh một dãy byte liên tục và kết thúc bằng ký

tự \0 Ví dụ chuỗi “Thu Duc” được lưu trữ trong bộ nhớ như sau:

Lưu ý “A” v{ ‘A’ có ý nghĩa kh|c nhau như sau:

“A” l{ một hằng chuỗi chiếm 2 buyte trong bộ nhớ

‘A’ l{ một ký tự nên chỉ chiếm 1 byte trong bộ nhớ Vì vậy có thể thực hiện phép to|n ‘A’+1 nhưng không thể l{m được như vậy đối với “A”

BIẾN CHUỖI

4.1.2|

Biến chuỗi là biến có thể nhận những giá trị chuỗi khác nhau Muốn sử dụng biến chuỗi chúng ta phải khai báo nó Biến chuỗi được khai báo theo quy cách khai báo một mảng các ký tự

KHAI BÁO BIẾN CHUỖI

4.2|

Cú pháp:

char <tên x}u>[độ dài]; // không khởi tạo

char <tên x}u>[độ dài] = xâu kí tự; // có khởi tạo

char <tên xâu>[] = xâu kí tự; // có khởi tạo

Ví dụ:

char szHoTen1[30];

char szHoTen2[30] = “Nguyen Van A”;

char szHoTen3[] = “Nguyen Van A”;

Các câu lệnh khai báo trên tạo ra các mảng ký tự có độ dài khác nhau Cụ thể: Mảng szHoTen1 chiếm 30 byte chứa tối đa 29 ký tự

Trang 35

Tài liệu giảng dạy Trang 29

Kết quả như sau:

Trường hợp có khoảng trắng thì các ký tự phía sau khoảng trắng đầu tiên sẽ

Trang 36

Tài liệu giảng dạy Trang 30

cin.get(tên biến chuỗi , số_ký tự_tố _đa_của_mảng)

Theo câu lệnh này máy sẽ thực hiện c|c bước tương tự cin >> nhưng cho phép đọc ký tự khoảng trắng vào phần tử của chuỗi

Kết quả ký tự trắng có thể được lưu v{o mảng::

Ví dụ sau minh họa trường hợp đoạn chương trình sử dụng nhiều lệnh cin.get() liên tiếp nhau gây nên hiện tượng trôi câu lệnh đọc chuỗi

char szHoten1[20], szHoten2[20];

cout << "Nhap vao ho ten nguoi thu 1: " << "\n";

Trang 37

Tài liệu giảng dạy Trang 31

Để khắc phục tình trạng này ta dùng một trong hai cách là dùng hàm cin.ignore(1) để bỏ qua ký tự Enter hoặc dùng cin.get(c) để thu lấy ký tự enter

char szHoten1[20], szHoten2[20];

cout << "Nhap vao ho ten nguoi thu 1: " << "\n";

cin.get(szHoten1,20);

cin.ignore(1); //Bỏ qua ký tự Enter

cout << "Nhap vao ho ten nguoi thu 2: " << "\n";

Trang 38

Tài liệu giảng dạy Trang 32

int main()

{

char szHoten1[20], szHoten2[20], c;

cout << "Nhap vao ho ten nguoi thu 1: " << "\n";

cin.get(szHoten1,20);

cin.get(c); //Bỏ qua ký tự Enter

cout << "Nhap vao ho ten nguoi thu 2: " << "\n";

Ví dụ:

char s[10], t[10];

t = "Face"; // không được dùng

strcpy(t, "Face"); // được, gán "Face" cho t

Ngày đăng: 11/10/2022, 23:20

HÌNH ẢNH LIÊN QUAN

Hình 1: Minh họa biến pa trỏ đến biến a - Kỹ thuật lập trình 2 Bậc cao đẳng
Hình 1 Minh họa biến pa trỏ đến biến a (Trang 16)
Hình 3: Minh họa con trỏ trên mảng một chiều - Kỹ thuật lập trình 2 Bậc cao đẳng
Hình 3 Minh họa con trỏ trên mảng một chiều (Trang 24)