80
Lp trình bn: Ngôn nglp trình C Đỗ ThMai Hường Bmôn Hthng thông tin Khoa Công nghthông tin

Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Lập trình cơ bản:Ngôn ngữ lập trình C

Đỗ Thị Mai HườngBộ môn Hệ thống thông tinKhoa Công nghệ thông tin

Page 2: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

Page 3: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Tài liệu tham khảo

Chương 7 - Phần 13

• 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

Page 4: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Nội dung

Chương 7 - Phần 1

• 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ự– Khái niệm

– Khởi tạo

– Các thao tác trên xâu ký tự

4

Page 5: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

5

Page 6: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Mảng một chiều• Khái niệm

• Khai báo

• Truy xuất dữ liệu

6

Page 7: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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áovà không bao giờ thay đổi.

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

7

Page 8: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

• Tường minh

– <N1>, …, <Nn> : số lượng phần tử của mỗi chiều.

• Lưu ý– 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ử> = N1*N2*…*Nn

– Bộ nhớ sử dụng = <tổng số phần tử>*sizeof(<kiểu cơ

<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>];

8

Page 9: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

0

1

2

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

• Ví dụint Mang1Chieu[10];

0 1 2 3 4 7 85 6 9

Mang1Chieu

int Mang2Chieu[3][4];

0 1 2 3 4 7 85 6 9

Mang2Chieu

10 11

9

Page 10: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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)

• Ví dụ

Chương 7 - Phần 1

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>[<N1>]…[<Nn>];

<tên kiểu mảng> <tên biến mảng>;

typedef int Mang1Chieu[10];typedef int Mang2Chieu[3][4];

Mang1Chieu m1, m2, m3;Mang2Chieu m4, m5;

10

Page 11: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

int n1 = 10; int a[n1];const int n2 = 20; int b[n2];

#define n1 10#define n2 20int a[n1]; // int a[10];int b[n1][n2]; // int b[10][20];

11

Page 12: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

int a[4] = {2912, 1706, 1506, 1904};

29122912 17061706 15061506 19041904

0 1 2 3

a

int a[4] = {2912, 1706};

29122912 17061706 00 00

0 1 2 3

a

12

Page 13: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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ị 0 cho mọi phần tử của mảng

– Tự động xác định số lượng phần tử

int a[4] = {0};

00 00 00 00

0 1 2 3

a

int a[] = {2912, 1706, 1506, 1904};

29122912 17061706 15061506 19041904

0 1 2 3

a

13

Page 14: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Truy xuất đến một phần tử• Thông qua chỉ số

• Ví dụ– Cho mảng như sau

– 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!

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

int a[4];

0 1 2 3

14

Page 15: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

• Ví dụ

Chương 7 - Phần 1

#define MAX 3typedef int MangSo[MAX];MangSo a = {1, 2, 3}, b;

b = a; // Saifor (int i = 0; i < 3; i++) b[i] = a[i];

15

Page 16: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Ví dụ

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

tử của mảng

16

#include <stdio.h>#define MAX 1000void main(){int ary[MAX];int i,n;printf(“Nhap n = ”);scanf(“%d”,&n);for(i=0; i<n; i++) {

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

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

}

1.2.3.4.5.6.7.8.9.10.11.12.13.14.

Page 17: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

mảng tổng

17

#include <stdio.h>#define MAX 1000void main(){

int ary1[MAX], ary2[MAX], sum[MAX];int i,n;printf(“Nhap n = ”);scanf(“%d”,&n);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=1; i<10; i++)sum[i]=ary1[i]+ary2[i];for(i=1; i<10; i++) printf(“a[%d]=%d\n“,i, sum[i])}

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.

Page 18: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Mảng hai chiều• Khái niệm

• Khai báo

• Truy xuất dữ liệu

18

Page 19: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Ma Trận

0

m-1

0 1 … n-1

Am,n

0

n-1

An

0 … n-1

19

Page 20: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Ma Trận0

n-1

An

0 … n-1

0

n-1

0 … n-1

0

…n-1

