Bai 5- Mang va Con tro.pdf

Embed Size (px)

Citation preview

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    1/63

    TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

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

    Bài 5: Bảng và Con trỏ

    TS. Đỗ Đăng Khoa

    Bộ môn Cơ học Ứng dụngViện Cơ khí

    http://chud-dhbkhn.blogspot.com/

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    2/63

    Khái niệm về Bảng (Mảng)Khi cần lưu trữ một dãy n phần tử dữ liệu chúng ta cần khaibáo n biến tương ứng với n tên gọi khác nhau -> khó khăn để có

    thể nhớ và quản lý hết được tất cả các biếnMột bảng trong C/C++ là một tập hợp các phần tử dữ liệu liênquan có cùng kiểu và được truy cập bởi một tên chung

    TRƯỜNG ĐẠI HỌC

    BÁCH KHOA HÀ NỘI

    nhớ liền kề nhau, và sử dụng chỉ số để xác định từng phần tửChỉ số bảng bắt đầu từ 0Mảng có thể có nhiều chiều

    Ví dụ: danh sách sinh viên, danh sách điểm số của sinh viên,etc

    2

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    3/63

    Mảng một chiều

    // mảng số nguyên một chiều có 10 phần tử

    int A[10];

    A[3]=1;

    TRƯỜNG ĐẠI HỌC

    BÁCH KHOA HÀ NỘI

    -- -- 1--A -- -- ---- -- --4 5 630 2 8 971

    A[4] A[5] A[6]A[3]A[0] A[2] A[8] A[9]A[7]A[1]

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    4/63

    Khai báo bảng (mảng) một chiều

    Các đặc tính riêng của bảng (mảng) cần được định nghĩa.Kiểu dữ liệu của các phần tử 

    Tên mảng :   đại diện cho vị trí phần tử đầu tiên

    Kích thước mảng  : một hằng sốKhai báo mảng giống như cách khai báo biến. Chỉ khác là

    TRƯỜNG ĐẠI HỌC

    BÁCH KHOA HÀ NỘI

    trong cặp dấu ngoặc vuông   [], để xác định kích thước củamảng.

    int x[20]; // x có thể chứa 20 số nguyên

    float price[10]; // price có thể chứa 10 số thực

    char letter[70]; // letter có thể chứa tối đa 69 kí tự

    do cần cần có kí tự kết thúc không (\0) cuối xâu

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    5/63

    Các qui tắc về bảng (mảng)

      Các phần tử của mảng có cùng kiểu dữ liệu

      Mỗi phần tử của mảng có thể được sử dụng như một biếnriêng lẻ   Kiểu dữ liệu của mảng có thể là int, char , float hoặc double  Mảng được “đối xử” không giống hoàn toàn với biến

    TRƯỜNG ĐẠI HỌC

    BÁCH KHOA HÀ NỘI

     Hai mảng có cùng kiểu và cùng kích thước cũng khôngđược xem là tương đương nhau  Không thể gán trực tiếp một mảng cho một mảng khác.  Không thể gán trị cho toàn bộ mảng, mà phải gán trị cho

    từng phần tử của mảng

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    6/63

    Khởi tạo bảng (mảng) một chiều

      Mỗi phần tử của một mảng cần được khởi tạo riêng rẽ.Kiểu_dữ_liệu tên_bảng[kích_thước_mảng] = {ds_các_phần_tử_bảng};

    Kiểu_dữ_liệu tên_bảng[] = {ds_các_phần_tử_bảng};

    Ví dụ:

    int id[7] = {1, 2, 3, 4, 5, 6, 7};

    TRƯỜNG ĐẠI HỌC

    BÁCH KHOA HÀ NỘI

    float x[] = {5.6, 5.7, 5.8, 5.9, 6.1};char vowel[6] = {'a', 'e', 'i', 'o', 'u', '\0'};

    char vowel[6] = "aeiou";   // Kí tự NULL được trình biên dịchtự động thêm vào, do đó vẫn phải dự trữ thêm một chỗ cho

    NULL.   Các phần tử của mảng có thể được gán giá trị bằng cách sử

    dụng vòng lặp for 

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    7/63

    Sử dụng bảng (mảng) một chiều

      Để chỉ thành phần thứ i (hay chỉ số i) của một mảng ta viết

    tên mảng kèm theo chỉ số trong cặp ngoặc vuông [].int id[7] = {1, 2, 3, 4, 5, 6, 7};cout a ; // sai

    mà phải nhập cho từng phần tử từ a[0] đến a[9] của a

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    8/63

    Ví dụ về mảng một chiều

      Tìm số bé nhất của một dãy số. In ra số này và vị trí của nó

    trong dãyvoid main(){

    float a[100], min;// a chứa tối đa 100 số

    int i,n,k;

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    9/63

    Xâu/mảng ký tự

      Một xâu kí tự là một dãy bất kỳ các kí tự (kể cả dấu cách) do

    vậy nó có thể được lưu bằng mảng kí tự   Cần thiết phải có kí tự kết thúc xâu ‘\0’

    char [độ dài] ; // không khởi tạo

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     

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

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

    Ví dụ:char hoten[26] ; // xâu họ tên chứa tối đa 25 kí tự

    char monhoc[31] = "NNLT C++" ;

    char thang[] = "Muoi hai" ; // độ dài mảng = 9

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    10/63

    Sử dụng Xâu/mảng ký tự

     Xâu kí tự có những đặc trưng như mảng, tuy nhiên chúng

    cũng có những điểm khác biệt  Truy cập một kí tự trong xâu: cú pháp giống như mảng. Ví dụ:

    char s[50] = "I\'m a student" ;/* chú ý kí tự '

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     

    phải được viết là \‘ */cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    11/63

    Sử dụng Xâu/mảng ký tự

    Không được thực hiện các phép toán trực tiếp trên xâu như:

    char s[20] = "Hello", t[20] ; /* khai báo haixâu s và t */

    t = "Hello" ;// sai, chỉ gán được khi khai báo

    t = s ; // sai, không gán được toàn bộ mảng

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     

    if (s < t) … // sai, không so sánh được hai mảng  Các hàm thư viện xử lý xâu ký tự được khai báo trong file

    nguyên mẫu

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    12/63

    Các hàm xử lý xâu ký tự (chuỗi)

    Các hàm xử lý chuỗi được tìm thấy trong thư viện chuẩn

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    13/63

    Ví dụ về các hàm xử lý xâu ký tự (chuỗi)

    Hàm strcpy(s1,s2): Hàm sao chép xâu s2 vào s1

    char s[10], t[10] ;t = "Face" ; // không được dùng

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

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

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     

    strcpy(s, t) ; // được, sao chép t sang scout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    14/63

    Ví dụ về các hàm xử lý xâu ký tự (chuỗi)

    Hàm strncpy (s1,s2,n): Hàm sao chép n ký tự xâu s2 vào s1

    char s[10], t[10] = "Steven";

    strncpy(s, t, 5) ;// copy 5 kí tự "Steve" vào s

    s[5] = '\0' ; // đặt d u k t thúc xâu

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     

    // in câu: Steve is young brother of Steven

    cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    15/63

    Ví dụ về các hàm xử lý xâu ký tự (chuỗi)

    Hàm strcat (s1,s2): Hàm nối xâu s2 vào s1

    char a[100] = “Ban", b[4] = “toi";strcat(a, “ va ”);

    strcat(a, b);

    cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    16/63

    Ví dụ về các hàm xử lý xâu ký tự (chuỗi)

    Hàm strncat (s1,s2,n): Hàm nối n ký tự xâu s2 vào s1

    char s[20] = “Nha " ;char t[] = “anh chi"

    strncat(s, t, 3) ; // s = “Nha anh"

    hoặc:

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     

    strncat(s, t+4, 3) ; // s = "Nha chi"

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    17/63

    Ví dụ về các hàm xử lý xâu ký tự (chuỗi)

    Hàm strcmp(s1,s2): Hàm so sánh 2 xâu s1 và s2

    if (strcmp(s1,s2))cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    18/63

    Ví dụ về các hàm xử lý xâu ký tự (chuỗi)

    Hàm strcmpi(s1, s2): Như strcmp(s1, s2) nhưng không phân

    biệt chữ hoa, thườngchar s[] = “Ha Noi" , t[] = “ha noi" ;cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    19/63

    Truyền mảng một chiều cho hàm

    Một hàm có thể nhận địa chỉ của một bảng một chiều theo ba

    cách Một con trỏint myfunction(float *x)

    Một bảng có kích thước

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    char yourfunction(float x[5]) Một bảng không có kích thước

    void yourfunction(float x[ ])

    Hai cách sau thường ít được sử dụng

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    20/63

    Ví dụ: lấy giá trị trung bình của mảng

    #include

    using namespace std;

    double getAverage(int arr[], int size);int main ()

    {

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    nt a ance = { , , , , };

    double avg;

    avg = getAverage( balance, 5 ) ;

    cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    21/63

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    22/63

    Mảng hai chiều

    // Mảng số nguyên hai chiều – 3 hàng và 10 cột

    int A[3][10];

    A[1][2] = 1;

    4 5 630 2 8 971

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    -- -- ----

    A

    -- -- ---- -- --

    -- 1 ---- -- -- ---- -- ---- -- ---- -- -- ---- -- --0

    2

    1

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    23/63

    Mảng hai chiều

    Mảng hai chiều có thể xem như là một mảng (m phầntử) với mỗi phần tử là mảng một chiều (n phần tử)Một mảng hai chiều trông giống như một ma trận gồmcác hàng và các cộtTrong bộ nhớ tất cả các phần tử của mảng được sắpliên tiếp theo từng hàng của mảng

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    Khai báo mảng hai chi u:

    [m][n] ;

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    24/63

    Khởi tạo bảng (mảng) hai chiều

      Mỗi phần tử của một mảng cần được khởi tạo riêng rẽ.Kiểu_dữ_liệu tên_bảng[hàng][cột] = {ds_các_phần_tử_bảng};

    Kiểu_dữ_liệu tên_bảng[][cột] = {ds_các_phần_tử_bảng};

    Ví dụ:

    int x[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    int x[][4] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12} };

    Kết quả của phép gán trong cả hai trường hợp:x[0][0]=1 x[0][1]=2 x[0][2]=3 x[0][3]=4

    x[1][0]=5 x[1][1]=6 x[1][2]=7 x[1][3]=8x[2][0]=9 x[2][1]=10 x[2][2]=11 x[2][3]=12

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    25/63

    Khởi tạo bảng (mảng) hai chiều

    Khởi tạo bảng xâu ký tựchar name[4][10] = {"Sally", "Joyce", "Lisa",

    "Alice"};

    Kết quả:name[0] = "Sally" name[1] = "Joyce"

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     

    name[2] = "Lisa" name[3] = "Alice"

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    26/63

    Sử dụng bảng (mảng) hai chiều

      Để chỉ thành phần hàng i (hay chỉ số i) và cột j của một mảngta viết tên mảng kèm theo các chỉ số trong 2 cặp ngoặc vuông[].

    int id[2][2] = {1, 2, 3, 4};

    cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    27/63

    Truyền mảng hai chiều cho hàm

    Một hàm có thể nhận địa chỉ của một bảng 2 chiều theo bacách Một bảng con trỏ

    int myfunction(float **x) Một bảng có kích thước

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    char yourfunction(float x[4][5]) Một bảng không có kích thước

    void yourfunction(float x[ ][5])

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    28/63

    Ví dụ: truyền mảng 2 chiều cho hàm

    Truyền mảng kích thước cố địnhint array[10][10];

    //Định nghĩa hàm nhận mảng 2 chiều cố định

    void passFunc(int a[10][10])

    { // thao tác với a[i][j] }

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     

    passFunc(array);Hoặcvoid passFunc(int a[][10])

    {//thao tác với a[i][j] }

    passFunc(array);

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    29/63

    Ví dụ: truyền mảng 2 chiều cho hàm

    Hoặcvoid passFunc(int (&a)[10][10])

    { // thao tác với a[i][j] }passFunc(array);

    Hoặc 

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    vo pass unc n a

    { // thao tác với (*a)[i][j] }

    passFunc(&array);

    Hoặcvoid passFunc(int (*a)[10]) // con trỏ tới mảng

    { // thao tác với a[i][j] }

    passFunc(array);

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    30/63

    Ví dụ: truyền mảng 2 chiều cho hàm

    Sai nếu định nghĩavoid passFunc(int **a) //con trỏ tới con trỏ

    { // …}Truyền mảng kích thước thay đổi

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    n array;

    array = new int *[10];

    for(int i = 0; i

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    31/63

    Khái niệm về Con trỏ

    Con trỏ là một biến, nó chứa địa chỉ ô nhớ của một biến khácNếu p là con trỏ chứa địa chỉ của biến c ta gọi p trỏ tới c và c

    được trỏ bởi p

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    Con trỏ cung cấp phương thức truy xuất gián tiếp đến giá trịcủa một phần tử dữ liệu

    Các con trỏ có thể trỏ đến các biến có kiểu dữ liệu cơ bản nhưint, char, double, hay dữ liệu tập hợp như mảng hoặc cấu trúc.

    Phép toán lấy địa chỉ của đối tượng: &.

    31

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    32/63

    Ứng dụng của con trỏ

    Để trả về nhiều hơn một giá trị từ một hàm

    Để truyền mảng và chuỗi từ một hàm đếnmột hàm khác thuận tiện hơn

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    vì truy xuất trực tiếp vào các phần tử nàyĐể cấp phát bộ nhớ và truy xuất bộ nhớ (Cấp

     phát bộ nhớ trực tiếp)

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    33/63

    Khai báo con trỏ

    Khai báo con trỏ: chỉ ra một kiểu cơ sở vàmột tên biến được đặt trước bởi dấu *

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     p p a o ng qu :

    Ví dụ:

    ;

    int *p;

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    34/63

    Các toán tử con trỏ * và &

    Để con trỏ p trỏ đến biến x ta phải dùng phép gán p = địa chỉcủa x. Nếu x không phải là mảng ta viết: p = &x. Nếu x là mảng ta viết: p = x hoặc p = &x[0].

    Khôn án cho một hằn địa chỉ cụ thể. Ví dụ viết = 200

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     

    là sai.Phép toán * cho phép lấy nội dung nơi p trỏ đến, ví dụ đểgán nội dung nơi p trỏ đến cho biến f ta viết f = *p.& và * là 2 phép toán ngược nhau. Cụ thể nếu p = &x thì x =

    *p. Từ đó nếu p trỏ đến x thì bất kỳ nơi nào xuất hiện x đều cóthể thay được bởi *p và ngược lại.

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    35/63

    Ví dụ về con trỏ

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

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

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

    cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    36/63

    Ví dụ về con trỏ

    // tăng j (thông qua q) và hỏi j, j = 6

    (*q)++ ;

    cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    37/63

    Phép toán con trỏ

    Phép toán gánGán con trỏ với địa chỉ một biến: p = &i ;

    Gán con trỏ với con trỏ khác: p = q ;Phép toán tăng giảm địa chỉ

    p ± n: con trỏ trỏ đến thành phần thứ n sau (trước) p 

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

     

    của biến được trỏVí dụ giả sử p là con trỏ nguyên (2 byte) đang trỏ đếnđịa chỉ 200 thì p+1 là con trỏ trỏ đến địa chỉ 202, p - 3chứa địa chỉ 194

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    38/63

    Ví dụ về phép toán +/- con trỏ

    int a[100] = { 1, 2, 3, 4, 5, 6, 7 };int *p, *q;

    // cho p trỏ đến mảng a, *p = a[0] = 1p = a; cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    39/63

    Phép toán con trỏ

    Phép toán tự tăng giảmp++, p--, ++p, --p: tương tự p+1 và p-1, chú ý đến tăng

    (giảm) trước, sauint a[2] = {3, 7}, *p = a;

    // tăng (sau) giá trị nơi p trỏ  ≡ tăng a[0] thành 4 

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    (*p)++ ;

    // tăng (trước) giá trị nơi p trỏ ≡ tăng a[0] thành 4++(*p) ;// lấy giá trị nơi p trỏ (3) và tăng trỏ p (tăng sau),// p -> a[1]*(p++) ;

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

    *(++p) ;

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    40/63

    Phép toán con trỏ

    Hiệu của 2 con trỏPhép toán này chỉ thực hiện được khi p và q là 2 con

    trỏ cùng trỏ đến các phần tử của một dãy dữ liệu nàođó trong bộ nhớHiệu p - q là số thành phần giữa p và q

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    s p v q con r nguy n, p c a c v

    q có địa chỉ 208. Khi đó p - q = -4Phép toán so sánhSo sánh giữa địa chỉ của hai nơi được trỏ bởi các contrỏ nàyChỉ áp dụng cho hai con trỏ trỏ đến phần tử của cùngmột mảng dữ liệu nào đó

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    41/63

    Ví dụ về phép toán so sánh con trỏ

    float a[100], *p, *q ;

    // p trỏ đến mảng (tức p trỏ đến a[0])

    p = a ;// q trỏ đến phần tử thứ 3 (a[3]) của mảng

    q = &a[3] ;

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    cou

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    42/63

    Cấp phát động với con trỏ

    Cấp phát tĩnh: cấp sẵn trước khi chạy chương trình vàkhông thể thay đổi tăng, giảm kích thước hoặc vị trí trong

    suốt quá trình chạy chương trìnhCấp phát động: kích thước cụ thể (mảng) sẽ được cấpphát trong quá trình chạy chương trình

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    ng ng n a a c u c n gọ g

    phóng) số ô nhớ này để chương trình sử dụng vào việckhácViệc cấp phát và thu hồi này được thực hiện thông quacác toán tử new, delete và con trỏ p

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    43/63

    Cấp phát động với con trỏ

    Cú pháp của câu lệnh new.p = new ; // cấp phát 1 phần tử

    p = new [n] ; // cấp phát n phần tửNếu không có vùng nhớ với số lượng như vậy thì việc cấpphát là thất bại và p = NULL

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    Ví dụ:int *p ;

    // cấp phát vùng nhớ chứa được 1 số nguyên

    p = new int ;

    // cấp phát vùng nhớ chứa được 100 số nguyên

    p = new int[100] ;

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    44/63

    Ví dụ cấp phát động với con trỏ

    double *p ;

    int n ;cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    45/63

    Giải phóng bộ nhớ động

    Để giải phóng bộ nhớ đã cấp phát cho một biến (khi khôngcần sử dụng nữa) ta sử dụng câu lệnh delete.

    delete p ; // p là con trỏ được sử dụng trong new

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    p ng o n m ng ược c p p p ng qua con r  

    p ta dùng câu lệnh:

    delete[] p ; // p là con trỏ trỏ đến mảng

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    46/63

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

    Con trỏ trỏ đến mảng cũng tương tự trỏ đến các biến khác

    Con trỏ p trỏ đến mảng a thì p+i là địa chỉ thành phần thứ icủa mảng a và do đó: *(p+i) = a[i] = *(a+i).

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    v p ạ c v a , cụ v p ợp

    lệ còn a++ là không được phép (p thực sự là một biến, nó cóthể thay đổi được giá trị còn a là một hằng)

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    47/63

    Con trỏ và xâu ký tự

    Con trỏ kí tự có thể xem như một biến xâu kí tựKhác với mảng kí tự, ta được phép sử dụng phép gán cho 2

    xâu dưới dạng con trỏ Ví dụ:char *s, *t = "Tin hoc" ; 

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    s = ; ay c o m s rcpy s, ;

    Thực chất phép gán trên chỉ là gán 2 con trỏ với nhau

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    48/63

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    49/63

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

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

    a không được xem là mảng 1 chiều với 6 phần tử mà được 

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    quan n m n ư m ng m c u g m p n , m p n

    bộ 3 số thựcĐịa chỉ của mảng a chính là địa chỉ của phần tử đầu tiên a[0][0],và a+1 không phải là địa chỉ của phần tử tiếp theo a[0][1] mà là địachỉ của phần tử a[1][0]Phép gán p = a là dễ gây nhầm lẫn vì p là con trỏ float còn a làđịa chỉ mảng (1 chiều)

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    50/63

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

    Cách sai:p = a ; // sai vì khác kiểu

    Các cách đúng:// ép kiểu của a về con trỏ float (cũng là kiểu

    //của p)

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    p = oa a;

    p = a[0]; // gán với địa chỉ của mảng a[0]// gán với địa chỉ số thực đầu tiên trong a

    p = &a[0][0];

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    51/63

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

    Sau khi gán a cho p (p là con trỏ thực), việc tăng giảm p chính làdịch chuyển con trỏ trên từng phần tử (thực) của a.

    p trỏ tới a[0][0]

    p+1 trỏ tới a[0][1]

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    p+ r a

    p+3 trỏ tới a[1][0]p+4 trỏ tới a[1][1]

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

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    52/63

    Mảng con trỏ

    Nhiều con trỏ cùng kiểu cũng được tổ chức thành mảngMỗi phần tử của mảng con trỏ là một con trỏ trỏ đến một mảng

    nào đóCách khai báo:

    *tên_mảng_con_trỏ[size]; 

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    ụ:

    int *a[10];khai báo một mảng a chứa 10 con trỏ. Mỗi con trỏ a[i] chứa địa chỉ của một mảng nguyên nào đó (kích thước các mảng này có thểkhác nhau)

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    53/63

    Con trỏ và Hàm

    Giá trị trả lại của hàm là một mảng:Không có cách nào để giá trị trả lại của một hàm là mảng

    Hàm trả lại một con trỏ trỏ đến dãy dữ liệu kết quả là tươngđương với việc trả lại mảngMảng kết quả có thể được trả lại vào trong tham đối của hàm

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    ụ:

    int* tragiatri1(){

    // tạo mảng kết quả với 3 giá trị 1, 2, 3

    int kq[3] = { 1, 2, 3 };

    return kq ;

    }

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    54/63

    Con trỏ và Hàm

    int* tragiatri2()

    {

    // cấp phát 3 ô nhớ nguyênint *kq = new int[3];

    *kq = 1;

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    q+ = ;

    *(kq+2)=3 ;return kq ;

    }

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    55/63

    Con trỏ và Hàm

    main()

    {

    int *a, i;a = tragiatri1();

    for (i=0; i

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    56/63

    Con trỏ và Hàm

    Việc sử dụng hàm trả lại con trỏ là phải hết sức cẩn thận. Muốntrả lại con trỏ cho hàm thì con trỏ này phải trỏ đến dãy dữ liệu

    nào sao cho nó không mất đi sau khi hàm kết thúc như hàmtragiatri1()

    Nếu muốn trả lại giá trị con trỏ thì vùng dữ liệu mà nó trỏ đến 

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    p ược c p p m c c ư ng m n ng o n new ,

    chứ không để chương trình tự động cấp phát và tự động thu hồiĐối và giá trị trả lại là xâu kí tựĐối của các hàm xâu kí tự có thể khai báo dưới 2 dạng: mảngkí tự hoặc con trỏ kí tựGiá trị trả lại luôn luôn là con trỏ kí tự

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    57/63

    Con trỏ và Hàm

    Đối là hằng con trỏKhi các biến ngoài không có nhu cầu thay đổi nhưng đối tương

    ứng với nó vẫn phải khai báo dưới dạng con trỏCó khả năng do nhầm lẫn, các biến ngoài này sẽ bị thay đổingoài ý muốn

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    c n ược a o n ư m ng con r ng c c

    thêm trước khai báo kiểu của chúng từ khoá const

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    58/63

    Con trỏ Hàm

    Một hàm (tập hợp các lệnh) cũng có tên gọi , có địa chỉ lưu trongbộ nhớ và có thể truy nhập đến hàm thông qua tên gọi hoặc địa

    chỉ của nóĐể truy nhập (gọi hàm) thông qua địa chỉ chúng ta phải khai báomột con trỏ chứa địa chỉ này và sau đó gọi hàm bằng cách gọi tên

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    con r 

    Khai báo (*tên biến hàm)(d/s tham đối); (*tên biến hàm)(d/s tham đối) = ;Phân biệt giữa 2 khai báo: float (*f)(int) là khai báo con trỏ hàmcó tên là f và float* f(int) là khai báo hàm f với giá trị trả lại là mộtcon trỏ float

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    59/63

    Con trỏ Hàm

    /* khai báo con trỏ hàm có tên là f trỏ đến hàm

    có một tham đối kiểu int và cho giá trị kiểu

    float*/float (*f)(int);

    // con trỏ trỏ đến hàm với cặp đối (float, int).

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    vo oa , n ;

    Khởi ỏ Hà

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    60/63

    Khởi tạo con trỏ Hàm

    Cú pháp của khởi tạo cũng như phép gán là như sau:biến con trỏ hàm = tên hàm;

    Con trỏ hàm f và tên hàm được trỏ phải giống nhau về kiểu trảlại và danh sách đốiVí dụ:

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

      a o m u a

    float luythua(float, int);// khai báo con trỏ f tương thích với hàm luythua

    float (*f)(float, int);

    f = luythua; // cho f trỏ đến hàm luỹ thừa

    Sử d t ỏ hà

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    61/63

    Sử dụng con trỏ hàm

    Để sử dụng con trỏ hàm ta phải gán nó với tên hàm cụ thểBất kỳ nơi nào được phép xuất hiện tên hàm thì ta đều có thể

    thay nó bằng tên con trỏfloat bphuong(float x) {return x*x;

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    void main(){

    float (*f)(float);

    f = bphuong;

    cout

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    62/63

    Mảng con trỏ hàm

    Các con trỏ hàm giống nhau có thể được gộp lại vào trong mộtmảng

    Thêm [n] vào sau tên mảng với n là số lượng tối đa các con trỏVí dụ:void cong(int a, int b){

     

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    cou

  • 8/19/2019 Bai 5- Mang va Con tro.pdf

    63/63

    Mảng con trỏ hàm

    main()

    {

    clrscr();// khai báo, khởi tạo 4 con trỏ

    void (*f[4])(int, int) = {cong, tru, nhan, chia};

    TRƯỜNG ĐẠI HỌCBÁCH KHOA HÀ NỘI

    n m, n;

    cout "Nhập m, n " ; cin >> m >> n ;for (int i=0; i