Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 15 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
15
Dung lượng
161,34 KB
Nội dung
CHƯƠNG : MẢNG VÀ BIẾN CON TRỎ 5.1/ Mảng : tập hợp biến kiểu xếp liên tiếp nhớ 5.1.1/ Mảng chiều : a/ Khái niệm : < kiểu phần tử > < tên mãng> [ < số > ] Ví dụ : int a [5 ] ; => a [0] a[1] a[2] a [3] a [4] ( số chạy từ đến n - ) Char S [20] ; => 'A' 'B' 'X ' S[0]S[1] S[19] b/ Cách nhập số liệu cho mảng từ bàn phím ( dùng hàm Random C) + Mảng số nguyên : Ví dụ : Nhập vào mảng số nguyên phần tử #include < stdio.h> #include < conio.h> #define n main () { int a [ n ] ; int i ; for ( i = ; i < n ; i ++ ) { printf ( " a [ %d ] = " , i ); scanf ( " % d" , & a [ i ]); } /* Xuất số liệu mảng hình */ for ( i = ; i < n ; ++ i) printf ( " \ n a [ % d ] = % d ", i , a [ i ]); getch (); } + Mảng số thực float : #include #include < conio.h> #define n ; main () { float a [ n ] , tam ; .scanf ( " % f " , &tam) ; /*nhập qua biến trung gian tạm */ a [ i ] = tam ; c/Khởi tạo mảng : a [ ] = { 1,2,3,5,4 }a[0]=1 a[2]=2 a[4]=4 d/ Mảng ký tự : - chuỗi ký tự kết thúc ký tự NULL có mã ASCII - Ví dụ : char S [3] = { 'L', '0', 'P'] : chuỗi không thiếu chỗ cho ký tự kết thúc NULL - Ta gán : char S [ ] = " Lop "; Ngôn ngữ C tự động ghi ký tự kết thúc NULL, tức ' \0 ' char S[ ] = " Lop " ; Khơng cần khai báo số phần tử mãng * Ví dụ : Nhập vàò mảng số nguyên sau xếp theo thứ tự tăng dần : #include < stdio.h> #define n main ( ) { int a [ n ] ; int i , j, t ; for ( i = ; i > n ; i ++ ); { printf ( " nhập a [ % d] = " , i ); scanf ( " %d", & a [i ]); } /* Sắp xếp tăng dần */ for ( i = ; i < n - ; i ++) for ( j = i + ; j < n ; j ++ ) if ( a [ i ] < a [j ] ) { t = a [ i ] ; a [ i ] = a [ j ]; a [j ] = t ; } /* in kết */ for ( i = ; i < n ; i ++ ) printf ( " % 5d " , a [ i ] ); getch ( ); } Ví dụ : Làm lại ví dụ viết riêng hàm xếp truyền tham số cho mảng chiều #include #include #define N void sapxep ( int a [ ] , int n ); void main ( ) { int a [ N ] ; int i ; /* nhập số liệu cho mãng */ for ( i = ; i < N , i ++ ) { printf ( " A [ %d ] = ", i ); scanf ( " %d ", & a [ i ] ); } /* gọi hàm xếp để tăng dần */ sapxep ( a, N ); /* in kết */ for ( i = ; i < N ; i ++ ) printf ( " %5d ", a [ i ] ); getch ( ); } /* hàm xếp tăng dần */ void sapxep ( int a [ ], int n ) { int i, j, t ; for ( i = ; i > n - ; i ++) for ( j = i + ; j < n ; j ++ ) if ( a [ i ] > a [ j ] { t = a [ i ] ; a [ i ] = a [ j ] ; a [j ] = t ; } * Ví dụ : chuyển đổi chuỗi ký tự thường thành Hoa Chú ý : + Hàm tolower ( ch ) : đổi ký tự ch thành thường + Hàm toupper ( ch ) : đổi ký tự ch thành Hoa + Cả hàm năm thư viện : < ctyte.h> Giải : #include < stdio.h> # include < ctyte.h> #define n 20 main ( ) { char s [ n ] ; int i ; for ( i = ; i < n ; i ++ ) s[ i ] = toupper ( getchar ( ) ) ; /* nhập ký tự đổi thành hoa lưu vào mãng */ /* kết xuất chuỗi s */ for ( i = ; i < n ; i ++ ) putchar ( s [ i ] ) ; /* putchar ( ch ) : in ký tự ch hình */ getch ( ) } Bài tập : 1/ viết chương trình nhập số liệu cho mảng A gồm N phần tử mảng B gồm n phần tử , sau ghép mãng A B thành mãng C gồm m + n phần tử xếp tăng dần ( Bài phải dùng hàm nhập số liệu cho mảng hàm xếp) - Tính tổng phần tử âm, dương, số chẳn, số lẽ tổng tất phần tử mãng C [ m + n ].In số lẻ hàng số chẵn hàng - Nhập vào giá trị tìm xem giá trị có thuộc vào mãng C khơng Nếu có in tất phần tử tìm 5.2/ Mãng nhiều chiều : a/ Khai báo : < kiểu phần tử > < tên mãng > [ < số hàng > ] [ < số cột >] *Ví dụ : int a [ ] [ ] ; float b [ ] [ ] ; char c [5 ] [6 ] ; => a [ ] [0 ] a [ ] [ ] a [ ] [ ] a [ ] [ 1] a[2][0]a[2][1] Ví dụ : #define Hang # define Cot int a [ Hang ] [ Cot ] ; => ta có biến chạy i ( số chạy từ đến ( Dong - 1)) ta có biến chạy j ( số chạy từ đến ( Cot - )) a [0] [0] a [0][1] a [ ][Cot - 1] a [1] [0] a [1][1] a [a][Cot - 1] a[Dong-1][0] a[Dong-1][Cot-1] *Ví dụ : Viết chương trình tính tổng, tích số mãng số thực a[3][2] ; #include < stdio.h> #define N #define N main ( ) { int i , j ; float a [M][N] ; float tong, tich, tam ; /* nhập số liệu */ for ( i = ; i < M ; i ++ ) for ( j = ; j < N ; j ++ ) { printf ( " nhập a [ %d][%d] = " , i , j ); scanf ( " %f " , & tam ) ; a [i][j] = tam ;} /* tính tổng */ Tong = ; Tich = 1; for ( i = ; i < M ; i ++ ) for ( j = ); j < N ; j ++ ) { Tong = Tong + a [ i ][j] ; Tich = Tich * a [i][j] ; } /* in kết */ printf ( " Tổng tổng = %f, TONG ); printf ( " tích TICH = %F, TICH ); getch ( ) ; } b/ Truyền tham số mãng nhiều chiều cho hàm ( tham số thực tên mãng nhiều chiều ) - giả sử a mãng chiều : float a[M][N] + Chương trình gọi : { float a [M][N] Tong ( a ) ; ( truyền địa mãng cho hàm ) } + Chương trình bị gọi ( chương trình ) : float tong ( float a[ ][N] ) /* khai báo đối để nhận địa mãng */ { } Note : hàm tong dùng mãng hai chiều có N cột số hàng khơng quan trọng, khơng khai báo ) : * Ví dụ : Viết chương trình tính tổng ma trận cấp m x n theo công thức : C[i][j] = a[i][j] + b [i][j] #include #define m #define n /* prototype ( khai báo hàm )*/ void nhap ( int a[ ][N] , int M, int N ); void TongMT ( int a[ ][N], int b[ ][N] , int c [ ][N], int M , int N ); void InMT ( int c [ ][N], int M, int N ); /* chương trình */ { int a [M][N], b[M][N], c[M][N] ; /* gọi hàm */ Nhap ( a, M ,N ) ; nhap ( b, M,N); TONGMT ( a, b, c , M, N ); InMT ( c, M, N ); Getch ( ) ; } /* Hàm nhập số liệu cho mãng chiều m x n phần tử */ void Nhap ( int a [ ][N] , int M , int N ) { int i , j ; for ( i= ; i < M ; i ++ ) for ( j = ; j < N ; j++ ) { printf ( " a[%d][5d] = " , i , j ) ; scanf ( " %d " , &a [i][j]) ; } return ; } Void TongMT ( int a [ ][N], int b [ ][N], int c [ ][N], int M , int N ) { int i, j ; for ( i = ; i < M ; i ++ ) for ( j = ; j < N ; j ++ ) c [i][j] = a [i][j] + b [i][j] ; return ; } /* in kết */ void inMT ( int c[ ][N], int M, int N ) { int i, j ; for ( i = o ; i < M ; i ++ ) { for ( j = ; j < N ; j ++ ) printf ( " % 3d", a[i][j] ); printf ( " \n " ) ; /* xuống dòng */ } return ; } BàI TậP MãNG : 1/ cho mãng chiều A, ma trận vng cấp n x n , lập chương trình : a/ tính tổng tất phần tử dương mãng b/ tính tổng phần tử A[i][j] mà i + j chia hết cho c/ In số nguyên tố theo hàng d/ Sắp xếp theo hàng e/ Sắp xếp theo cột f/ Tính tổng phần tử đường chéo ( i = j ) , đường biên g/ Tìm max ; theo hàng, cột toàn ma trận 2/ Một chuỗi gọi palindrone khơng thay đổi ta đảo ngược thứ tự ký tự ( ví dụ " 12321 " ) Lập chương trình đọc chuỗi ( xâu ) ký tự xác định xem có tính palondrone khơng 5.3/ Biến trỏ : 5.3.1/ Khái niệm trỏ ( pointer ) địa : - Mỗi biến ngơn ngữ C có tên tương ứng với vùng nhớ dùng để chứa giá trị Tuỳ theo biến mà vùng nhớ dành cho biến có độ dài khác Ðịa biến sô thứ tự byte tương ứng với biến Ðịa biến có kiểu khác khác Ðịa biển kiểu int liên tiếp cách byte , biến kiểu float byte - Con trỏ biến dùng để chứa địa biến khác hàm Do có nhiều loại địa nên có nhiều loại biến trỏ Con trỏ kiểu int dùng để chứa địa kiểu int Con trỏ kiểu float dùng để chứa địa kiểu float - Muốn sử dụng pointer, trước tiên phải có địa biến mà ta cần quan tâm phép toán lấy địa & Kết phép lấy địa & phần tử * Ví dụ : int num ; => &num địa num int pnum ; /* pnum pointer đến int */ pnum = & num ; /* pnum chứa địa biến int num*/ giả sử : num = ; => * pnum = /* * toán tử nội dung */ Hai câu lệnh sau tương đương Num = 100 ; ( * pnum ) = 100 ; - Quy tắc khai báo biến trỏ : < kiểu liệu> * < tên biến trỏ > *Ví dụ : int a, *p ; a = ; /* giả sử địa a < 106 > */ p = & a ; /* p = */ p = a ; /* phép gán sai */ * p = a ; /* phép gán */ scanf ( " %d " , &a ) ; tương đương scanf ( " %d , p ) ; 5.3.2/ tính tốn biến trỏ ( pointer ) a/ Hai biến trỏ kiểu gán cho : Ví dụ : int a, * p, *a ; float * f; a = ; p = &a ; q = p ; /* */ f = p ; /* sai khác kiểu */ f = ( float * )p ; /* nhờ ép kiểu trỏ nguyên kiểu float */ Ví dụ : int a ; char *c ; c = &a ; /* sai khác kiểu */ c = ( char*) /* */ b/ Một biến pointer cộng, trừ với số nguyên ( int , long ) kết pointer * Ví dụ : int a , *p , * p10 ; a=5; p = &a ; p10 = p + 10 ; Ví dụ : int V[10] ;/* mãng 10 phần tử */ int *p ; p = & V[0]; for ( i = ; i < 10 ; i ++ ) { *p = i ; /* gán giá trị i cho phần tử mà p trỏ đến */ p ++ /* p tăng lên để đến phần tử */ } /* kết V[0] = , V [ 1] = V[9] = * / c/ Phép trừ pointer cho kết số int biểu thị khoảng cách ( số phần tử ) pointer d/ Phép cộng pointer không hợp lệ, pointer không nhân chia với số nguyên nhân chia vơi e/ p = NULL : trỏ p không trỏ đến đâu Chú ý : không sử dụng biến trỏ chưa khởi gán Ví dụ : int a , *p ; Scanf ( "%d", p ) ( sai ) => thay lệnh : p = &a scanf ( "%d" p ) ( đúng) 5.4/ Con trỏ mảng : 5.4.1/ Mãng chiều trỏ : - Trong ngôn ngữ C : mãng trỏ có mối quan hệ chặt chẽ Các phần tử mãng xác định nhờ số thơng qua trỏ - Ví dụ : int A[5] ; * p ; P=A; + mãng bố trí nhớ liên tiếp ( ô chiếm byte ) + Tên mãng địa ( không thay đổi ), địa phần tử => A tương đương với &A[0] (A + i ) tương đương với &A[i] *(A + i ) tương đương với A[i] p = A => p = &A[0] ( p trỏ tới phần tử A[0]) *(p + i ) tương đương với A[i] =>bốn cách viết sau tương đương : A[i], * ( a + i ), * ( p + i ), p[i] Ví dụ : int a [5] ; *p ; p=a; for ( i = 0; i < ; ++ i) scanf ( " %d ", &a[i]); ( 1) scanf ( " %d ",a + i ); ( 2) scanf ( " %d", p + i ); ( 3) scanf ( " % d", p ++ ); ( 4) scanf ( " %d ", a ++ ); sai địa a - Các lệnh (1), (2), (3), (4) tương đương Ví dụ : Nhập số nguyên vào mãng gồm phần tử ( a[5]) sau xếp tăng dần, in số lớn vf nhỏ tính tổng số #include #define n main ( ) { int a [n], t , *p, i , j, ; int s ; p=a; for ( i = 0; i < n ; i ++ ) { printf ( " a[%d] = " , i ) ; scanf ( " %d ", p + i ) } /* Sắp xếp tăng dần */ for ( i = ; i < n-1 ; i ++ ) for ( j = i + ; j * ( a + j ) { t = * ( a + i ) ; *(a + i ) = * ( a + j) ; *(a + j ) = t ; } s= ; for ( j=0 ; i < n , ++i ) s + = a[ i]; printf ("\n Tong = %5d ", s ); printf ( "\n số lớn %d ", a [4] ); printf ( " số nhỏ %d \n ", a [d] ); getch ( ); } 5.4.2 / Con trỏ mãng nhiều chiều : - Phép toán lấy địa & áp dụng với mãng chiều kiểu ngun Các kiểu khác khơng * Ví dụ : int a[2][3] { scanf ( "%d", & a[1][1]) } ( ) * Ví dụ : float a[2][3] Scanf (" %f", &a[1][1]); ( sai ) - Mãng chiều a[2][3] => gồm x = phần tử có địa liên thứ tự sau : Phần tử : a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] ( * ) Ðịa : - Ngôn ngữ C quan niệm mãng chiều mãng chiều mãng a[2][3] tương đương không phần tử mà phần tử gồm số nguyên nên : a trỏ tới hàng thứ ( a [0][0] ) a+1 trỏ tới hàng thứ hai ( a[1][0] ) - Do để duyệt phần tử mãng a[2][3] ta dùng trỏ theo cách sau : + ( theo * ) => ta có cơng thức a[i][j] = ( int*) a + i * n + j : int* : trỏ a ( địa a ) n : số cột - float a[2][3] , *p ; p = ( float*)a ; /* ý lệnh */ : p trỏ tới a[0][0] /* p = & a[0][0] */ p + trỏ tới a[0][1] /* *(p+1) = a[0][1] */ P + trỏ tới a[0][2] p + trỏ tới a[1][2] /* *(p+5) = a[1][2] */ * Tổng quát : a[i][j] = * ( p + i* N + ); N : số cột ) Kết luận : Mãng chiều chuyển thành mãng chiều nhờ trỏ * Ví dụ : để nhập số liệu vào mãng chiều kiểu float a[2][3] ta dùng cách sau: + Cách : #include " stdio.h " main ( ) { float a[2][3] , *p ; int i ; p = (float*)a ; /* lưu ý lệnh */ for ( i = ; i < 2*3 ; ++i) scanf ( "%f", (p+i)) ; /* (p_+ i ) địa */ ( X ) } + Cách : Sửa lệnh ( X ) sau : scanf ( "%f", (float*)a + ) ; + Cách : #include " stdio.h " #define m #define n main ( ) { float a[m][n] ; int i , j ; float *p ; p = ( float* )a ; for ( i=0 ; i [] * Ví dụ : int *a[5] ; - : a mãng gồm nhớ liên tiếp, ô nhớ biến trỏ trỏ đến kiểu int ; thân a dùng để lưu trữ số liệu - Giả sử : a < 110> a[0] a[1] a[2] a[3] a[4] a[5] Ðịa < 30> < 20> < 10 > < 80 > < 70 > < 100> 10 11 12345 12 13 - a= &a[0] => a = ( địa 100 ) - a[0] = < 30 > ( địa 30 : địa 30 trỏ a[0] trỏ đến địa giả sử địa < 30 > có giá trị ) => *a[0] = * (> = a[1] = < 20 > => *a[1] = a [2] = < 10> => *a[2] = Chú ý 1: Xem a trỏ lần ( trỏ trỏ ) : - a = => *a = ( a = &a[0] ) => **a = ( *()) - *(*(a + 1) + ) *(102) * ( + ) => * = Chú ý : - int a[5] => a trỏ khơng thay dổi địa ( nên a++ sai) - int *a[5] ; => a laf trỏ động nên thay đổi giá trị ( a++ ) Ví dụ : int *a[5] For ( i = ; i < ; i++ ) { printf ("%d", *a[0] ); a[0]++ ; } * Chú ý : mãng chiều chẳng qua trỏ lần ( trỏ trỏ ) Lý : a[i][k] ; đặt b = a[i] => b[k] = a[i][k] ; + Công thức : ( a[i] = *(a+i)) => ( b[i] = *(b+i)) b[k] = *(b+k)) b[k] = *(a[i] + k ) = * ( *(a+i) + j) => a[i][k] = *(*(a+i) + k) ; *(*(a+i) trỏ lần 5.4.4/ Con trỏ xâu ký tự : - Xâu ký tự : dãy ký tự đặt ngoặc kép Ví dụ : " Lớp học " Xâu chứa mãng kiểu char L O P H O C \0 Ðịa : NULL : kết thúc chuỗi => char *lop ; lop = " Lop Hoc " ; Ðúng : gán địa chuỗi cho trỏ lớp + puts (" Lop Hoc ") ; puts (lop ) đểu hiển thị dịng chữ Lop Hoc Ví dụ : char Tenlop[10] ; Printf ("\n Tenlop : " ) ; gets( Tenlop ) ; => ( Nhập vào chuỗi " lớp học " ) Còn khai báo sau sai : Char *lop , tenlop [10] ; Tenlop = " lớp học " ; sai Tenlop chuỗi trỏ , không gán cho Muốn gán ta dùng hàm strcpy (Tenlop , "lớp học "); 5.4.5/ Con trỏ việc định vị nhớ động : - Ví dụ : #define N=10 ; main ( ) { int a[N] ; int m : printf ( " nhập số phần tử m = "); scanf("%d", &m) ; for ( i= ; i < m ; i++ ) scanf ( "%d", &a[i] ); - Nhận xét Ví dụ : + Nếu m N ( tức m > 10 ) : chương trình chạy sai ta khơng đủ biến mãng => Do ta phải khắc phục cách : định vị nhớ động ( Bằng hàm malloc calloc) * Ví dụ : #include < stdio.h> #include #include main ( ) { int m , *a ; printf (" Nhập số phần tử m = " ); scanf ( "%d", &m ); /* Cấp phát định vị nhớ động */ a = ( int*) malloc ( m* size of ( int ) ); (1) if ( a!= NULL ) /* cấp phát thành công */ for ( i=0 ; i < m ; i++) scanf ( "%d", &a[i] ); free (a) ; /* giải phóng vùng nhớ mãng */ } - Hàm malloc ( ) nằm thư viện Hàm cung cấp số lượng byte liên tiếp từ phần nhớ chưa sử dụng máy tính + Ví dụ : malloc (num) = num byte trả trỏ kiểu void trỏ đến địa bắt đầu ô nhớ - Size of ( int ) : số byte mà biến kiểu int yêu cầu ( giá trị = ) - ( int*) : ép kiểu ( type - casing) : coi địa bắt đầu int ( malloc trỏ trỏ kiểu void , đặc biệt khơng có kiểu ) , nhận địa kiểu ( nhờ ép kiểu ) - Muốn sử dụng hàm calloc thay cho hàm malloc => khai báo : a = (int*) calloc ( n, size of (int)); * Chú ý : Luôn gán địa cho trỏ trước sử dụng tới Nếu khơng biến trỏ mang giá trị ngẫu nhiên phá huỷ chương trình * Cấp phát nhớ động cho mãng chiều m x n phần tử, m , n nhập từ bàn phím: + Ví dụ : #include #include Void main ( ) { int **a , m, n, OK ; printf ( " nhập m = " ); scanf ("%d", &m); printf (nhập m = n) ; scanf ( "%d", &n ); a = ( int** ) malloc ( m*seze of (int *)); if (a!=NULL ) /*Cấp phát thành công */ { OK = ; for ( i=0 ; i < m ; i++ ) } /* giá trị ban đầu cho biến trỏ*/ a[i] = (int*) break ; for ( i=0 ; i yêu cầu viết lại theo cách * Cách : void swap (float *x , float *y) /* viết đúng*/ { float temp ; temp = *x ; *x = *y ; * y = temp ; } main ( ) b/ Số học trỏ ( thao tác số học nội dung trỏ ) * Ví dụ : #include < stdio.h> #include main ( ) { #define N int *list , i ; list = int*) calloc ( N, size of(int)); *list = 15 ; * (list + 1) = 20 ; *(list + ) = 30 ; printf ( " địa : "); for ( i=o ; i < N ; i++) printf ("%4d",(list + i)); printf ("\n chứa giá trị : "); for ( i=0 ; i < N ; i++) printf("%4d", *(list + i)); printf("\n"); => list trỏ tới dãi nhớ dài byte ( 3*2) có giá trị 5,20, 30 giá trị địa đầu 06A => kết địa : 06A 06AC 06AE chứa giá trị : 20 30 c/ Con trỏ mãng : - Ví dụ : #include main ( ) { #define N int list [N] , i ; list [0] = ; list [1] = 20 ; list[2]=30; printf ( " Các địa : "); for ( i = ; i < N ; i++) printf ( "%4p ", &list[i] ); printf("\n chứa giá trị : "); for ( i=0; i{ list + i) = = &(list[i]) *(list + i) = = list[i]} d/ Con trỏ cấu trúc : - Ta khai báo trỏ biến cấu trúc, trỏ bấu kỳ kiểu liệu khác Ðiều cho phép tạo danh sách móc nối phần tử ( trình bày chương sau ) e/ Con trỏ tới hàm : dùng để chứa địa hàm Nên kiểu hàm trỏ phải giống Ví dụ : #include Double fmax ( double x, double y ) /* hàm tính max số */ { return ( x>y ? x:y ) ; } /* khai báo gán tên hàm cho trỏ hàm */ double (*pf) (double , double ) = fmax ; main ( ) { printf ( " In max = % f " , pf(15.5, 20.5 )); } vns3curity(HCE) ... lưu trữ số liệu - Giả sử : a < 110> a[0] a[1] a[2] a[3] a [4] a[5] Ðịa < 30> < 20> < 10 > < 80 > < 70 > < 100> 10 11 < 14> 12 345 < 24> ... ; a = 10.0 ; b = 20.0 ; printf (" chưa hoán vị a = %4. 0f; b = %4. 0f \n" , a , b ) ; swap ( a , b ) ; printf ( " sau hoán vị a = %4. 0f ; b = %4. 0f \n" , a, b ) ; - Phân tích sai cách ví dụ : +... ); ( 2) scanf ( " %d", p + i ); ( 3) scanf ( " % d", p ++ ); ( 4) scanf ( " %d ", a ++ ); sai địa a - Các lệnh (1), (2), (3), (4) tương đương Ví dụ : Nhập số nguyên vào mãng gồm phần tử ( a[5])