0 … n-1

dòng = cột dòng > cột dòng < cột

0

n-1

An

0 … n-1

0

…n-1

0 … n-1

0

n-1

0 … n-1

dòng + cột = n-1 dòng + cột > n-1 dòng + cột < n-120

Page 21: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

21

Page 22: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Khai báo biến mảng 2 chiều• Ví dụ

– Tường minh

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

int a[10][20], b[10][20];int c[5][10];int d[10][20];

typedef int MaTran10x20[10][20];typedef int MaTran5x10[5][10];

MaTran10x20 a, b;MaTran11x11 c;MaTran10x20 d;

22

Page 23: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Truy xuất đến một phần tử• Thông qua chỉ số

• Ví dụ

– Cho mảng 2 chiều như sau

– 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]

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

int a[3][4];

0

1

2

0 1 2 3

23

Page 24: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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ử

• Ví dụint a[5][10], b[5][10];

b = a; // Saiint i, j;for (i = 0; i < 5; i++)

for (j = 0; j < 10; j++)b[i][j] = a[i][j];

24

Page 25: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

25

#include <stdio.h>#define MAX 1000void main(){int a[MAX][MAX];int i,n,m;//Nhap mangprintf(“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][%d]: ”, i, j);scanf(“%d”, &a[i][j]);

}

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

Page 26: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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)

26

// In cac phan tu cua mangfor (i=0; i<m; i++){for (j=0; j<n; j++)printf(“%d ”, a[i][j]);printf(“\n”);}

}

16.17.18.19.20.21.

Page 27: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

27

#include <stdio.h>#define MAX 1000void main(){

int a[MAX][MAX], b[MAX][MAX], c[MAX][MAX];int i,n,m;//Nhap 2 mangprintf(“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][%d]: ”, i, j);scanf(“%d”, &a[i][j]); }

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

printf(“Nhap a[%d][%d]: ”, i, j);scanf(“%d”, &b[i][j]); }

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

Page 28: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuấ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)

28

// Tinh cac phan tu cua mang Cfor (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 Cfor (i=0; i<m; i++){

for (j=0; j<n; j++)printf(“%d ”, c[i][j]);printf(“\n”);}

}

16.17.18.19.20.21.22.23.24.

Page 29: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Bài tập thảo luận trên lớp1. 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ện29

Page 30: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Bài tập5. 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?

6. Sắp xếp mảng một chiều bằng các phương pháp

• 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?30

Page 31: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Bài tập10.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 31

Page 32: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

32

Page 33: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

KhaiKhai bbááoo bibiếếnn con con trtrỏỏ..

33

• Cú pháp: <Kiểu dữ liệu> * <Tên con trỏ>

• Ý nghĩa: Khai báo một biến có tên là Tên con trỏ dùng để chứa địa chỉ của các biến có kiểu Kiểu dữ liệu.

• Ví dụ 1: Khai báo 2 biến a,b có kiểu int và 2 biến pa, pb là 2 biến con trỏ kiểuint.

int a, b, *pa, *pb;

• Ví dụ 2: Khai báo biến f kiểu float và biến pf là con trỏ float

float f, *pf;

• Chú ý: Nếu chưa muốn khai báo kiểu dữ liệu mà con trỏ ptr đang chỉ đến, ta sử dụng:

void *ptr;

Sau đó, nếu ta muốn con trỏ ptr chỉ đến kiểu dữ liệu gì cũng được.

Tác dụng của khai báo này là chỉ dành ra 2 bytes trong bộ nhớ để cấp phát cho biến con trỏ ptr.

Page 34: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

CCáác thao tc thao táác trên con trc trên con trỏỏ ..

34

Gán địa chỉ của biến cho biến con trỏ:• Toán tử & dùng để định vị con trỏ đến địa chỉ của một biến

đang làm việc. • Cú pháp: <Tên biến con trỏ>=&<Tên biến> • Giải thích: Ta gán địa chỉ của biến Tên biến cho con trỏ

Tên biến con trỏ.Ví dụ: Gán địa chỉ của biến a cho con trỏ pa, gán địa chỉ của

