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

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

80 18 0
Tài liệu đã được kiểm tra trùng lặp

Đ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 80
Dung lượng 1,76 MB

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

Nội dung

Mời các bạn cùng tham khảo Bài giảng Lập trình cơ bản: Ngôn ngữ lập trình C để nắm chi tiết các kiến thức về mảng, con trỏ và xâu ký tự; mảng một chiều và nhiều chiều; con trỏ và các phép toán; xâu ký tự.

Trang 1

Lập trình cơ bản:

Ngôn ngữ lập trình C

Đỗ Thị Mai Hường

Bộ môn Hệ thống thông tin

Khoa Công nghệ thông tin

Trang 2

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

tự

Trang 3

Tài liệu tham khảo

Chương 7 - Phần 1 3

• 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 4

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 5

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

NHIỀU CHIỀU

5

Trang 7

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

– NNLT C luôn chỉ định một khối nhớ liên tục

cho một biến kiểu mảng.

7

Trang 8

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

– 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

Trang 9

0 1 2

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

Trang 10

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ụ

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;

Trang 11

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

Trang 12

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 13

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

Trang 14

• 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

Trang 15

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

Trang 16

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

Trang 17

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

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

Trang 21

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

Trang 22

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;

Trang 23

• 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

23

Trang 24

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ử

Trang 26

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)

// In cac phan tu cua mang

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

Trang 28

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)// 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 29

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

29

Trang 30

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?

30

Trang 31

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

Trang 32

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

PHÉP TOÁN

Trang 33

Khai báo biến con trỏ.

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ểu int

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

Trang 34

Các thao tác trên con trỏ

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ả

Trang 35

Các thao tác trên con trỏ (t)

Trang 36

Các thao tác 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

Trang 37

Ví dụ về con trỏ

*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 moi

cua bien b=%d “ ,a,b);

/* a, b thay doi theo*/

getch();

}

Trang 38

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

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]

Trang 39

Con trỏ trỏ tới các phần tử của mảng mộ ột

chiều:

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:

Trang 40

Ví dụ:

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.

Trang 41

Ví dụ:

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.

Trang 42

Ví dụ:

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.

Trang 43

Con trỏ và mảng nhiều chiều

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

Trang 44

Con trỏ và mảng nhiều chiều (t)

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]

Trang 45

Ví dụ:

Dùn

g con trỏ

để vào số liệu cho mảng hai chiều

Trang 46

Kiểu con trỏ, kiểu địa chỉ, các phép toán trên con

trỏ

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đị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;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:

Trang 47

Ví dụ

dụng con trỏ

Trang 48

Các phép toán trên con trỏ

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

Trang 49

Các phép toán trên con trỏ (t)

 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.

Trang 50

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)

Trang 51

Con trỏ kiểu void

• 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.

Trang 52

Mảng con trỏ

• 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ó

Trang 53

Cấp phát bộ nhớ cho biến con trỏ

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

Trang 54

Giải phóng vùng nhớ do biến con trỏ quản

• Một vùng nhớ đã cấp phát cho biến con trỏ, khi không cần

sử dụng nữa, ta sẽ thu hồi lại vùng nhớ này nhờ hàm

free()

• 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óng

vùng nhớ cho 2 biến con trỏ pa & pb:

free(pa);

free(pb);

Trang 55

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

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

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

Trang 56

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

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

Trang 57

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

Trang 58

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

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

Trang 59

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

Trang 60

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

Trang 61

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

Trang 62

PHẦN 3 XÂU KÝ TỰ

Trang 63

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

Trang 64

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

Trang 65

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 66

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_

Trang 67

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 _

67

Trang 68

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

Trang 69

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

69

Trang 70

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

Trang 73

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 74

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 )

Trang 75

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

Ngày đăng: 13/03/2021, 09:08

TỪ KHÓA LIÊN QUAN

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

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w