/ *g ọi hàm g() biến b được cấp phát
2. Tham số const
Rõ ràng với tham số là một con trỏ, một hàm có thể thay đổi nội dung của đối tượng bên ngồi được trỏ bởi con trỏ đó. Trong nhiều trường hợp ta muốn truyền vào cho hàm một con trỏ nhưng không muốn hàm làm thay đổi nội dung đối tượng được trỏ bởi con trỏ. Ví dụ như khi ta muốn truyền một xâu cho hàm cần phải dùng tham số là con trỏ xâu. Nhưng không phải lúc nào ta cũng cho phép hàm thay đổi nội dung của xâu truyền vào (vi dụ hàm strlen()). Để tránh người lập trình có thể sửa đổi một đối tượng trong hàm khi truyền dạng con trỏ ta có thể dùng từ khoá const. Một tham số con trỏ đã được xác định là const thì trong hàm khơng thể sử dụng nó để thay đổi nội dung đối tượng do nó trỏ tới.
Ví dụ:
/* xâu s truyền vào không thể bị thay đổi trong hàm strlen() */ int strlen(const char* s);
/* nội dung xâu s1 bị thay đổi cịn s2 khơng thay đổi trong hàm strcpy() */ char* strcpy(char* s1, const char* s2);
void foo(const int*p)
{ /* p là tham số trỏ const */
*p = 5; /* báo lỗi vì khơng được thay đổi đối tượng trỏ bởi p */ }
Chương trình mẫu (thambien.c): Tổ chức các hàm trong một chương trình làm các việc: nhập
dãy số, sắp xếp, tính tổng và in dãy số. #include <stdio.h>
#include <stdlib.h> #include <alloc.h>
/* chương trình nhập dãy số vào bộ nhớ động với n (int) là số phần tử của dãy
p (int*) là con trỏ đến dãy số trong bộ nhớ động */ */
/* hàm nhập dãy số, dùng tham số con trỏ để truyền tham biến truyền con trỏ n_ptr, p_ptr
chứa địa chỉ biến n, p nhận kết quả sau khi nhập */
void nhapday(int *n_ptr, int **p_ptr);
/* sắp xếp dãy số cần truyền tham số n và p */ void sapxep(int n, int*p);
/* tính tổng dãy số truyền tham số n và p
vì p trỏ tới dãy số và nội dung dãy số không đổi khi kết thúc nên p được truyền dạng const
*/
int sum(int n, const int *p);
/* in dãy số truyền tham số n và p */ void inday(int n, const int *p);
void main() {
int n, *p;
printf("Nhap day so nguyen\n");
/* gọi hàm nhập dãy số và truyền vào địa chỉ n và p */ nhapday(&n, &p);
printf("Day so da nhap:\n"); inday(n, p);
printf("Tong cua day: %d\n", sum(n, p)); printf("Day so da sap xep:\n");
sapxep(n, p); inday(n, p); }
void nhapday(int *n_ptr, int **p_ptr) {
int i;
printf("n = ");
/* nhập số phần tử vào biến n
n_ptr là địa chỉ của nó truyền vào cho hàm */ scanf("%d", n_ptr);
/* cấp phát mảng động cho con trỏ dãy số p con trỏ đến biến p là p_ptr */
*p_ptr=(int*)malloc(*n_ptr*sizeof(int)); for (i=0; i<*n_ptr; i++)
{
printf("So thu %d: ", i+1); scanf("%d", &((*p_ptr)[i])); }
}
{
int i, j, tg;
for (i=0; i<n-1; i++) for(j=i+1; j<n; j++) if(p[i]>p[j]) { tg = p[i]; p[i] = p[j]; p[j] = tg; } }
int sum(int n, const int *p) {
int i, s; s = 0;
for(i=0; i<n; i++) s += p[i]; return s;
}
void inday(int n, const int *p) {
int i;
for(i=0; i<n; i++) printf("%5d", p[i]); printf("\n");
}
Chương trình mẫu (sapten.c): Nhập và in danh sách tên các cá nhân có sắp xếp theo thứ tự bảng
chữ cái.
#include <stdio.h> #include <string.h>
/* hàm chuẩn hoá cắt các dấu cách thừa của một xâu */ char* chuanhoa(char* s);
/* hàm cho phép nhập một tên và chuẩn hố nó */ char* nhapten();
/* tách một xâu họ và tên thành xâu họ và xâu tên copy chúng vào bộ nhớ xâu tương ứng
*/
void tachhoten(const char* hovaten, char* ho, char* ten);
/* sắp xếp mảng con trỏ xâu sao cho các xâu theo thứ tự bảng chữ cái */ void sapxep(int n, char *danhsach[]);
void main() {
char * danhsach[100]; char * ten;
int i, n;
printf("Nhap danh sach ten, de ket thuc nhap ten rong.\n"); i = 0;
while(strcmp(ten=nhapten(), "")!=0) danhsach[i++] = ten;
n = i;
printf("Danh sach ten da nhap:\n"); for(i=0; i<n; i++)
printf("%3d. %s\n", i+1, danhsach[i]); } char* chuanhoa(char* s) { int i; i = 0; while (s[i]!='\0')
if (s[i]==' '&&(i==0||s[i+1]==' '||s[i+1]=='\0')) strcpy(&s[i], &s[i+1]);
else i++; return s; }
void tachhoten(const char* hovaten, char* ho, char* ten) { char * ptim; int dodai; ptim = strrchr(hovaten, ' '); if (ptim==NULL) { strcpy(ten, hovaten); strcpy(ho, ""); }else { strcpy(ten, ptim+1); dodai = ptim-hovaten;
strncpy(ho, hovaten, dodai); ho[dodai] = '\0'; } } char* nhapten() { char s[80];
printf("Nhap mot ten: "); gets(s);
chuanhoa(s); return strdup(s); }
void sapxep(int n, char *danhsach[]) {
char ho1[80], ten1[80], ho2[80], ten2[80]; int i, j;
char *tmp;
for (i=0; i<n-1; i++) for(j=i+1; j<n; j++) {
/* tách họ và tên của hai chuỗi rồi so sánh chúng */ tachhoten(danhsach[i], ho1, ten1);
strupr(ho1); strupr(ten1);
tachhoten(danhsach[j], ho2, ten2); strupr(ho2); strupr(ten2);
if(strcmp(ten1, ten2)>0||
(strcmp(ten1, ten2)==0&&strcmp(ho1, ho2)>0)) {
danhsach[i] = danhsach[j]; danhsach[j] = tmp; } } } BÀI TẬP
Câu 1: Tạo một hàm để tìm ra một dãy số đơn điệu tăng có số phần tử lớn nhất trong một dãy số.
Ví dụ dãy số 1 4 2 3 6 8 3 5 7 có dãy đơn điệu tăng với số phần tử lớn nhất là 2 3 6 8. Kết quả sau khi tìm kiếm sẽ là một con trỏ đến đầu dãy số tìm thấy và số phần tử của dãy đơn điệu tăng. Sử dụng hàm tạo ra để viết chương trình tìm dãy đơn điệu tăng có số phần tử lớn nhất cho một dãy số nhập vào. Chú ý nếu trường hợp có nhiều dãy có cùng số phần tử lớn nhất thì kết quả tìm thấy là dãy số đầu tiên.
Câu 2: Viết hàm để tách từ đầu tiên ra khỏi một xâu kí tự. Cất từ tách được vào một vùng nhớ có
địa chỉ truyền vào như là tham số của hàm. Xâu truyền vào sẽ chỉ giữ phần còn lại của xâu sau khi đã tách từ đầu tiên. Áp dụng hàm xây dựng được để viết chương trình in ra các từ của một xâu đọc vào từ bàn phím.