biến b cho con trỏ pb. pa=&a; pb=&b;

• Lúc này, hình ảnh của các biến trong bộ nhớ được mô tả

Page 35: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

CCáác thao tc thao táác trên con trc trên con trỏỏ (t)(t)

35

Lưu ý: • Khi gán địa chỉ của biến tĩnh cho con trỏ cần phải lưu ý

kiểu dữ liệu của chúng. • Ví dụ sau đây không đúng do không tương thích kiểu:

int Bien_Nguyen; float *Con_Tro_Thuc; ... Con_Tro_Thuc=&Bien_Nguyen;

• Phép gán ở đây là sai vì Con_Tro_Thuc là một con trỏkiểu float (nó chỉ có thể chứa được địa chỉ của biến kiểu float); trong khi đó, Bien_Nguyen có kiểu int

Page 36: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

CCáác thao tc thao táác trên con trc trên con trỏỏ ..

36

Nội dung của ô nhớ con trỏ chỉ tới.

• Để truy cập đến nội dung của ô nhớ mà con trỏ chỉ tới, ta sử dụng cú pháp:

*<Tên biến con trỏ>

• Với cách truy cập này thì *<Tên biến con trỏ> có thể coi là một biến có kiểu được mô tả

trong phần khai báo biến con trỏ.

Ví dụ: Ví dụ sau đây cho phép khai báo, gán địa chỉ cũng như lấy nội dung vùng nhớ của

biến con trỏ: int x=100; int *ptr;

ptr=&x;

int y= *ptr;

• Lưu ý: Khi gán địa chỉ của một biến cho một biến con trỏ, mọi sự thay đổi trên nội dung ô

nhớ con trỏ chỉ tới sẽ làm giá trị của biến thay đổi theo (thực chất nội dung ô nhớ và biến

chỉ là một)

Page 37: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

VVíí ddụụvvềề

con con trtrỏỏ

37

#include “stdio.h”#include “conio.h”void main(){

int a,b,*pa,*pb;a=2;b=8;printf("\nGia tri cua bien a=%d \nGia tri cuabien b=%d ",a,b);pa=&a;pb=&b;printf("\nNoi dung cua o nho con tro pa tro toi=%d",*pa);printf("\nNoi dung cua o nho con tro pb trotoi=%d ",*pb);*pa=20; /* thay doi gia tri cua *pa*/*pb=25; /* thay doi gia tri cua *pb*/printf("\nGia tri moi cua bien a=%d \nGia tri moicua bien b=%d “ ,a,b); /* a, b thay doi theo*/getch();

}

Page 38: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Con Con trtrỏỏ vvàà mmảảngng mmộộtt chichiềềuu

38

• Trong C có mối quan hệ chặt chẽ giữa con trỏ và mảng: các phần tử của mảng có thể được xác định nhờ chỉ số hoặc thông qua con trỏ.

Phép toán lấy địa chỉ:

• Giả sử ta có khai báo: double b[20];

phép toán: &b[9] sẽ cho địa chỉ của phần tử b[9].

Tên mảng là một hằng địa chỉ:

• Khi chúng ta khai báo: float a[10]; máy sẽ bố trí bố trí cho mảng a mười khoảng nhớ liên tiếp.

• Mỗi khoảng nhớ là 4 byte.

• Như vậy, nếu biết địa chỉ của một phần tử nào đó của mảng a, thì ta có thểdễ dàng suy ra địa chỉ của các phần tử khác của mảng.

• Trong C ta có: a &a[0]

a+i &a[i]

*(a+i) a[i]

Page 39: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Con Con trtrỏỏ trtrỏỏ ttớớii ccáácc phphầầnn ttửử ccủủaa mmảảngng mmộộtchichiềềuu::

39

• Khi con trỏ pa trỏ tới phần tử a[k] của mảng a thì: pa+i trỏ tới phần tử thứ i sau a[k], có nghĩa là nó trỏ tới a[k+i]. pa-i trỏ tới phần tử thứ i trước a[k], có nghĩa là nó trỏ tới a[k-i]. *(pa+i) tương đương với pa[i].

