HC VIN KTQS KHOA CNG NGH THNG TIN

  • Slides: 77
Download presentation
HỌC VIỆN KTQS KHOA CÔNG NGHỆ THÔNG TIN Chương 7. Mảng, con trỏ và

HỌC VIỆN KTQS KHOA CÔNG NGHỆ THÔNG TIN Chương 7. Mảng, con trỏ và xâu ký tự Học phần: LẬP TRÌNH CƠ BẢN

Tài liệu tham khảo Kỹ thuật lập trình C: cơ sở và nâng cao,

Tài liệu tham khảo 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 2 nd Edition, Brian Kernighan and Dennis Ritchie, Prentice Hall Software Series – Chương 4 The C programming language 2 nd Edition, Brian Kernighan and Dennis Ritchie, Prentice Hall Software Series – Chương 5 2 Chương 7 - Phần 1

Nội dung Mảng một chiều Mảng hai chiều Con trỏ và phép toán trên

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ỏ Phép gán con trỏ Truy xuất giá trị qua con trỏ Con trỏ và mảng Cấp phát vùng nhớ cho con trỏ Xâu ký tự 3 Khái niệm Khởi tạo Các thao tác trên xâu ký tự Chương 7 - Phần 1

PHẦN 1. MẢNG MỘT CHIỀU VÀ NHIỀU CHIỀU 4 Chương 7 - Phần 1

PHẦN 1. MẢNG MỘT CHIỀU VÀ NHIỀU CHIỀU 4 Chương 7 - Phần 1

Mảng một chiều Khái niệm Khai báo Truy xuất dữ liệu 5 Chương 7

Mảng một chiều Khái niệm Khai báo Truy xuất dữ liệu 5 Chương 7 - Phần 1

Dữ liệu kiểu mảng Khái niệm Là một kiểu dữ liệu có cấu trúc

Dữ liệu kiểu mảng Khái niệm Là một kiểu dữ liệu có cấu trúc do người lập trình định nghĩa. Biểu diễn một dãy các biến có cùng kiểu. Ví dụ: dãy các số nguyên, dãy các ký tự… 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 Chương 7 - Phần 1

