Ngôn ngữ lập trình c&c++ ( Phạm Hồng Thái) P13

Chia sẻ: Yukogaru | Ngày: | Loại File: PDF | Số trang:10

0
60
lượt xem
10
download

Ngôn ngữ lập trình c&c++ ( Phạm Hồng Thái) P13

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Chương 4. Hàm và chương trình Tham trị Tham chiếu Dẫn trỏ 7. Hàm và mảng dữ liệu a. Truyền mảng 1 chiều cho hàm Thông thường chúng ta hay xây dựng các hàm làm việc trên mảng như vectơ hay ma trận các phần tử. Khi đó tham đối thực sự của hàm sẽ là các mảng dữ liệu này. Trong trường hợp này ta có 2 cách khai báo đối. Cách thứ nhất đối được khai báo bình thường như khai báo biến mảng nhưng không cần có số phần tử kèm theo, ví dụ: − int x[]; − float x[]; Cách thứ...

Chủ đề:
Lưu

Nội dung Text: Ngôn ngữ lập trình c&c++ ( Phạm Hồng Thái) P13

  1. Chương 4. Hàm và chương trình Tham trị Tham chiếu Dẫn trỏ Khai báo đối void swap(int x, int y) void swap(int &x, int &y) void swap(int *x, int *y) Câu lệnh t = x; x = y; y = t; t = x; x = y; y = t; t = *x; *x = *y; *y = t; Lời gọi swap(a, b); swap(a, b); swap(&a, &b); Tác dụng a, b không thay đổi a, b có thay đổi a, b có thay đổi 7. Hàm và mảng dữ liệu a. Truyền mảng 1 chiều cho hàm Thông thường chúng ta hay xây dựng các hàm làm việc trên mảng như vectơ hay ma trận các phần tử. Khi đó tham đối thực sự của hàm sẽ là các mảng dữ liệu này. Trong trường hợp này ta có 2 cách khai báo đối. Cách thứ nhất đối được khai báo bình thường như khai báo biến mảng nhưng không cần có số phần tử kèm theo, ví dụ: − int x[]; − float x[]; Cách thứ hai khai báo đối như một con trỏ kiểu phần tử mảng, ví dụ: • int *p; • float *p Trong lời gọi hàm tên mảng a sẽ được viết vào danh sách tham đối thực sự, vì a là địa chỉ của phần tử đầu tiên của mảng a, nên khi hàm được gọi địa chỉ này sẽ gán cho con trỏ p. Vì vậy giá trị của phần tử thứ i của a có thể được truy cập bởi x[i] (theo khai báo 1) hoặc *(p+i) (theo khai báo 2) và nó cũng có thể được thay đổi thực sự (do đây cũng là cách truyền theo dẫn trỏ). Sau đây là ví dụ đơn giản, nhập và in vectơ, minh hoạ cho cả 2 kiểu khai báo đối. Ví dụ 8 : Hàm nhập và in giá trị 1 vectơ void nhap(int x[], int n) // n: số phần tử { int i; for (i=0; i> x[i]; // hoặc cin >> *(x+i) } void in(int *p, int n) { 109
  2. Chương 4. Hàm và chương trình int i; for (i=0; i
  3. Chương 4. Hàm và chương trình của phần tử này. Ưu điểm của cách khai báo này là ta có thể truyền mảng với kích thước bất kỳ (số cột không cần định trước) cho hàm. Sau đây là các ví dụ minh hoạ cho 2 cách khai báo trên. Ví dụ 9 : Tính tổng các số hạng trong ma trận float tong(float x[][10], int m, int n) // hoặc float tong(float (*x)[10], int m, int n) { // m: số dòng, n: số cột float t = 0; int i, j ; for (i=0; i> na; for (i=0; i
  4. Chương 4. Hàm và chương trình float min = *x; // gán phần tử đầu tiên cho min int k, kmin; for (k=1; k *(x+k)) { min = *(x+k) ; kmin = k; } cout
  5. Chương 4. Hàm và chương trình { float *t = new float[m*n]; // t là ma trận kết quả (xem như dãy số) int k, i, j ; for (k = 0; k < m*n; k++) *(t+k) = *(x+k) + *(y+k) ; inmt((float*)t, m, n); } main() { float a[8][10], b[5][7] ; int i, j, m, n; cout > m >> n; for (i=0; i
  6. Chương 4. Hàm và chương trình mảng cũng chính là một con trỏ, vì vậy việc 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ảng. Ngoài ra còn một cách dễ dùng hơn đối với mảng 2 chiều là mảng kết quả được trả lại vào trong tham đối của hàm (giống như nghiệm của phương trình bậc 2 được trả lại vào trong các tham đối). Ở đây chúng ta sẽ lần lượt xét 2 cách làm việc này. 1. Giá trị trả lại là con trỏ trỏ đến mảng kết quả. Trước hết chúng ta xét ví dụ nhỏ sau đây: int* tragiatri1() // giá trị trả lại là con trỏ trỏ đến dãy số nguyên { int kq[3] = { 1, 2, 3 }; // tạo mảng kết quả với 3 giá trị 1, 2, 3 return kq ; // trả lại địa chỉ cho con trỏ kết quả hàm } int* tragiatri2() // giá trị trả lại là con trỏ trỏ đến dãy số nguyên { int *kq = new int[4]; // cấp phát 3 ô nhớ nguyên *kq = *(kq+1) = *(kq+2) = 0 ; // tạo mảng kết quả với 3 giá trị 1, 2, 3 return kq ; // trả lại địa chỉ cho con trỏ kết quả hàm } main() { int *a, i; a = tragiatri1(); for (i=0; i
  7. Chương 4. Hàm và chương trình chỉ của kq trước khi nó kết thúc, thế nhưng sau khi hàm thực hiện xong, toàn bộ kq sẽ được xoá khỏi bộ nhớ và vì vậy con trỏ kết quả hàm đã trỏ đến vùng nhớ không còn các giá trị như kq đã có. Từ điều này việc sử dụng hàm trả lại con trỏ là phải hết sức cẩn thận. Muốn trả 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, hay nói khác hơn đó phải là những dãy dữ liệu được khởi tạo bên ngoài hàm hoặc có thể sử dụng theo phương pháp trong hàm tragiatri2(). Trong tragiatri2() một mảng kết quả 3 số cũng được tạo ra nhưng bằng cách xin cấp phát vùng nhớ. Vùng nhớ được cấp phát này sẽ vẫn còn tồn tại sau khi hàm kết thúc (nó chỉ bị xoá đi khi sử dụng toán tử delete). Do vậy hoạt động của tragiatri2() là chính xác. Tóm lại, ví dụ trên cho thấy nếu muốn trả lại giá trị con trỏ thì vùng dữ liệu mà nó trỏ đến phải được cấp phát một cách tường minh (bằng toán tử new), chứ không để chương trình tự động cấp phát và tự động thu hồi. Ví dụ sau minh hoạ hàm cộng 2 vectơ và trả lại vectơ kết quả (thực chất là con trỏ trỏ đến vùng nhớ đặt kết quả) int* congvt(int *x, int *y, int n) // n số phần tử của vectơ { int* z = new int[n]; // xin cấp phát bộ nhớ for (int i=0; i n; // nhập số phần tử for (i=0; i> a[i] ; // nhập vectơ a for (i=0; i> b[i] ; // nhập vectơ b c = congvt(a, b, n); for (i=0; i
  8. Chương 4. Hàm và chương trình - xem mục truyền tham đối thực sự theo dẫn trỏ). Ở đây ta xét 2 ví dụ: bài toán cộng 2 vectơ trong ví dụ trước và nhân 2 ma trận. Ví dụ 12 : Cộng 2 vectơ, vectơ kết quả trả lại trong tham đối của hàm. So với ví dụ trước giá trị trả lại là void (không trả lại giá trị) còn danh sách đối có thêm con trỏ z để chứa kết quả. void congvt(int *x, int *y, int *z, int n) // z lưu kết quả { for (int i=0; i n; // nhập số phần tử for (i=0; i> a[i] ; // nhập vectơ a for (i=0; i> b[i] ; // nhập vectơ b congvt(a, b, c, n); for (i=0; i
  9. Chương 4. Hàm và chương trình } } main() { int a[10][10], b[10][10], c[10][10] ; // khai báo 3 mảng a, b, c int m, n, p ; // kích thước các mảng cout > m >> n >> p ; // nhập số phần tử for (i=0; i
  10. Chương 4. Hàm và chương trình họ và tên không chứa các dấu cách đầu và cuối xâu, trong đó họ là dãy kí tự từ đầu cho đến khi gặp dấu cách đầu tiên và tên là dãy kí tự từ sau dấu cách cuối cùng đến kí tự cuối xâu. char* ho(char hoten[]) // hàm trả lại họ { char* kq = new char[10]; // cấp bộ nhớ để chứa họ int i=0; while (hoten[i] != '\40') i++; // i dừng tại dấu cách đầu tiên strncpy(kq, hoten, i) ; // copy i kí tự của hoten vào kq return kq; } char* ten(char* hoten) // hàm trả lại tên { char* kq = new char[10]; // cấp bộ nhớ để chứa tên int i=strlen(hoten); while (hoten[i] != '\40') i--; // i dừng tại dấu cách cuối cùng strncpy(kq, hoten+i+1, strlen(hoten)-i-1) ; // copy tên vào kq return kq; } void tachht(char* hoten, char* ho, char* ten) { int i=0; while (hoten[i] != '\40') i++; // i dừng tại dấu cách đầu tiên strncpy(ho, hoten, i) ; // copy i kí tự của hoten vào ho i=strlen(hoten); while (hoten[i] != '\40') i--; // i dừng tại dấu cách cuối cùng strncpy(ten, hoten+i+1, strlen(hoten)-i-1) ; // copy tên vào ten } main() { 118
Đồng bộ tài khoản