• Ví dụ: sau hai câu lệnh:float a[20],*pa;pa=&a; // pa=&a[0];

• Khi đó, 4 cách viết sau có tác dụng như nhau và cùng truy cập đến phần tử thứ i của mảng a:

a[i] *(a+i) pa[i] *(pa+i)

Page 40: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

VVíí ddụụ::Vào số

liệu cho các phần tử của một mảng

và tính tổng các phần tửcủa chúng.

40

Cách 1:

#include "stdio.h"void main(){

float a[4],tong;int i;for (i=0;i<4;++i){

printf("\n a[%d]=",i);scanf("%f",(a+i));

}tong=0;for (i=0;i<4;++i)

tong+=a[i];

Page 41: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

VVíí ddụụ::Vào số

liệu cho các phần tử của một mảng

và tính tổng các phần tửcủa chúng.

41

Cách 2:

#include "stdio.h"void main(){

float a[4],tong, *troa;int i;troa=a;for (i=0;i<4;++i){

printf("\n a[%d]=",i); scanf("%f",troa+i);

}tong=0;for (i=0;i<4;++i)

tong+=a[i];printf("\n Tong cac phan tu mang la:%8.2f ",tong);

}

Page 42: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

VVíí ddụụ::Vào số

liệu cho các phần tử của một mảng

và tính tổng các phần tửcủa chúng.

42

Cách 3:

#include "stdio.h"void main(){

float a[4],tong,*troa;int i;troa=a;for (i=0;i<4;++i){

printf("\n a[%d]=",i);scanf("%f",troa+i);

}tong=0;for (i=0;i<4;++i)

tong+=*(troa+i);printf("\n Tong cac phan tu mang la:%8.2f ",tong);

}

Page 43: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Con Con trtrỏỏ vvàà mmảảngng nhinhiềềuu chichiềềuu

43

Phép cộng địa chỉ trong mảng hai chiều:

• Giả sử ta có mảng hai chiều a[2][3] có 6 phần tử ứng với sáu địa chỉ liên tiếp trong bộ

nhớ được xếp theo thứ tự sau:

• Tên mảng a biểu thị địa chỉ đầu tiên của mảng.

• Phép cộng địa chỉ : C coi mảng hai chiều là mảng (một chiều) của mảng, như vậy khai

báo

float a[2][3]; thì a là mảng mà mỗi phần tử của nó là một dãy 3 số thực (một hàng

của mảng).

• Vì vậy: a trỏ phần tử thứ nhất của mảng: phần tử a[0][0]

a+1 trỏ phần tử đầu hàng thứ hai của mảng: phần tử a[0][1],

...

a+i trỏ phần tử đầu hàng thứ i của mảng: phần tử a[0][i].

Phầntử a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]

Địachỉ 1 2 3 4 5 6

Page 44: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Con Con trtrỏỏ vvàà mmảảngng nhinhiềềuu chichiềềuu (t)(t)

44

Con trỏ và mảng hai chiều:Để lần lượt duyệt trên các phần tử của mảng

hai chiều ta có thể dùng con trỏ như minh hoạ ở ví dụ sau:

float *pa,a[2][3];

pa=(float*)a;

Khi đó:

– pa trỏ tới a[0][0]

– pa+1 trỏ tới a[0][1]

– pa+2 trỏ tới a[0][2]

– pa+3 trỏ tới a[1][0]

– pa+4 trỏ tới a[1][1]

– pa+5 trỏ tới a[1][2]

Page 45: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

VVíí ddụụ::Dùn

g con trỏđể vào sốliệu cho

mảng haichiều

45

Cách 1:#include "stdio.h"void main(){

float a[2][3],*pa;int i;pa=(float*)a;for (i=0;i<6;++i)

scanf("%f",pa+i);}

Cách 2:#include "stdio.h"void main(){

float a[2][3],*pa;int i;for (i=0;i<6;++i)

scanf("%f",(float*)a+i);