Khai báo biến mảng (tường minh) Tường minh <kiểu cơ sở> <tên biến mảng>[<số

Khai báo biến mảng (tường minh) 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>[<N 1>][<N 2>]…[<Nn>]; <N 1>, …, <Nn> : số lượng phần tử của mỗi chiều. Lưu ý 7 Phải xác định <số phần tử> cụ thể (hằng) khi khai báo. Mảng nhiều chiều: <tổng số phần tử> = N 1*N 2*…*Nn Bộ nhớ sử dụng = <tổng số phần tử>*sizeof(<kiểu cơ sở>) Một dãy liên tục có chỉ số từ 0 đến <tổng số phần tử>-1 Chương 7 - Phần 1

Khai báo biến mảng (tường minh) Ví dụ int Mang 1 Chieu[10]; 0 1

Khai báo biến mảng (tường minh) Ví dụ int Mang 1 Chieu[10]; 0 1 2 3 4 5 6 7 8 9 Mang 1 Chieu int Mang 2 Chieu[3][4]; 0 1 2 Mang 2 Chieu 0 1 2 8 Chương 7 - Phần 1 10 11

Khai báo biến mảng (không tường minh) Cú pháp Không tường minh (thông qua

Khai báo biến mảng (không tường minh) Cú pháp Không tường minh (thông qua khai báo kiểu) typedef <kiểu cơ sở> <tên kiểu mảng>[<số phần tử>]; typedef <kiểu cơ sở> <tên kiểu mảng>[<N 1>]…[<Nn>]; <tên kiểu mảng> <tên biến mảng>; Ví dụ typedef int Mang 1 Chieu[10]; typedef int Mang 2 Chieu[3][4]; Mang 1 Chieu m 1, m 2, m 3; Mang 2 Chieu m 4, m 5; 9 Chương 7 - Phần 1

Số phần tử của mảng Phải xác định cụ thể số phần tử ngay

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 int n 1 = 10; int a[n 1]; const int n 2 = 20; int b[n 2]; Nên sử dụng chỉ thị tiền xử lý #define để định nghĩa #define n 1 mảng 10 số phần tử #define n 2 20 int a[n 1]; int b[n 1][n 2]; 10 // int a[10]; // int b[10][20]; Chương 7 - Phần 1

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

Khởi tạo giá trị cho mảng lúc khai báo Gồm cách sau Khởi tạo giá trị cho mọi phần tử của mảng int a[4] = {2912, 1706, 1506, 1904}; a 1 2 3 2912 1706 1506 1904 Khởi tạo giá trị cho một số phần tử đầu mảng int a[4] = {2912, 1706}; a 11 0 0 1 2 3 2912 1706 0 0 Chương 7 - Phần 1

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

Khởi tạo giá trị cho mảng lúc khai báo Gồm cách sau Khởi tạo giá trị 0 cho mọi phần tử của mảng int a[4] = {0}; a 0 1 2 3 0 0 Tự động xác định số lượng phần tử int a[] = {2912, 1706, 1506, 1904}; a 12 0 1 2 3 2912 1706 1506 1904 Chương 7 - Phần 1

Truy xuất đến một phần tử Thông qua chỉ số <tên biến mảng>[<gt cs

Truy xuất đến một phần tử Thông qua chỉ số <tên biến mảng>[<gt cs 1>][<gt cs 2>]…[<gt csn>] Ví dụ Cho mảng như sau 0 1 2 int a[4]; Các truy xuất 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! 13 Chương 7 - Phần 1 3

Gán dữ liệu kiểu mảng Không được sử dụng phép gán thông thường mà

Gán dữ liệu kiểu mảng Không được sử dụng phép gán thông thường mà phải gán trực tiếp giữa các phần tử tương ứng <biến mảng đích> = <biến mảng nguồn>; //sai <biến mảng đích>[<chỉ số thứ i>] = <giá trị>; Ví dụ #define MAX 3 typedef int Mang. So[MAX]; Mang. So a = {1, 2, 3}, b; b = a; // Sai for (int i = 0; i < 3; i++) b[i] = a[i]; 14 Chương 7 - Phần 1

Ví dụ Nhập mảng có n phần tử kiểu nguyên, in ra các phần

Ví dụ Nhập mảng có n phần tử kiểu nguyên, in ra các phần tử của 1. #include <stdio. h> 2. mảng #define MAX 1000 3. void main() 4. { int ary[MAX]; 5. int i, n; 6. printf(“Nhap n = ”); 7. scanf(“%d”, &n); 8. for(i=0; i<n; i++) { 9. printf(“n Enter value: %d : ”, i+1); 10. scanf(“%d”, &ary[i]); 11. } 12. for(i=1; i<10; i++) printf(“a[%d]=%dn“, i, 13. ary[i]) 14. } 15. 15 Chương 7 - Phần 1

Ví dụ Nhập 2 mảng có n phần tử kiểu nguyên, tính và in

Ví dụ Nhập 2 mảng có n phần tử kiểu nguyên, tính và in ra 1. #include <stdio. h> 2. tổng #define MAX 1000 3. void main() 4. { 5. int ary 1[MAX], ary 2[MAX], sum[MAX]; 6. int i, n; 7. printf(“Nhap n = ”); scanf(“%d”, &n); 8. for(i=0; i<n; i++) { 9. printf(“n Enter value: %d : ”, i+1); 10. scanf(“%d”, &ary 1[i]); 11. } 12. for(i=0; i<n; i++) { 13. printf(“n Enter value: %d : ”, i+1); 14. scanf(“%d”, &ary 2[i]); 15. } 16. for(i=1; i<10; i++)sum[i]=ary 1[i]+ary 2[i]; 17. for(i=1; i<10; i++) printf(“a[%d]=%dn“, i, sum[i]) 18. } 16 Chương 7 - Phần 1 mảng

Mảng hai chiều Khái niệm Khai báo Truy xuất dữ liệu 17 Chương 7

Mảng hai chiều Khái niệm Khai báo Truy xuất dữ liệu 17 Chương 7 - Phần 1

Ma Trận 0 1 … n-1 0 0 m-1 18 0 An … …

Ma Trận 0 1 … n-1 0 0 m-1 18 0 An … … Am, n … n-1 Chương 7 - Phần 1

Ma Trận 0 … n-1 0 … … n-1 dòng = cột dòng >

Ma Trận 0 … n-1 0 … … n-1 dòng = cột dòng > cột dòng < cột 0 0 0 … n-1 0 … … … n-1 n-1 dòng + cột = n-1 19 0 n-1 0 An … n-1 … An 0 dòng + cột > n-1 dòng + cột < n-1 Chương 7 - Phần 1

Khai báo biến mảng 2 chiều Cú pháp Tường minh <kiểu cơ sở> <tên

Khai báo biến mảng 2 chiều Cú pháp Tường minh <kiểu cơ sở> <tên biến>[<N 1>][<N 2>]; Không tường minh (thông qua kiểu) typedef <kiểu cơ sở> <tên kiểu>[<N 1>][<N 2>]; <tên kiểu> <tên biến>; <tên kiểu> <tên biến 1>, <tên biến 2>; 20 Chương 7 - Phần 1

Khai báo biến mảng 2 chiều Ví dụ Tường minh int a[10][20], b[10][20]; int

Khai báo biến mảng 2 chiều Ví dụ Tường minh int a[10][20], b[10][20]; int c[5][10]; int d[10][20]; Không tường minh (thông qua kiểu) typedef int Ma. Tran 10 x 20[10][20]; typedef int Ma. Tran 5 x 10[5][10]; Ma. Tran 10 x 20 a, b; Ma. Tran 11 x 11 c; Ma. Tran 10 x 20 d; 21 Chương 7 - Phần 1

Truy xuất đến một phần tử Thông qua chỉ số <tên biến mảng>[<giá trị

Truy xuất đến một phần tử Thông qua chỉ số <tên biến mảng>[<giá trị cs 1>][<giá trị cs 2>] 0 Ví dụ 0 Cho mảng 2 chiều như sau 1 int a[3][4]; 22 2 Các truy xuất 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] Chương 7 - Phần 1 1 2 3

Gán dữ liệu kiểu mảng Không được sử dụng phép gán thông thường mà

Gán dữ liệu kiểu mảng Không được sử dụng phép gán thông thường mà phải gán trực tiếp giữa các phần tử <biến mảng đích> = <biến mảng nguồn>; //sai <biến mảng đích>[<giá trị cs 1>][giá trị cs 2] = <giá trị>; Ví dụ int a[5][10], b[5][10]; b = a; // Sai int i, j; for (i = 0; i < 5; i++) for (j = 0; j < 10; j++) b[i][j] = a[i][j]; 23 Chương 7 - Phần 1

Ví dụ Nhập mảng có n dòng, m cột các phần tử kiểu nguyên,

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 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 24 #include <stdio. h> #define MAX 1000 void main() { int a[MAX]; int i, n, m; //Nhap mang printf(“Nhap n = ”); scanf(“%d”, &n); printf(“Nhap m = ”); scanf(“%d”, &m); for (i=0; i<m; i++) for (j=0; j<n; j++) { printf(“Nhap a[%d]: ”, i, j); scanf(“%d”, &a[i][j]); } Chương 7 - Phần 1

Ví dụ Nhập mảng có n dòng, m cột các phần tử kiểu nguyên,

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) 16. 17. 18. 19. 20. 21. 25 // In cac phan tu cua mang for (i=0; i<m; i++) { for (j=0; j<n; j++)printf(“%d ”, a[i][j]); printf(“n”); } } Chương 7 - Phần 1

Ví dụ Nhập 2 mảng A, B có n dòng, m cột các phần

Ví dụ Nhập 2 mảng A, B có n dòng, 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 1. #include <stdio. h> 2. #define MAX 1000 3. void main(){ 4. int a[MAX], b[MAX], c[MAX]; int i, n, m; 5. //Nhap 2 mang 6. printf(“Nhap n = ”); scanf(“%d”, &n); 7. printf(“Nhap m = ”); scanf(“%d”, &m); 8. for (i=0; i<m; i++) 9. for (j=0; j<n; j++){ 10. printf(“Nhap a[%d]: ”, i, j); 11. scanf(“%d”, &a[i][j]); } 12. for (i=0; i<m; i++) 13. for (j=0; j<n; j++){ 14. printf(“Nhap a[%d]: ”, i, j); 15. scanf(“%d”, &a[i][j]); } 26 Chương 7 - Phần 1

Ví dụ Nhập 2 mảng A, B có n, m cột các phần tử

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) 16. 17. 18. 19. 20. 21. 22. 23. 24. 27 // 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++) { for (j=0; j<n; j++)printf(“%d ”, c[i][j]); printf(“n”); } } Chương 7 - Phần 1

Bài tập thảo luận trên lớp 1. Nhập mảng có n phần tử kiểu

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 28 Chương 7 - Phần 1

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

Bài tập Nhập 2 vector có n phần tử kiểu nguyên, kiểm tra 2 vector 5. đó có vuông góc với nhau không? Sắp xếp mảng một chiều bằng các phương pháp 6. • Phương pháp chọn • Phương pháp nổi bọt 7. Nhập vào một dãy, tìm phần tử lớn nhất, nhỏ nhất và các vị trí có phần tử đạt giá trị lớn nhất, nhỏ nhất. 8. Tính và in ra tích hai ma trận vuông cấp n x n. 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? 29 Chương 7 - Phần 1

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

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 30 trước) Chương 7 - Phần 1

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

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

