1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Mảng, con trỏ và xâu ký tự (lập TRÌNH cơ bản SLIDE)

77 153 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 77
Dung lượng 3,24 MB

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

Nội dung

Số phần tử của mảng Phải xác định cụ thể số phần tử ngay lúc khai báo, không được sử dụng biến hoặc hằng thường  Nên sử dụng chỉ thị tiền xử lý #define để định nghĩa số phần tử mảng..

Trang 1

Chương 10 Mảng, con trỏ và xâu ký tự

Học phần: LẬP TRÌNH CƠ BẢN

Trang 2

Tài liệu tham khảo

2

 Kỹ thuật lập trình C: cơ sở và nâng cao, Phạm Văn Ất, Nhà xuất bản KHKT – Chương 6

 The C programming language 2nd Edition,

Brian Kernighan and Dennis Ritchie, Prentice Hall Software Series – Chương 4

 The C programming language 2nd Edition,

Brian Kernighan and Dennis Ritchie, Prentice Hall Software Series – Chương 5

Trang 3

Nội dung

Mảng một chiều

Mảng hai chiều

Con trỏ và phép toán trên con trỏ

Khai báo con trỏ

Trang 4

PHẦN 1 MẢNG MỘT CHIỀU VÀ NHIỀU CHIỀU

4

Trang 6

 Kích thước được xác định ngay khi khai báo và

không bao giờ thay đổi

 NNLT C luôn chỉ định một khối nhớ liên tục cho một biến kiểu mảng.

6

Trang 7

Khai báo biến mảng (tường minh)

<kiểu cơ sở> <tên biến mảng> [ <số phần tử> ] ;

<kiểu cơ sở> <tên biến mảng> [ <N1> ][ <N2> ] … [ <Nn> ] ;

7

Trang 8

0 1 2

Khai báo biến mảng (tường minh)

Trang 9

Số phần tử của mảng

 Phải xác định cụ thể số phần tử ngay lúc khai báo,

không được sử dụng biến hoặc hằng thường

 Nên sử dụng chỉ thị tiền xử lý #define để định nghĩa số phần tử mảng

Trang 10

Khởi tạo giá trị cho mảng lúc khai báo

 Gồm các cách sau

 Khởi tạo giá trị cho mọi phần tử của mảng

 Khởi tạo giá trị cho một số phần tử đầu mảng

Trang 11

Khởi tạo giá trị cho mảng lúc khai báo

Trang 12

 Hợp lệ : a[0], a[1], a[2], a[3]

 Không hợp lệ : a[-1], a[4], a[5], …

=> Cho kết thường không như mong muốn!

<tên biến mảng> [ <gt cs1> ][ <gt cs2> ] … [ <gt csn> ]

int a[4];

12

Trang 13

for(i=0; i<n; i++) {

printf(“\n Enter value: %d : ”, i+1);scanf(“%d”,&ary[i]);

}for(i=0; i<n; i++) printf(“a[%d]=%d\n“,i, ary[i]);

Trang 14

for(i=0; i<n; i++) {

printf(“\n Enter value: %d : ”, i+1);

scanf(“%d”,&ary1[i]);

} for(i=0; i<n; i++) {

printf(“\n Enter value: %d : ”, i+1);

scanf(“%d”,&ary2[i]);

} for(i=0; i<n; i++)sum[i]=ary1[i]+ary2[i];

for(i=0; i<n; i++) printf(“a[%d]=%d\n“,i, sum[i]) }

Trang 18

Khai báo biến mảng 2 chiều

 Cú pháp

 Tường minh

 Không tường minh (thông qua kiểu)

<kiểu cơ sở> <tên biến>[<N1>][<N2>];

typedef <kiểu cơ sở> <tên kiểu> [<N1>][<N2>];

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

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

18

Trang 19

Khai báo biến mảng 2 chiều

typedef int MaTran10x20 [10][20];

typedef int MaTran5x10 [5][10];

MaTran10x20 a, b;

MaTran11x11 c;

MaTran10x20 d;

19

Trang 20

 Hợp lệ: a[0][0], a[0][1], …, a[2][2], a[2][3]

 Không hợp lệ: a[-1][0], a[2][4], a[3][3]

<tên biến mảng> [ <giá trị cs1> ][ <giá trị cs2> ]

int a[3][4];

0 1 2

0 1 2 3

20

Trang 23

Ví dụ

Nhập mảng có n dòng, m cột các phần tử kiểu nguyên, in các phần tử của mảng ra màn hình (tiếp)

23

// In cac phan tu cua mang

for (i=0; i<m; i++)

Trang 25

Ví dụ