Page 46: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

KiKiểểuu con con trtrỏỏ, , kikiểểuu đđịịaa chchỉỉ, , ccáácc phphéépp totoáánn trêntrên con con trtrỏỏ

46

Kiểu con trỏ và kiểu địa chỉ:

• Con trỏ dùng để lưu địa chỉ của biến. Mỗi kiểu địa chỉ của biến cần có kiểu con trỏ

tương ứng. Phép gán địa chỉ cho con trỏ chỉ có thể thực hiện được khi kiểu địa chỉ phù

hợp với kiểu con trỏ.

• Theo khai báo:

float a[20][30], *pa,*pn[30],(*pm)[30];

• Ta có:

• a là mảng 2 chiều, có 600 phần tử kiểu float. a là địa chỉ kiểu float[30].

• pa là con trỏ float.

• pn là mảng 30 con trỏ kiểu float.

• pm là con trỏ kiểu float [30].

• Như vậy, phép gán:

pa=a; là không hợp lệ (tuy nhiên sẽ có quá trình chuyển kiểu tự động).

• Nhưng phép gán:

pm=a; là hợp lệ.

Page 47: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

VVíí ddụụvvềề ssửửddụụngngcon con trtrỏỏ

47

#include "conio.h"#include "stdio.h"

void main(){

float a[2][3]={{1.0,2.0,3.0},{4.0,5.0,6.0}}, *p, (*pm3)[3];float *b; int i;p=(float *)a;pm3=a;for (i=0;i<6;i++)

printf("%f", *(p+i));printf("\n");b=(float*)pm3;for (i=0;i<3;i++)

printf("%f", b[i]);printf("\n");b=(float*)(pm3+1);for (i=0;i<3;i++)

printf("%f", b[i]);getch();

}

Page 48: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

CCáác phc phéép top toáán trên con trn trên con trỏỏ

48

Có 4 phép toán liên quan đến con trỏ và đại chỉ là: Phép gán. Phép tăng giảm địa chỉ. Phép truy cập bộ nhớ. Phép so sánh.

• Phép gán: Phép gán chỉ thực hiện với các con trỏ cùng kiểu. Muốn gán cáccon trỏ khác kiểu phải dùng phép ép kiểu.

int x;char *pc;pc=(char*)(&x);

• Phép tăng giảm địa chỉ: Sử dụng phép toán này để di chuyển giữa các ô nhớ:

• Ví dụ: Các câu lệnh:float x[30],*px;px=&x[10];

• Cho con trỏ px là con trỏ float trỏ tới phần tử x[10]. Ta có:px+i trỏ tới phần tử x[10+i]px-i trỏ tới phần tử x[10-i]

Page 49: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

CCáác phc phéép top toáán trên con trn trên con trỏỏ (t)(t)

49

• Phép truy cập bộ nhớ:Con trỏ float trỏ tới địa chỉ dài 4 byte, con trỏ int trỏ tới địa chỉ dài 2 byte, con trỏ char

trỏ tới địa chỉ dài 1 byte.

• Ví dụ: khai báo:

float *pf;int *pi;char *pc;

• Khi đó ta có các nhận xét sau:

Nếu trỏ pf trỏ đến byte thứ 100 thì *pf biểu thị vùng nhớ 4 byte liên tiếp từ byte 100 đến 103.

Nếu trỏ pi trỏ đến byte thứ 100 thì *pi biểu thị vùng nhớ 2 byte liên tiếp từ byte 100 đến 101.

Nếu trỏ pc trỏ đến byte thứ 100 thì *pc biểu thị vùng nhớ 1 byte chính là byte 100.

• Phép so sánh: Cho phép so sánh các con trỏ cùng kiểu.

• Ví dụ nếu p1 và p2 là các con trỏ cùng kiểu thì nếu:

p1<p2 nếu địa chỉ p1 trỏ tới thấp hơn địa chỉ p2 trỏ tới.

p1==p2 nếu địa chỉ p1 trỏ tới cũng là địa chỉ p2 trỏ tới.