Kiến trúc máy tính Bộ nhớ RAM chứa rất nhiều ô nhớ, mỗi ô

Kiến trúc máy tính Bộ nhớ RAM chứa rất nhiều ô nhớ, mỗi ô nhớ có kích thước 1 byte. RAM dùng để chứa một phần hệ điều hành, các lệnh chương trình, các dữ liệu… Mỗi ô nhớ có địa chỉ duy nhất và địa chỉ này được đánh số từ 0 trở đi. 32 Ví dụ RAM 512 MB được đánh địa chỉ từ 0 đến 229 – 1 RAM 2 GB được đánh địa chỉ từ 0 đến 231 – 1 Chương 7 - Phần 2

Khai báo biến trong C Quy trình xử lý của trình biên dịch Dành

Khai báo biến trong C 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 = 0 x 1234; // Giả sử địa chỉ 0 x 0 B 0 A 0 B 0 C 0 D 0 E 0 F 10 11 12 13 14 15 16 17 … 34 12 00 00 … a 33 Chương 7 - Phần 2

Khái niệm con trỏ Khái niệm Địa chỉ của biến là một con số.

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ỏ. 0 A 0 B 0 C 0 D 0 E 0 F 10 11 12 13 14 15 16 17 … 34 12 00 00 0 B 00 00 00 a pa … 34 Chương 7 - Phần 2

