Kiểu mảng
Bạn khai báo mảng bằng cách chèn kích thước mảng vào sau một khai báo thông thường:
int a[10]; /* mảng số nguyên */
char s[100]; /* mảng kí tự (chính là chuỗi trong C) */
float f[20]; /* mảng số thực */
struct rec r[50]; /* mảng records */
char s[100]; /* mảng kí tự (chính là chuỗi trong C) */
float f[20]; /* mảng số thực */
struct rec r[50]; /* mảng records */
Gia/giảm giá trị
CÁCH DÀI | CÁCH NGẮN |
i= i + 1; | i++; |
i = i – 1; | i–; |
i = i + 3; | i += 3; |
i = i * j; | i *= j; |
Những lỗi cần tránh:
- Bạn hãy cẩn thận với dấu “/” vì như đã đề cập, sử dụng toán tử này với 2 số nguyên thường cho ra kết quả không mong đợi.
Hàm
Hầu hết các ngôn ngữ đều cho phép bạn sử dụng thủ tục (procedure), hàm (function), hoặc cả hai. Về bản chất, C chỉ cho phép sử dụng hàm, mặc dù bạn có thể khai báo thủ tục như hàm không trả về dữ liệu. Hàm trong C có thể chấp nhận một lượng không giới hạn các tham số. Như đã đề cập ở đầu bài viết, hàm trong C không thể đặt lồng nhau. Một điều nữa, trong C bạn không cần quan tâm đến thứ tự các hàm được đặt trong chương trình.
Chúng ta đã từng đề cập một ít về hàm; đó là hàm rand() ở phần trên. Nó không cần tham số và trả về một giá trị nguyên:
int rand()
{
rand_seed = rand_seed * 1103515245 +12345;
return (unsigned int)(rand_seed / 65536) % 32768;
}
{
rand_seed = rand_seed * 1103515245 +12345;
return (unsigned int)(rand_seed / 65536) % 32768;
}
Dòng int rand() khai báo hàm rand, xác định rằng nó không cần tham số và trả về một giá trị nguyên. Hàm này không cần biến địa phương; nhưng nếu cần, các biến này sẽ được đặt ngay sau dấu “{“.( Các biến này sẽ được đặt vào stack trong khi thực hiện thủ tục và được giải phóng ngay khi chạm đến dấu “}” ) ; Lưu ý rằng ngay khi không cần tham số bạn cũng phải đặt một cặp dấu ngoặc ().
Return là một lệnh quan trọng đối với bất kỳ một function nào có trả về giá trị. Nó sẽ trả về giá trị cho hàm và kết thúc hàm đó ngay lập tức. Điều này có nghĩa là bạn có thể đặt nhiều lệnh return trong một function để xác định những điểm kết thúc. Nếu trong function của bạn không có lệnh return, giá trị sẽ được trả về khi gặp dấu “}”; thông thường đó là những giá trị rác. Trong C, một hàm có thể trả về giá trị bất cứ kiểu gì.
Có nhiều cách gọi hợp lệ cho hàm rand() -ví dụ: x=rand(); (lưu ý bạn phải sử dụng cặp dấu ngoặc () ). Ngoài ra bạn có thể gọi như sau:
if (rand() > 100)
Hoặc như sau:
rand();
Trong trường hợp cuối cùng, giá trị trả về của hàm bị bỏ qua, không dùng đến.
Bạn có thể tạo ra thủ tục (procedure) giống như Pascal bằng cách cho hàm trả về kiểu void. Ví dụ:
void print_header()
{
printf("Báo Tin học & Nhà trường\n");
}
{
printf("Báo Tin học & Nhà trường\n");
}
Hàm này không trả về giá trị; do đó nó là một thủ tục. Bạn có thể gọi nó như sau:
print_header();
Bạn phải đặt dấu (), nếu không, thủ tục sẽ không được gọi, mặc dù vẫn được biên dịch đúng trên nhiều hệ thống.
Hàm trong C có thể chấp nhận tham số bất kỳ kiểu gì. Ví dụ hàm:
int fact(int i)
{
int j,k;
j=1;
for (k=2; k<=i; k++)
j=j*k;
return j;
}
{
int j,k;
j=1;
for (k=2; k<=i; k++)
j=j*k;
return j;
}
trả về giai thừa của i, là một tham số kiểu integer. Bạn ngăn cách các tham số bằng dầu phẩy (,):
int add (int i, int j)
{
return i+j;
}
{
return i+j;
}
Ngôn ngữ C được thay đổi qua nhiều năm. Bạn có thể gặp các hàm được viết theo “kiểu cũ” như sau:
int add(i,j)
int i;
int j;
{
return i+j;
}
int i;
int j;
{
return i+j;
}
Trong trình biên dịch Turbo C, bạn sẽ nhận được lỗi: “Kiểu định nghĩa hàm này không được dùng nữa” (Style of function definition is now obsolete). Bạn nên sử dụng “kiểu mới” (“ANSI C”), cho dù vẫn nên biết cách viết trên để có thể đọc được tất cả các loại code.
Bạn nên dùng mẫu hàm (function prototypes) trong chương trình. Một mẫu hàm khai báo tên hàm, các tham số và giá trị trả về giống như khai báo forward trong Pascal. Để hiểu tại sao mẫu hàm lại có ích, bạn hãy thực hiện đoạn chương trình sau:
#include <stdio.h>
void main()
{
printf("%d\n",add(3));
}
int add(int i, int j)
{
return i+j;
}
void main()
{
printf("%d\n",add(3));
}
int add(int i, int j)
{
return i+j;
}
Trong nhiều trình biên dịch, đoạn mã trên vẫn được biên dịch đúng, bởi vì nó không kiểm tra tham số có hợp lệ với kiểu cũng như về số lượng hay không. Bạn có thể tốn nhìêu thời gian để hiệu chỉnh chương trình chỉ vì vô tình đặt nhiều hoặc ít hơn lượng tham số cần thiết.
Để giải quyết vấn đề này, C cho phép bạn đặt mẫu hàm ở phần đầu (thực tế là ở đâu cũng được) một chương trình. Bạn hãy thử biên dịch đoạn mã sau:
#include <stdio.h>
int add (int,int); /* mẫu hàm cho add */
void main()
{
printf("%d\n",add(3));
}
int add(int i, int j)
{
return i+j;
}
int add (int,int); /* mẫu hàm cho add */
void main()
{
printf("%d\n",add(3));
}
int add(int i, int j)
{
return i+j;
}
Mẫu hàm trên sẽ giúp cho trình biên dịch phát hiện lỗi trên lệnh printf.
Nói chung, việc sử dụng mẫu hàm còn giúp chương trình sáng sủa, dễ đọc và dễ hiệu chỉnh hơn.
Xử lý file văn bản
Việc xử lý file văn bản (text) trong C tương đối dễ hiểu và dễ sử dụng. Chúng làm việc tương tự như những text files của Pascal. Tất cả các hàm và kiểu liên quan đến file trong C thuộc về thư viện chuẩn stdio.
Khi bạn chỉ cần đọc/ghi bằng bàn phím/ màn hình, bạn có thể sử dụng công cụ có sẵn của thư viện stdio là stdin (standard input) và stdout (standard output). Có 6 lệnh đọc/ghi sau đây cho phép bạn làm việc với stdin và stdout:
printf | In dữ liệu được định dạng ra stdout |
scanf | Đọc dữ liệu được định dạng từ stdin |
puts | In một chuỗi kí tự ra stdout |
gets | Đọc một chuỗi kí tự từ stdin |
putc | In một kí tự ra stdout |
getc, getchar | Đọc một kí tự từ stdin |
stdin và stdout có điểm thuận lợi là rất dễ sử dụng. Đoạn chương trình ví dụ sau đây giúp bạn đếm số kí tự nhập vào từ bàn phím:
#include <stdio.h>
#include <string.h>
void main()
{
char s[1000];
int count=0;
while (gets(s))
count += strlen(s);
printf("%d\n",count);
}
#include <string.h>
void main()
{
char s[1000];
int count=0;
while (gets(s))
count += strlen(s);
printf("%d\n",count);
}
Đôi khi bạn cần phải làm việc trực tiếp với file văn bản. Khi đó, bạn sẽ cần dùng đến các lệnh sau đây:
fopen | Mở một file văn bản |
fclose | Đóng một file văn bản |
feof | Kiểm tra kí tự kết thúc file |
fprintf | In dữ liệu được định dạng ra file |
fscanf | Đọc dữ liệu được định dạng từ file |
fputs | In một chuỗi kí tự ra file |
fgets | Đọc một chuỗi kí tự từ file |
fputc | In một kí tự ra file |
fgetc | Đọc một kí tự từ file |
Lệnh fopen tương tự như reset và rewrite trong Pascal. Nó mở một file theo một chế độ xác định (ba chế độ thường dùng là r (read), w (write) và a (append)). Sau đó, nó trả về một con trỏ đến file mà bạn sẽ dùng để truy nhập vào file đó. Chẳng hạn như bạn muốn mở một tập tin và viết các số từ 1 đến 10, bạn có thể dùng đoạn chương trình sau:
#include <stdio.h>
#define MAX 10
void main()
{
FILE *f;
int x;
f=fopen("number.out","w");
for(x=1; x<=MAX; x++)
fprintf(f,"%d\n",x);
fclose(f);
}
#define MAX 10
void main()
{
FILE *f;
int x;
f=fopen("number.out","w");
for(x=1; x<=MAX; x++)
fprintf(f,"%d\n",x);
fclose(f);
}
Lệnh fopen mở một file tên là number.out ở chế độ w. Tương tự như rewrite trong Pascal, chế độ này sẽ tạo ra file mới khi file cần mở không tồn tại, và xóa bỏ nội dung đang có nếu file tồn tại. Con trỏ đến file được trả vào biến f. Nếu tập tin không thể mở được vì một lý do nào đó, f sẽ nhận giá trị NULL.
Lệnh fprinf cũng giống như printf, chỉ khác là nó dùng con trỏ file f ở vị trí tham số đầu tiên. Lệnh fclose đóng file khi bạn đã hoàn thành công việc.
Để đọc một file, mở nó ở chế độ r. Nói chung, không nên sử dụng fscanf khi đọc, trừ khi tập tin được định dạng chặt chẽ. Thay vào đó, nên dùngfgets để đọc từng dòng và phân tích những thông tin bạn cần.
Đoạn mã sau đọc một file và ghi nội dung file đó ra màn hình:
#include <stdio.h>
void main()
{
FILE *f;
char s[1000];
f=fopen("number.in","r");
while (fgets(s,1000,f)!=NULL)
printf("%s",s);
fclose(f);
}
void main()
{
FILE *f;
char s[1000];
f=fopen("number.in","r");
while (fgets(s,1000,f)!=NULL)
printf("%s",s);
fclose(f);
}
Lệnh fgets trả về giá trị NULL nếu gặp kí tự kết thúc file. Nó đọc một dòng (trong trường hợp trên lên đến 1000 kí tự ) và in nó ra stdout. Lưu ý lệnh printf không cần kí tự “\n” trong chuỗi định dạng nữa, bởi vì bản thân fgets khi đọc một dòng đã đọc cả kí tự “\n” ở cuối dòng
Những lỗi cần tránh:
- Vô tình viết close thay vì fclose. Thật ra có tồn tại hàm close, nên trình biên dịch sẽ chấp nhận cho bạn. Hơn nữa, hàm close đôi khi có vẻ họat động tốt; nhưng nếu bạn sử dụng nó trong một vòng lặp thì sẽ dẫn đến lỗi vì hàm close không đóng tập tin một cách chính xác.
0 nhận xét