Nhập 2 mảng A, B có n, m cột các phần tử kiểu nguyên, tính và in các phần tử của mảng C = A + B (tiếp)

25

// Tinh cac phan tu cua mang C

for (i=0; i<m; i++)

for (j=0; j<n; j++)

c[i][j] = a[i][j] + b[i][j];

// In cac phan tu cua mang C

for (i=0; i<m; i++)

Trang 26

Bài tập thảo luận trên lớp

1. Nhập mảng có n phần tử kiểu nguyên, tìm phần tử

lớn nhất, nhỏ nhất của mảng.

2. Nhập mảng có n dòng, m cột phần tử kiểu nguyên,

tìm phần tử lớn nhất, nhỏ nhất của mảng

3. Nhập mảng có n phần tử kiểu nguyên, nhập giá trị x,

tìm xem x có trong mảng không, xác định vị trí xuất hiện đầu tiên.

4. Nhập mảng có n dòng, m cột phần tử kiểu nguyên,

nhập giá trị x, tìm xem x có xuất hiện trong mảng

không, xác định các vị trí xuất hiện

26

Trang 27

Bài tập

5. Nhập 2 vector có n phần tử kiểu nguyên, kiểm tra 2

vector đó có vuông góc với nhau không?

9. Nhập ma trận A (n x m) và kiểm tra xem có hai cột

đứng cạnh nhau có tổng bằng nhau hay không?

27

Trang 28

Bài tập

10. Nhập 2 mảng A(n,m), B(m,n) phần tử kiểu số thực,

tính và in mảng C=A*B

11. Nhập 2 mảng A(n,m), B(m,n) phần tử kiểu số thực,

kiểm tra A có là chuyển vị của B hay không

12. Nhập A(n,n) với n không giới hạn trước, kiểm tra A

có là ma trận đơn vị không?

13. Xây dụng ma trận A(n,m), sao cho các phần tử có

giá trị theo dạng xoắn ốc (n, m không giới hạn

trước)

28

Trang 29

PHẦN 2 CON TRỎ VÀ CÁC PHÉP

TOÁN

29

Trang 30

 RAM 512MB được đánh địa chỉ từ 0 đến 2 29 – 1

 RAM 2GB được đánh địa chỉ từ 0 đến 2 31 – 1

30

Trang 31

 Quy trình xử lý của trình biên dịch

 Dành riêng một vùng nhớ với địa chỉ duy nhất để lưu biến đó

 Liên kết địa chỉ ô nhớ đó với tên biến

 Khi gọi tên biến, nó sẽ truy xuất tự động đến ô nhớ đã liên kết với tên biến

 Ví dụ: int a = 0x1234; // Giả sử địa chỉ 0x0B

Trang 32

Khái niệm con trỏ

 Khái niệm

 Địa chỉ của biến là một con số.

 Ta có thể tạo biến khác để lưu địa chỉ của biến này  Con trỏ.

32

Trang 33

Khai báo con trỏ

 p1 là biến con trỏ, trỏ tới vùng nhớ kiểu int (4 bytes) còn p2

là biến kiểu int bình thường.

<kiểu dữ liệu> * <tên biến con trỏ>;

char * ch1, * ch2;

int * p1, p2;

33

Trang 34

Khai báo con trỏ

 Sử dụng từ khóa typedef

 Ví dụ

 Lưu ý khi khai báo kiểu dữ liệu mới

 Giảm bối rối khi mới tiếp xúc với con trỏ

 Nhưng dễ nhầm lẫn với biến thường

typedef <kiểu dữ liệu> * <tên kiểu con trỏ>;

<tên kiểu con trỏ> <tên biến con trỏ>;

typedef int *pint;

int *p1;

pint p2, p3;

34

Trang 35

Con trỏ NULL

 Khái niệm

 Con trỏ NULL là con trỏ không trỏ và đâu cả.

 Khác với con trỏ chưa được khởi tạo.

Trang 36

Khởi tạo kiểu con trỏ

 Khởi tạo

 Khi mới khai báo, biến con trỏ được đặt ở địa chỉ nào đó

(không biết trước)

 chứa giá trị không xác định

 trỏ đến vùng nhớ không biết trước

 Đặt địa chỉ của biến vào con trỏ (toán tử &)

Trang 37

Sử dụng con trỏ

 Truy xuất đến ô nhớ mà con trỏ trỏ đến

 Con trỏ chứa một số nguyên chỉ địa chỉ

 Vùng nhớ mà nó trỏ đến, sử dụng toán tử *

 Ví dụ

int a = 5, *pa = & a;