Khai báo con trỏ Khai báo Giống như mọi biến khác, biến con trỏ

Khai báo con trỏ Khai báo Giống như mọi biến khác, biến con trỏ muốn sử dụng cũng cần phải được khai báo <kiểu dữ liệu> *<tên biến con trỏ>; Ví dụ char *ch 1, *ch 2; int *p 1, p 2; ch 1 và ch 2 là biến con trỏ, trỏ tới vùng nhớ kiểu char (1 byte). p 1 là biến con trỏ, trỏ tới vùng nhớ kiểu int (4 bytes) còn p 2 là biến kiểu int bình thường. 35 Chương 7 - Phần 2

Khai báo con trỏ Sử dụng từ khóa typedef <kiểu dữ liệu> *<tên kiểu

Khai báo con trỏ Sử dụng từ khóa typedef <kiểu dữ liệu> *<tên kiểu con trỏ>; <tên kiểu con trỏ> <tên biến con trỏ>; Ví dụ typedef int *pint; int *p 1; pint p 2, p 3; 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. 36 Chương 7 - Phần 2

Con trỏ NULL Khái niệm Con trỏ NULL là con trỏ không trỏ và

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. int int n; *p 1 = &n; *p 2; // unreferenced local varialbe *p 3 = NULL; NULL 37 Chương 7 - Phần 2

