Ôn Tập Function, Array, Struct Trịnh Tấn Đạt Khoa CNTT Đại Học Sài Gòn Email trinhtandatsgu edu vn Website https sites google comsitettdat88 Nội dung ▪ Hàm ▪ Mảng o 1D Array o 2D Array ▪ Kiểu struct ▪ Tạo số ngẫu nhiên trong CC++ ▪ Giới thiệu Ma trận thưa (sparse matrix) vs dense matrix (option) Macro vs Function ▪ Macro được dùng để chỉ những định nghĩa được viết ở phần Preprocessor, thay vì đặt nó vào trong phần thực thi của file nguồn Ví dụ define TONG HAI SO(x, y) (x) +(y) ▪ Function.
Trang 1Ôn Tập Function, Array, Struct
Trịnh Tấn Đạt
Khoa CNTT - Đại Học Sài Gòn
Email: trinhtandat@sgu.edu.vn
Trang 2▪ Tạo số ngẫu nhiên trong C/C++
▪ Giới thiệu Ma trận thưa (sparse matrix) vs dense matrix (option)
Trang 3Macro vs Function
▪ Macro: được dùng để chỉ những định nghĩa được viết ở phần Preprocessor, thay vìđặt nó vào trong phần thực thi của file nguồn
Ví dụ : #define TONG_HAI_SO(x, y) (x) +(y)
▪ Function: là một loại chương trình con, gồm tên hàm, các tham số và thân hàm(chứa các phát biểu chương trình), thực thi một việc cụ thể
Ví dụ: int TongHaiSo(int x, int y)
{
return x+y;
Trang 4printf("\nMAX= %d", timMax (a, b));
return 0 ; }
int timMax( int x , int y ) {
return ((x) > (y) ? (x) : (y));
}
Gọi hàm
Trang 6Ví Dụ
Tham chiếu và tham trị
int main() {
Tăng giá trị của biến lên một đơn vị
toán tử địa chỉ &
tham số hình thức và tham số thực cùng địa chỉ
các thay đổi cho tham số hình thức (trong hàm) không làm thay đổi đối với tham số thực.
Trang 7} void local_func() {
cout<<"global var in locAl function = " << global_var <<endl; // 10
int global_var = 5; // biến cục bộ cout<<"local var = " << global_var <<endl; //5 ::global_var = 20;
cout<<"local var = " << global_var <<endl; //5 cout<<"global var in locAl function = " << ::global_var <<endl; //20 Biến toàn cục (global variable)
và biến cục bộ (local variable)
Trang 8Array: 1D-Array
▪ Chỉ số của mảng bắt đầu từ 0 -> N-1 ( với N là số lượng phần tử của mảng)
▪ Toán tử [] : toán tử lấy chỉ số (chỉ dùng cho các dãy vùng nhớ liên tiếp)
Trang 9Lưu ý:
▪ Không thể dùng biến mảng như thông thường
▪ Mà phải dùng từng phần tử trong chúng Mỗi phần tử được dùng như một biến
Trang 10Biến mảng là tham số của hàm
▪ Tham số được khai báo như khai báo biến mảng
Ví dụ: void SapXepTang( int a[100] );
Tham số kiểu mảng truyền cho hàm chính là địa chỉ của phần tử đầu tiên của mảng
Có thể không cần xác định số phần tử của mảng
Mảng được chuyển tham chiếu (Mảng có thể thay đổi nội dung sau khi thực hiện hàm)
Ví dụ: Hàm xuất nội dung một mảng các số nguyên:
void xuatMang( int a[] , int N);
Ví dụ: Hàm nhập nội dung một mảng các số nguyên:
Trang 11Biến mảng là tham số của hàmLưu ý: Số lượng phần tử thực sự truyền qua biến khác
Lời gọi hàm
int tinhtongMang( int A[] , int N);
void sapxepTang( int A[] , int N);
void xoaDau( int A[] , int & N);
int main() {
int a[100], n;
tinhtongMang(a,n);
sapxepTang(a,n);
xoaDau(a,n);
Trang 12cout<<"Cac phan tu cua mang:";
for (int i = 0 ; i < n ; i++ )
{
int A[100]; // khai báo biến mảng int N; // số lượng phần tử trong mảng NhapMang(A,N);
XuatMang(A,N);
return 0;
}
Trang 14for (int i= 0 ; i < n ; i++ )
if ( a[i] thỏa yêu cầu bài toán ) // tùy yêu cầu điều kiện khác nhau
tong = tong + a[i];
return tong;
Trang 15Ví dụ
Đếm số lượng phần tử thỏa điều kiện
int Demsoluong(int a[], int n)
{
int dem = 0;
for (int i= 0 ; i < n ; i++ )
if ( a[i] thỏa yêu cầu bài toán ) // tùy yêu cầu điều kiện khác nhau
dem++;
return dem;
Trang 16Ví dụ: Kỹ thuật đặt cờ hiệu
Kiểm tra mảng a có phải là mảng toàn các số nguyên tố hay không?
int KiemTra (int a[], int n) {
int flag = 1; // thảo đk for (int i = 0; i < n ; i++) {
if (flag == 1)
return 1;
else return 0;
int LaSNT (int n)
Trang 17Ví dụ: Kỹ thuật đặt lính canh
int TimMax (int a[], int n)
{
int max = a[0]; // max là lính canh
for (int i = 1; i < n; i++)
if (a[i] > max)
max = a[i];
return max;
Trang 18Ví dụ : Kỹ thuật cầm canh (Sentinel)
Tìm kiếm phần tử x trong mảng Giả sử có đủ vùng nhớ để gán a[n] = x ; trước vòng lặp while
- > chuyện gì xảy ra?????
int TimKiem (int a[], int n, int x)
Trang 19Sắp xếp trên mảng
void HoanVi (int &x, int &y) {
int tam = x; x = y; y = tam;
if ( a[i] > a[j] )
HoanVi(a[i], a[j]);
} }
}
Trang 20Ví dụ:
Sắp xếp các phần tử trên mảng sao cho các số dương tăng dần và các số âm giảm dần
Trang 212D - Array
Cú pháp dùng cho mảng hai chiều (2D-Array):
<Kiểu_Cơ_Sở> <Tên_Biến_Mảng> [ <N1> ] [ <N2> ] ;
N1, N2: số lượng phần tử mỗi chiều
Ví dụ: int A[3][4]; // mảng 2 chiều A có 3 dòng và 4 cột
0 1
int a[10][20], b[10][20];float c[5][10];
char d[10][20];
Trang 23Truyền mảng cho hàm
❖ Truyền mảng cho hàm
Số lượng phần tử thực sự truyền qua biến khác
Lời gọi hàm
void NhapMangHaiChieu(int a[][100], int &m, int &n); void XuatMangHaiChieu(int a[][100], int m, int n);
void main() {
int a[50][100], m, n;
Trang 24cout<<"Nhap phan tu:";
cin>>a[ i ][ j ];
} }
void XuatMangHaiChieu (int a[][MAXC], int m, int n)
Trang 25cout<<a[i][j] << “ ”;
} cout << endl; // in xuống dòng }
}
Goi ham trong ham mainint main()
{int a[MAX][MAX];int n,m;
nhapmang(a,m,n); xuatmang(a,m,n);
return 0;
Trang 26return tong;
Trang 27cout<<"tai dong:"<<i;
cout<<"tai cot:"<<j;
return 1;
} return 0;
Trang 28▪ Struct (Cấu trúc) : là kiểu dữ liệu gồm một nhóm các thành phần có kiểu không
giống nhau, mỗi thành phần được xác định bằng một tên riêng biệt
{
<Kiểu dữ liệu thành phần> <Tên thành phần>;
<Kiểu dữ liệu thành phần> <Tên thành phần>;
<Kiểu dữ liệu thành phần> <Tên thành phần>;
<Kiểu dữ liệu thành phần> <Tên thành phần>;
….
};
Trang 30Khai báo biến kiểu cấu trúc
▪ Cú pháp: struct <tên kiểu cấu trúc> <tên biến cấu trúc>;
(trong C++ có thể bỏ struct)
▪ Nếu dùng typedef: <tên kiểu cấu trúc> <tên biến cấu trúc>;
Ví dụ: Khai báo biến đơn kiểu cấu trúc
typedef struct Point2D
{
float x;
float y;
};
// khai báo biến P1,P2
typedef struct PhanSo {
int tuso;
int mauso;
};
Trang 31Khai báo biến kiểu cấu trúc
▪ Khai báo mảng cấu trúc: cũng tương tự khai báo biến mảng trên các kiểu dữ liệu
khác
Cú pháp: <tên kiểu cấu trúc> <tên biến mảng cấu trúc> [ HẰNG_SỐ ] ;
typedef struct Point2D
Trang 32Truy xuất các thành phần trong struct
❖ Đặc điểm
▪ Không thể truy xuất trực tiếp
▪ Truy xuất thông qua toán tử thành phần cấu trúc hay còn gọi là toán tử chấm (dot operation) và tên thành phần
Cú pháp: <tên biến cấu trúc>.<tên thành phần>
Trang 33/* Danh sach nhan vien */
Trang 34cout<<"Nhap vao ho ten: ";
fflush(stdin); // ko co dong nay ????
gets(snv[i].hoten); // gets dugn nhap chuoi ky tu }
//in danh sach nhan vien …
for(i = 0; i<n; i++)
Ví dụ: Nhập xuất danh sách nhân viên
Trang 35Các lưu ý về cấu trúc
❖ Truyền cấu trúc cho hàm
▪ Giống như truyền kiểu dữ liệu cơ sở
Tham trị (không thay đổi sau khi kết thúc hàm)
Tham chiếu (thay đổi sau khi kết thúc hàm)
Trang 36Bài Tập
Ôn tập lại các bài tập vể function, array và struct trong môn học cơ sơ lập trình
Trang 37Tạo ngẫu nhiên trong C/C++
▪ Hàm srand()
Cú pháp: void srand (unsigned int seed);
Dùng để khởi tạo một số ngẫu nhiên theo một số seed
Để cho mỗi số seed khác nhau người ta thường dùng kèm với unsigned int
time(NULL) trong thư viện time.h, hàm time(NULL) trả về số giây đã trôi qua kể từ
ngày 1/1/1970
▪ Hàm srand() thường được gọi trước khi gọi hàm rand()
Trang 38Tạo ngẫu nhiên trong C/C++
▪ Hàm rand()
Cú pháp: int rand(void);
Trả về một số nguyên giả random trong khoảng từ 0 đến RAND_MAX
Hằng RAND_MAX được định nghĩa trong stdlib.h đảm bảo ít nhất bằng 32767
Nếu chỉ dùng hàm rand() thì sẽ cho ra những số random giống nhau mỗi lần chạy, vì
vậy người ta thường khai báo srand(time(NULL)) trước để kết quả random mỗi lần
mỗi khác nhau
Để lấy số ngẫu nhiên từ 0 đến n, ta sử dụng rand()%(n+1)
Trang 39Tạo ngẫu nhiên trong C/C++
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(){
Trang 40Câu hỏi
Phát sinh ngẫu nhiên mảng các số nguyên có K phần từ (100K 200) Yêu cầu cácphần tử được phát sinh ngẫu nhiên trong đoạn [1,10000]
Trang 41Tạo ngẫu nhiên trong C/C++
▪ Tạo ngẫu nhiên Số thực:
Để lấy giá trị từ 0.0 to 1.0
float r = static_cast (rand()) / static_cast (RAND_MAX);
Trang 42Tạo ngẫu nhiên trong C/C++
C code:
#include <stdio.h> /* printf, NULL */
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
int main() {
srand (time(NULL)); // seed initialization for (int i = 0; i < 10; ++i)
{ float r = (float) (rand()) / (float) (RAND_MAX); printf("%f\n", r);
} return 0;
Trang 43Tạo ngẫu nhiên trong C/C++
C++ code
#include <iostream> /* std::cout, std::enld */
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
int main() {
srand (time(NULL)); // seed initialization for (int i = 0; i < 10; ++i)
{ float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX); std::cout << r << std::endl;
} return 0;
Trang 44Sparse matrix vs Dense matrix
▪ Ma trận thưa (Sparse matrix) là loại ma trận có kích thước lớn nhưng phần lớn các
phần tử là 0
▪ Thực hiện tính tóa trên ma trận thưa, ta thường quan tâm đến không gian lưu trữ
và tốc độ tính toán sao cho tối ưu nhất
Trang 45Sparse matrix - applications
Ví dụ: The NYC subway system
Biễu diễn bằng ma trận kề
Mỗi trạm có liên kết với nhau sẽ được biễu diễn bởi một trọng số (khác 0 )
trong ma trận.
Ví dụ
Trang 46Sparse matrix - applications
Ví dụ: Computer vision – bài toán background subtraction
Trang 47Sparse matrix - applications
Ví dụ: Computer vision – bài toán background subtraction (2)
Trang 48Sparse matrix - applications
Ví dụ: Audio signal processing – bài toán lyric and music separation
Trang 49Sparse matrix - applications
Ví dụ: Face analysis system – bài toán illumination normalization
Trang 50Sparse matrix
▪ Lưu trữ ma trận thưa (có nhiều cách): chỉ lưu trữ thông tin của các phần tử khác 0Dùng Arrays
Dùng Linked Lists
DOK (Dictionary of keys)
LIL (List of lists)
COO (Coordinate list)
CSR (Compressed Sparse Row)
CSC (Compressed Sparse Column)
Trang 52Sparse matrix
Dùng Linked Lists
* Học trong môn Cấu trúc
dữ liệu và giải thuật
Trang 53Bài tập
Nhập ngẫu nhiên hai ma trận thưa kích thước NxN
A) Biễu diễn ma trận thưa bằng triples- (Row, Column, value)B) Tính tổng hai ma trận
C) Tìm ma trận chuyển vị
* Tìm hiểu thuật toán nhân nhanh hai ma trận thưa (option)