printf(“%d\n”, pa); // Giá trị biến pa

printf(“%d\n”, *pa); // Giá trị vùng nhớ pa trỏ đến printf(“%d\n”, &pa); // Địa chỉ biến pa

05 00 00 00 00 00 00

37

Trang 38

printf("The value of i is %d\n", i);

printf("The pointer ptr1 contains the value %d\n",*ptr1); }

Kết quả:

The value of i is 3

The pointer ptr1 contains the value 3

38

Trang 40

Gán con trỏ

 Có thể gán biến con trỏ:

int *p1, *p2;

p2 = p1;

– Gán một con trỏ cho con trỏ khác

– «Chỉ định p2 trỏ tới nơi mà p1 đang trỏ tới»

 Dễ bị lẫn với:

*p2 = *p1;

– Gán “giá trị trỏ bởi p1” cho “giá trị trỏ bởi p2”

40

Trang 41

Các phép toán với con trỏ

Phép so sánh hai con trỏ

 Trên con trỏ tồn tại các phép so sánh (= =, !=, <, <=,

>,>=) hai con trỏ bằng nhau là hai con trỏ cùng trỏ tới một đối tượng (có giá trị bằng nhau), ngược lại là khác nhau Con trỏ trỏ tới vùng nhớ có địa chỉ nhỏ hơn là con trỏ nhỏ hơn và ngược lại.

41

Trang 42

Các phép toán với con trỏ (tiếp)

Phép cộng, trừ con trỏ với số nguyên

Giả sử p là con trỏ kiểu T, k là số nguyên  thì (p + k)  cũng là con trỏ kiểu T,  không mất tổng quát  giả sử p trỏ tới phần tử t thì: 

1 p+1 là con trỏ trỏ tới một phần tử kiểu T kế tiếp sau t và p+2 trỏ tới một phần tử kiểu T kế tiếp sau t 2 phần tử,  

2 p -1 là con trỏ trỏ tới một phần tử kiểu T kế tiếp trước t  

3 p -2 trỏ tới một phần tử kiểu T kế tiếp trước t  hai phần tử,  

4 tổng quát: p+k trỏ tới phần tử cách t một khoảng k phần tử kiểu T (nếu k >0 dịch về phía địa chỉ lớn, k<0 thì dịch về phía địa chỉ nhỏ).

42

Trang 43

Các phép toán với con trỏ (tiếp)

Phép cộng, trừ con trỏ với số nguyên

Ví dụ:  

int *p, *q; 

giả sử p trỏ tới phần tử có địa chỉ 180, q trỏ tới phần tử có địa chỉ 160 thì  

 (p-q) = = 10; (kiểu int chiếm 4 byte bộ nhớ)    

 float *r1, *r2;  

 giả sử r1 trỏ tới phần tử có địa chỉ 120, r2 trỏ tới phần tử có địa chỉ 100 thì  

 (r1-r2) = = 5; (kiểu float chiếm 4 byte bộ nhớ).

Lưu ý: Đây là ANSI C, với C chạy trên Win32 có thể kích thước kiểu int, float sẽ lớn

hơn.

Ngoài các phép toán +, - với số nguyên, còn có thể áp dụng các phép toán ++, cùng các phép toán số học khác với con trỏ.

43

Trang 44

Kích thước của con trỏ

 Kích thước của con trỏ

 Con trỏ chỉ lưu địa chỉ nên kích thước của mọi con trỏ là như nhau:

 Môi trường MD-DOS (16 bit): 2 bytes

 Môi trường Windows (32 bit): 4 bytes

Trang 45

Con trỏ và mảng một chiều

(Tự đọc)

 Mảng một chiều

 Tên mảng array là một hằng con trỏ

 không thể thay đổi giá trị của hằng này

 array là địa chỉ đầu tiên của mảng

Trang 46

46

Trang 47

 Truy xuất đến phần tử thứ n của mảng (không sử dụng biến mảng)

Trang 50

 Đối số mảng một chiều truyền cho hàm là địa chỉ

phần tử đầu tiên của mảng.

Con trỏ và mảng một chiều

50

Trang 51

Cấp phát bộ nhớ

 Hàm malloc() là một trong các hàm được sử dụng thường xuyên nhất để thực hiện việc cấp phát bộ nhớ từ vùng nhớ còn tự do

 Tham số của hàm malloc() là một số nguyên xác định số bytes cần cấp phát

51

Trang 52