Khởi tạo kiểu con trỏ Khởi tạo Khi mới khai báo, biến con trỏ

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ử &) <tên biến con trỏ> = &<tên biến>; Ví dụ int a, b; int *pa = &a, *pb; pb = &b; 38 Chương 7 - Phần 2

Sử dụng con trỏ Truy xuất đến ô nhớ mà con trỏ đến Con

Sử dụng con trỏ Truy xuất đến ô nhớ mà con 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 printf(“%dn”, = &a; pa); // Giá trị biến pa *pa); // Giá trị vùng nhớ pa trỏ đến &pa); // Địa chỉ biến pa 0 A 0 B 0 C 0 D 0 E 0 F 10 11 12 13 14 15 16 17 … 39 05 00 00 00 0 B 00 00 00 a pa Chương 7 - Phần 2 …

Kích thước của con trỏ char *p 1; int *p 2; float *p 3;

Kích thước của con trỏ char *p 1; int *p 2; float *p 3; double *p 4; … Con trỏ chỉ lưu địa chỉ nên kích thước của mọi con trỏ là như nhau: 40 Môi trường MD-DOS (16 bit): 2 bytes Môi trường Windows (32 bit): 4 bytes Chương 7 - Phần 2

Con trỏ và mảng một chiều Mảng một chiều int array[3]; Tên mảng array

Con trỏ và mảng một chiều Mảng một chiều int array[3]; 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 array == &array[0] 0 A 0 B 0 C 0 D 0 E 0 F 10 11 12 13 14 15 16 17 … … array 41 Chương 7 - Phần 2

Con trỏ và mảng một chiều Con trỏ đến mảng một chiều int array[3],

Con trỏ và mảng một chiều Con trỏ đến mảng một chiều int array[3], *parray; parray = &array[0]; // Cách 1 // Cách 2 18 19 1 A 1 B 1 C 1 D 1 E 1 F … 0 B 00 00 00 … parray 0 A 0 B 0 C 0 D 0 E 0 F 10 11 12 13 14 15 16 17 … 42 … array Chương 7 - Phần 2