p1>p2 nếu địa chỉ p1 trỏ tới cao hơn địa chỉ p2 trỏ tới.

Page 50: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

VVíí ddụụ

50

Ví dụ 1:

Đoạn chương trình tính tổng các số thực dùng phép so sánh con trỏ:

float a[100],*p,*pcuoi,tong=0.0;

pcuoi=(float*)(a+99); /* Địa chỉ cuối dãy*/

for (p=(float*)a;p<=pcuoi;++p)

tong+=*p;

Ví dụ 2:

Dùng con trỏ char để tách các byte của một biến nguyên, ta làm như sau:

Giả sử ta có biến nguyên n được khai báo như sau:

unsigned int n=0xABCD; /* Số nguyên hệ 16*/

char *pc;

pc=(char*)(&n);

Khi đó:

*pc=0xAB (byte thứ nhất của n)

*(pc+1)=0xCD (byte thứ hai của n)

Page 51: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Con trCon trỏỏ kikiểểu voidu void

51

• Cú pháp: void *tên_con_trỏ;

• Đây là con trỏ đặc biệt, con trỏ không kiểu, nó có thể nhận địa chỉkiểu bất kỳ.

• Ví dụ: Câu lệnh sau là hợp lệ:

void *pa;

float a[20][30];

pa=a;

• Con trỏ void thường dùng làm tham số hình thức để nhận bất kỳ địa

chỉ kiểu nào từ tham số thực. Trong thân hàm phải dùng phép chuyển

đổi kiểu để chuyển sang dạng địa chỉ cần xử lý.

• Chú ý: Các phép toán tăng giảm địa chỉ, so sánh và truy cập bộnhớ không dùng được trên con trỏ void.

Page 52: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

MMảảng con trng con trỏỏ

52

• Mảng con trỏ: là một mảng mà mỗi phần tử của nó là một con trỏ.

• Cú pháp:

<Kiểu dữ liệu> *<Tên_mảng_con_trỏ>[N];

• Khi gặp khai báo trên, máy sẽ cấp phát N khoảng nhớ liên tiếp cho N phần

tử của mảng.

• Ví dụ: double *pa[100];

Khai báo một mảng con trỏ kiểu double gồm 100 phần tử. Mỗi phần tử

pa[i] có thể dùng để lưu trữ một địa chỉ kiểu double.

• Chú ý :

• Bản thân các mảng con trỏ không dùng để lưu trữ số liệu.

• Trước khi sử dụng một mảng con trỏ ta cần gán cho mỗi phần tử của nó

một địa chỉ.

Page 53: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

CCấấp php pháát bt bộộ nhnhớớ cho bicho biếến con trn con trỏỏ

53

• Trước khi sử dụng biến con trỏ, ta phải cấp phát vùng nhớ cho biến con trỏ này quản lý địa chỉ. Việc cấp phát được thực hiện nhờ các hàm malloc(), calloc(), realloc() trong thư viện alloc.h, hoặc stdlib.h.

• Cú pháp các hàm:

void *malloc(size_t size); Cấp phát vùng nhớ có kích thước là size byte.

void *calloc(size_t nitems, size_t size); Cấp phát vùng nhớ có kích thước

là nitems*size byte.

void *realloc( void *memblock, size_t size ); Cấp phát lại ô nhớ cho con

trỏ memblock size byte.• Ví dụ: Giả sử ta có khai báo:

int a, *pa, *pb;pa = (int*)malloc(sizeof(int)); /* Cấp phát vùng nhớ có kích thước bằng với

kích thước của một số nguyên */ pb= (int*)calloc(10, sizeof(int)); /* Cấp phát vùng nhớ có thể chứa được 10

số nguyên*/ pa= (int*) realloc(pa, 10*sizeof(int)); /* Cấp phát lại vùng nhớ có thể chứa

được 10 số nguyên*/

Page 54: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

GiGiảảii phphóóngng vvùùngng nhnhớớ do do bibiếếnn con con trtrỏỏ ququảảnnlýlý

54