for(i=0; i<n; i++) {

printf(“\n Enter value: %d : ”, i+1);scanf(“%d”,p+i);

Trang 53

 ptr phải được dùng trước đó với lời gọi hàm

malloc(), calloc(), hoặc realloc()

53

Trang 54

Hàm calloc()

 calloc tương tự như malloc, nhưng điểm khác biệt chính là mặc nhiên giá trị 0 được lưu vào không gian bộ nhớ vừa cấp phát

calloc yêu cầu hai tham số

 Tham số thứ nhất là số lượng các biến cần cấp phát bộ nhớ

 Tham số thứ hai là kích thước của mỗi biến

 Cú pháp:

void *calloc( size_t num, size_t size );

 Ví dụ

54

float *calloc1, *calloc2;

calloc1 = (float *)calloc(3,sizeof(float));

Trang 55

Bài tập thảo luận trên lớp

 Bài 1: Cho đoạn chương trình sau:

Trang 56

Bài tập thảo luận trên lớp

Trang 57

Câu hỏi ôn tập lý thuyết

1.Toán tử nào dùng để xác định địa chỉ của một biến?

2.Toán tử nào dùng để xác định giá trị của biến do con trỏ trỏ đến? 3.Phép lấy giá trị gián tiếp là gì?

4.Các phần tử trong mảng được sắp xếp trong bộ nhớ như thế nào? 5.Cho mảng một chiều data Trình bày 2 cách lấy địa chỉ phần tử đầu tiên của mảng này.

6.Nếu ta truyền cho hàm đối số là mảng một chiều Trình bày hai cách nhận biết phần tử cuối của mảng?

7.Trình bày 6 phép toán có thể thực hiện trên con trỏ?

8.Cho con trỏ p1 trỏ đến phần tử thứ 3 còn con trỏ p2 trỏ đến phần

tử thứ 4 của mảng int p2 – p1 = ?

9.Giống như câu trên nhưng đối với mảng float?

57

Trang 58

Bài tập về nhà

Sử dụng con trỏ viết cac chương trình:

1.Nhập vào một dãy số thực, tìm dãy con tăng có nhiều phần

tử nhất

2.Nhập vào một dãy và kiểm tra xem dãy đã cho là tăng hay không, nếu không hãy sắp xếp lại dãy theo chiều tăng dần

3.Nhập vào một dãy số nguyên, kiểm tra xem dãy là dãy

giảm hay không? Nếu không hãy sắp xếp lại dãy

4.Nhập dãy số nguyên dương Xét xem trong dãy có số

nguyên tố hay không? Nếu có, hãy in ra giá trị, số nguyên tố

bé nhất

58

Trang 59

PHẦN 3 XÂU KÝ TỰ

59

Trang 60

Khái niệm

 Khái niệm

 Kiểu char chỉ chứa được một ký tự Để lưu trữ một xâu ký tự (nhiều ký tự) ta sử dụng mảng (một chiều) các ký tự.

 Xâu ký tự kết thúc bằng ký tự ‘ \0 ’ (null)

 Độ dài xâu ký tự = kích thước mảng – 1

 Ví dụchar hoten[30]; // Dài 29 ký tự

char ngaysinh[9]; // Dài 8 ký tự

60

Trang 61

char s[] = {‘T’, ‘H’, ‘C’, ‘S’, ‘ ’, ‘A’, ‘\0’}; char s[] = “THCS A”; // Tự động thêm ‘\0’

Trang 62

Xuất xâu ký tự

 Sử dụng hàm printf với đặc tả “%s”

 Sử dụng hàm puts

char monhoc[50] = “Tin hoc co so A”;

printf(“%s”, monhoc); // Không xuống dòng

char monhoc[50] = “Tin hoc co so A”;

Trang 63

Nhập xâu ký tự

 Sử dụng hàm scanf với đặc tả “%s”

 Chỉ nhận các ký tự từ bàn phím đến khi gặp ký tự khoảng trắng hoặc ký tự xuống dòng.

 Xâu nhận được không bao gồm ký tự khoảng trắng

và xuống dòng.

char monhoc[50];

printf(“Nhap mot chuoi: “);

scanf(“%s”, monhoc);

printf(“Chuoi nhan duoc la: %s”, monhoc);

Nhap mot chuoi: Tin hoc co so A

Chuoi nhan duoc la: Tin_

63

Trang 64

Nhập xâu ký tự

 Sử dụng hàm gets

 Nhận các ký tự từ bàn phím đến khi gặp ký tự xuống dòng.

 Xâu nhận được là những gì người dùng nhập (trừ ký

tự xuống dòng).

char monhoc[50];

printf(“Nhap mot chuoi: “);

gets(monhoc);

printf(“Chuoi nhan duoc la: %s”, monhoc);

Nhap mot chuoi: Tin hoc co so A

Chuoi nhan duoc la: Tin hoc co so A _

64

Trang 65

Một số hàm thao tác trên xâu ký tự

Trang 66

Hàm sao chép xâu ký tự

Sao chép xâu ký tự src sang xâu ký tự

dest, dừng khi ký tự kết thúc xâu ký tự

strcpy(s, “Tin hoc co so A”); // đúng

char *strcpy(char dest[], const char src[])

char * strcpy (char dest [], const char src [])

66

Trang 67

Hàm tạo bản sao

Tạo bản sao của một xâu ký tự s cho trước Hàm sẽ tự tạo vùng nhớ đủ chứa xâu ký tự s

Thành công: Địa chỉ xâu ký tự kết quả

Thất bài: null

char *s;

s = strdup(“Tin hoc co so A”);

char *strdup(const char s[])

char * strdup (const char s [])

67

Trang 70

Hàm đảo ngược xâu ký tự

Đảo ngược thứ tự các ký tự trong xâu

ký tự (trừ ký tự kết thúc xâu ký tự)

Địa chỉ xâu ký tự kết quả

char s[] = “Tin hoc co so A!!!”;

Trang 71

char s2[] = “hoc tin co so A!!!”;

int kq = strcmp(s1, s2); // => kq

> 0

int strcmp(const char *s1, const char *s2)

int strcmp (const char * s1 , const char * s2 )

71

Trang 72

char s2[] = “TIN HOC CO SO A!!!”;

int kq = stricmp(s1, s2); // => kq

== 0

int stricmp(const char *s1, const char *s2)

int stricmp (const char * s1 , const char * s2 )

72

Trang 73

Hàm nối hai xâu ký tự

Nối xâu ký tự src vào sau xâu ký tự dest

! Xâu dest phải đủ chứa kết quả

Địa chỉ của xâu ký tự được nối

char s1[100] = “Tin hoc”;

char s2[] = “co so A!!!”;

strcat(s1, “ ”);// => “Tin hoc ”strcat(s1, s2); // => “Tin hoc co so A!!!”

char* strcat(char *dest, const char *src)

char* strcat (char * dest , const char * src )

73

Trang 74

Hàm tính độ dài xâu ký tự

Tính độ dài xâu ký tự s

size_t thay cho unsigned (trong

<stddef.h>) dùng để đo các đại lượng không dấu

Độ dài xâu ký tự s

char s[] = “Tin hoc co so A!!!”;

int len = strlen(s); // => 18

size_t* strlen(const char *s)

size_t* strlen (const char * s )

74

Trang 75

Hàm tìm xâu ký tự trong xâu ký tự

Tìm vị trí xuất hiện đầu tiên của s2 trong s1

Thành công: trả về con trỏ đến vị trí xuất hiện đầu tiên của s2 trong s1

Thất bại: trả về nullchar s1[] = “Tin hoc co so A!!!”;

char s2[] = “hoc”;

if (strstr(s1, s2) != null)

printf(“Tim thay!”);

char* strstr(const char *s1, const char *s2)

char* strstr (const char * s1 , const char * s2 )

75

Trang 76

Bài tập

1 Xem thêm một số hàm khác như

atoi, atol, atof : đổi xâu ký tự thành số

itoa, ltoa, ultoa: đổi số thành xâu ký tự

strtok

2 Xóa tất cả các khoảng trắng của xâu ký tự s

3 Đếm xem có bao nhiêu từ trong xâu s Xuất các từ trên các dòng liên tiếp.

4 Tìm từ có chiều dài dài nhất và in ra.

5 Trích ra n ký tự đầu tiên/cuối cùng/bắt đầu tại vị trí pos.

6 Tìm kiếm và thay thế xâu con trong xâu ký tự lớn

7 Viết chương trình nhập vào một xâu ký tự bất kỳ và xoá k ký tự của xâu ký tự bắt

đầu từ vị trí thứ n.

76

Trang 77

Bài tập

8 Nhập xâu họ tên (không quá 40 kí tự), chuẩn hoá xâu đó

(kí tự đầu từ viết hoa, các kí tự khác viết thường, các từ cách nhau 1 dấu cách)

9 Nhập 3 xâu s1, s2, s3 (không quá 40 kí tự), thay xâu s2

bằng s3 trong s1

10 Nhập xâu kí tự Đưa xâu đó về dạng chuẩn (các từ cách

nhau bởi 01 dấu cách, chữ cái đầu xâu viết hoa, các chữ còn lại viết thường,…)

77

Ngày đăng: 29/03/2021, 10:44

TỪ KHÓA LIÊN QUAN

w