Phép toán số học trên con trỏ Phép cộng (tăng) + n * sizeof(<kiểu

Phép toán số học trên con trỏ Phép cộng (tăng) + n * sizeof(<kiểu dữ liệu>) Có thể sử dụng toán tử gộp += hoặc ++ p = array +2 +1 0 A 0 B 0 C 0 D 0 E 0 F 10 11 12 13 14 15 16 17 … 43 int array[3]; … Chương 7 - Phần 2

Phép toán số học trên con trỏ Phép trừ (giảm) – n * sizeof(<kiểu

Phép toán số học trên con trỏ Phép trừ (giảm) – n * sizeof(<kiểu dữ liệu>) Có thể sử dụng toán tử gộp –= hoặc – – p = &array[2] – 2 – 1 0 A 0 B 0 C 0 D 0 E 0 F 10 11 12 13 14 15 16 17 … 44 int array[3]; … Chương 7 - Phần 2

Phép toán số học trên con trỏ Phép toán tính khoảng cách giữa 2

Phép toán số học trên con trỏ Phép toán tính khoảng cách giữa 2 con trỏ <kiểu dữ liệu> *p 1, *p 2; p 1 – p 2 cho ta khoảng cách (theo số phần tử) giữa hai con trỏ (cùng kiểu) p 1 = array p 2 = &array[2] p 1 – p 2= (0 B – 13)/sizeof(int) = – 2 p 2 – p 1= (13 – 0 B)/sizeof(int) = +2 0 A 0 B 0 C 0 D 0 E 0 F 10 11 12 13 14 15 16 17 … 45 int array[3]; … Chương 7 - Phần 2

Phép toán số học trên con trỏ Các phép toán khác Phép so sánh:

Phép toán số học trên con trỏ Các phép toán khác Phép so sánh: So sánh địa chỉ giữa hai con trỏ (thứ tự ô nhớ) 46 == != > >= < <= Không thể thực hiện các phép toán: * / % Chương 7 - Phần 2

Con trỏ và mảng một chiều Truy xuất đến phần tử thứ n của

Con trỏ và mảng một chiều Truy xuất đến phần tử thứ n của mảng (không sử dụng biến mảng) array[n] == p[n] == *(p + n) * ( p + 2 ) 0 A 0 B 0 C 0 D 0 E 0 F 10 11 12 13 14 15 16 17 … 47 int array[3]; … Chương 7 - Phần 2

Con trỏ và mảng một chiều Ví dụ nhập mảng void main() { int

Con trỏ và mảng một chiều Ví dụ nhập mảng void main() { int a[10], n = 10, *pa; pa = a; // hoặc pa = &a[0]; for (int i = 0; i<n; i++) scanf(“%d”, &a[i]); scanf(“%d”, &p[i]); scanf(“%d”, a + i); scanf(“%d”, p + i); scanf(“%d”, a++); scanf(“%d”, p++); } &a[i] (a + i) (p + i) &p[i] 48 Chương 7 - Phần 2

Con trỏ và mảng một chiều Ví dụ xuất mảng void main() { int

Con trỏ và mảng một chiều Ví dụ xuất mảng void main() { int a[10], n = 10, *pa; pa = a; // hoặc pa = &a[0]; … for (int i = 0; i<n; i++) printf(“%d”, a[i]); printf(“%d”, p[i]); printf(“%d”, *(a + i)); printf(“%d”, *(p + i)); printf(“%d”, *(a++)); printf(“%d”, *(p++)); } a[i] *(a + i) *(p + i) p[i] 49 Chương 7 - Phần 2

Con trỏ và mảng một chiều Lưu ý Không thực hiện các phép toán

Con trỏ và mảng một chiều Lưu ý Không thực hiện các phép toán nhân, chia, lấy phần dư. Tăng/giảm con trỏ n đơn vị có nghĩa là tăng/giảm giá trị của nó n*sizeof(<kiểu dữ liệu mà nó trỏ đến>) Không thể tăng/giảm biến mảng. Hãy gán một con trỏ đến địa chỉ đầu của mảng và tăng/giảm nó. Đố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. 50 Chương 7 - Phần 2

Cấp phát bộ nhớ Hàm malloc() là một trong các hàm được sử dụng

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 Chương 7 - Phần 2

Ví dụ Cấp phát động mảng 1 chiều, nhập và in mảng sử dụng

Ví dụ Cấp phát động mảng 1 chiều, nhập và in mảng sử dụng con trỏ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 52 #include <stdio. h> #include <malloc. h> void main() { int *p, n, i, j, temp; printf(“Nhap n = ”); scanf(“%d”, &n); p = (int *)malloc(n*sizeof(int)); for(i=0; i<n; i++) { printf(“n Enter value: %d : ”, i+1); scanf(“%d”, p+i); } for(i=1; i<10; i++) printf(“%dn“, i, *(p+i)) } Chương 7 - Phần 2

Hàm free() được sử dụng để giải phóng bộ nhớ khi nó không cần

Hàm free() được sử dụng để giải phóng bộ nhớ khi nó không cần dùng nữa. Cú pháp: void free(void*ptr); Hàm này giải phóng không gian được trỏ bởi ptr, để dùng cho tương lai. ptr phải được dùng trước đó với lời gọi hàm malloc(), calloc(), hoặc realloc(). 53 Chương 7 - Phần 2

Hàm calloc() calloc tương tự như malloc, nhưng điểm khác biệt chính là mặc

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ụ float *calloc 1, *calloc 2; calloc 1 = (float *)calloc(3, sizeof(float)); 54 Chương 7 - Phần 2

Bài tập thảo luận trên lớp Bài 1: Cho đoạn chương trình sau: float

Bài tập thảo luận trên lớp Bài 1: Cho đoạn chương trình sau: float pay; float *ptr_pay; pay=2313. 54; ptr_pay = &pay; Hãy cho biết giá trị của: a. pay b. *ptr_pay c. *pay d. &pay 55 Chương 7 - Phần 2

Bài tập thảo luận trên lớp Bài 2: Tìm lỗi #include<stdio. h> #include<conio. h>

Bài tập thảo luận trên lớp Bài 2: Tìm lỗi #include<stdio. h> #include<conio. h> void main() { int *x, y = 2; *x = y; *x += y++; printf("%d %d", *x, y); getch(); } 56 Chương 7 - Phần 2

Câu hỏi ôn tập lý thuyết 1. Toán tử nào dùng để xác định

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ỏ đế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ỏ p 1 trỏ đến phần tử thứ 3 còn con trỏ p 2 trỏ đến phần tử thứ 4 của mảng int. p 2 – p 1 = ? 9. Giống như câu trên nhưng đối với mảng float? 57 Chương 7 - Phần 2

Bài tập về nhà Sử dụng con trỏ viết cac chương trình: 1. Nhập

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 Chương 7 - Phần 2

PHẦN 3. X U KÝ TỰ 59

PHẦN 3. X U KÝ TỰ 59

Khái niệm Kiểu char chỉ chứa được một ký tự. Để lưu trữ một

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ự ‘’ (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 Chương 7 - Phần 3

Xuất xâu ký tự Sử dụng hàm printf với đặc tả “%s” char monhoc[50]

Xuất xâu ký tự Sử dụng hàm printf với đặc tả “%s” char monhoc[50] = “Tin hoc co so A”; printf(“%s”, monhoc); // Không xuống dòng Tin hoc co so A_ Sử dụng hàm puts char monhoc[50] = “Tin hoc co so A”; puts(monhoc); // Tự động xuống dòng printf(“%sn”, monhoc); Tin hoc co so A _ 62 Chương 7 - Phần 3

Nhập xâu ký tự Sử dụng hàm scanf với đặc tả “%s” Chỉ nhận

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 Chương 7 - Phần 3

Nhập xâu ký tự Sử dụng hàm gets Nhận các ký tự từ bàn

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 Chương 7 - Phần 3

Một số hàm thao tác trên xâu ký tự Thuộc thư viện <string. h>

Một số hàm thao tác trên xâu ký tự Thuộc thư viện <string. h> strcpy strdup strlwr/strupr strrev strcmp/stricmp strcat strlen strstr 65 Chương 7 - Phần 3

Hàm sao chép xâu ký tự char *strcpy(char dest[], const char src[]) Sao chép

Hàm sao chép xâu ký tự char *strcpy(char dest[], const char src[]) 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ự ‘’ vừa được chép. ! dest phải đủ lớn để chứa src Trả về Địa chỉ xâu ký tự dest char s[100]; s = “Tin hoc co so A”; strcpy(s, “Tin hoc co so A”); 66 // sai // đúng Chương 7 - Phần 3

Hàm tạo bản sao char *strdup(const char s[]) Tạo bản sao của một xâu

Hàm tạo bản sao char *strdup(const char s[]) 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. Trả về 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”); 67 Chương 7 - Phần 3

Hàm chuyển xâu ký tự thành chữ thường char *strlwr(char *s) Chuyển xâu ký

Hàm chuyển xâu ký tự thành chữ thường char *strlwr(char *s) Chuyển xâu ký tự s thành xâu ký tự thường (‘A’ thành ‘a’, ‘B’ thành ‘b’, …, ‘Z’ thành ‘z’) Trả về Địa chỉ xâu ký tự s char s[] = “Tin hoc co so A!!!”; strlwr(s); puts(s); // tin hoc co so a!!! 68 Chương 7 - Phần 3

Hàm chuyển xâu ký tự thành chữ IN char *strupr(char *s) Chuyển xâu ký

Hàm chuyển xâu ký tự thành chữ IN char *strupr(char *s) Chuyển xâu ký tự s thành xâu ký tự in (‘a’ thành ‘A’, ‘b’ thành ‘B’, …, ‘z’ thành ‘Z’) Trả về Địa chỉ xâu ký tự s char s[] = “Tin hoc co so A!!!”; strupr(s); puts(s); // TIN HOC CO SO A!!! 69 Chương 7 - Phần 3

Hàm đảo ngược xâu ký tự char *strrev(char *s) Đảo ngược thứ tự các

Hàm đảo ngược xâu ký tự char *strrev(char *s) Đả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ự) Trả về Địa chỉ xâu ký tự kết quả char s[] = “Tin hoc co so A!!!”; strrev(s); puts(s); // !!!A os oc coh ni. T 70 Chương 7 - Phần 3

Hàm so sánh hai xâu ký tự int strcmp(const char *s 1, const char

Hàm so sánh hai xâu ký tự int strcmp(const char *s 1, const char *s 2) So sánh hai xâu ký tự s 1 và s 2 (phân biệt hoa thường) Trả về < 0 nếu s 1 < s 2 == 0 nếu s 1 == s 2 >0 nếu s 1 > s 2 char s 1[] = “tin hoc co so A!!!”; char s 2[] = “hoc tin co so A!!!”; int kq = strcmp(s 1, s 2); // => kq > 0 71 Chương 7 - Phần 3

Hàm so sánh hai xâu ký tự int stricmp(const char *s 1, const char

Hàm so sánh hai xâu ký tự int stricmp(const char *s 1, const char *s 2) So sánh hai xâu ký tự s 1 và s 2 (không phân biệt hoa thường) Trả về < 0 nếu s 1 < s 2 == 0 nếu s 1 == s 2 >0 nếu s 1 > s 2 char s 1[] = “tin hoc co so A!!!”; char s 2[] = “TIN HOC CO SO A!!!”; int kq = stricmp(s 1, s 2); // => kq == 0 72 Chương 7 - Phần 3

Hàm nối hai xâu ký tự char* strcat(char *dest, const char *src) Nối xâu

Hàm nối hai xâu ký tự char* strcat(char *dest, const char *src) 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ả Trả về Địa chỉ của xâu ký tự được nối char s 1[100] = “Tin hoc”; char s 2[] = “co so A!!!”; strcat(s 1, “ ”); // => “Tin hoc ” strcat(s 1, s 2); // => “Tin hoc co so A!!!” 73 Chương 7 - Phần 3

Hàm tính độ dài xâu ký tự size_t* strlen(const char *s) Tính độ dài

Hàm tính độ dài xâu ký tự size_t* strlen(const char *s) 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. Trả về Độ dài xâu ký tự s char s[] = “Tin hoc co so A!!!”; int len = strlen(s); // => 18 74 Chương 7 - Phần 3

Hàm tìm xâu ký tự trong xâu ký tự char* strstr(const char *s 1,

Hàm tìm xâu ký tự trong xâu ký tự char* strstr(const char *s 1, const char *s 2) Tìm vị trí xuất hiện đầu tiên của s 2 trong s 1 Trả về Thành công: trả về con trỏ đến vị trí xuất hiện đầu tiên của s 2 trong s 1. Thất bại: trả về null char s 1[] = “Tin hoc co so A!!!”; char s 2[] = “hoc”; if (strstr(s 1, s 2) != null) printf(“Tim thay!”); 75 Chương 7 - Phần 3

Bài tập Xem thêm một số hàm khác như 1. atoi, atol, atof :

Bài tập Xem thêm một số hàm khác như 1. 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 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 Chương 7 - Phần 3

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

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 s 1, s 2, s 3 (không quá 40 kí tự), thay xâu s 2 bằng s 3 trong s 1 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 Chương 7 - Phần 3