• Một vùng nhớ đã cấp phát cho biến con trỏ, khi không cầnsử dụng nữa, ta sẽ thu hồi lại vùng nhớ này nhờ hàmfree().

• Cú pháp: void free(void *block)

• Ý nghĩa: Giải phóng vùng nhớ được quản lý bởi con trỏblock.

• Ví dụ: Ở ví dụ trên, sau khi thực hiện xong, ta giải phóngvùng nhớ cho 2 biến con trỏ pa & pb:

free(pa);

free(pb);

Page 55: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

55

#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(“%d\n“,i, *(p+i))

}

1.2.3.4.5.6.7.8.9.10.11.12.13.

Page 56: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Hàm free()• 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(). 56

Page 57: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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ụ

57

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

Page 58: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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. &pay58

Page 59: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

}

59

Page 60: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Câu hỏi ôn tập lý thuyết1.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

60

Page 61: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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á

61

Page 62: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

62

Page 63: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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ự

63

Page 64: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Khởi tạo• Khởi tạo như mảng thông thường

– Độ dài cụ thể

– Tự xác định độ dài

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

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

‘T’‘T’ ‘H’‘H’ ‘C’‘C’ ‘S’‘S’ ‘ ’‘ ’ ‘A’‘A’0 1 2 3 4 5 6 7 8 9

‘T’‘T’ ‘H’‘H’ ‘C’‘C’ ‘S’‘S’ ‘ ’‘ ’ ‘A’‘A’0 1 2 3 4 5

‘\0’‘\0’

‘\0’‘\0’6

64

Page 65: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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”;puts(monhoc); // Tự động xuống dòng printf(“%s\n”, monhoc);

Tin hoc co so A

Tin hoc co so A

_

_

65

Page 66: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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 AChuoi nhan duoc la: Tin_

66

Page 67: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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 AChuoi nhan duoc la: Tin hoc co so A _

67

Page 68: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

– strstr68

Page 69: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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ự ‘\0’ vừa được chép.! dest phải đủ lớn để chứa src

Địa chỉ xâu ký tự dest

char s[100];s = “Tin hoc co so A”; // saistrcpy(s, “Tin hoc co so A”); // đúng

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

69

Page 70: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

70

Page 71: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Hàm chuyển xâu ký tự thành chữ thường

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

Địa chỉ xâu ký tự s

char s[] = “Tin hoc co so A!!!”;strlwr(s);puts(s); // tin hoc co so a!!!

char *strlwr(char *s)char *strlwr(char *s)

71

Page 72: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Hàm chuyển xâu ký tự thành chữ IN

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

Địa chỉ xâu ký tự s

char s[] = “Tin hoc co so A!!!”;strupr(s);puts(s); // TIN HOC CO SO A!!!

char *strupr(char *s)char *strupr(char *s)

72

Page 73: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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!!!”;strrev(s);puts(s); // !!!A os oc coh niT

char *strrev(char *s)char *strrev(char *s)

73

Page 74: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Hàm so sánh hai xâu ký tự

So sánh hai xâu ký tự s1 và s2 (phân biệt hoa thường)

< 0 nếu s1 < s2== 0 nếu s1 == s2>0 nếu s1 > s2

char s1[] = “tin hoc co so A!!!”;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)

74

Page 75: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Hàm so sánh hai xâu ký tự

So sánh hai xâu ký tự s1 và s2 (không phân biệt hoa thường)

< 0 nếu s1 < s2== 0 nếu s1 == s2>0 nếu s1 > s2

char s1[] = “tin hoc co so A!!!”;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)

75

Page 76: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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)

76

Page 77: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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

Tính độ dài xâu ký tự ssize_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)

77

Page 78: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

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ề null

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

78

Page 79: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Bài tập1. 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.79

Page 80: Lập trình cơ bản: Ngôn ngữlập trình Cfit.mta.edu.vn/files/DanhSach/Bai5_6_7.pdf · • Kỹthuật lập trình C: cơ sởvà nâng cao, Phạm Văn Ất, Nhà xuất

Bài tập8. 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 80