Skip to content
Narrow screen resolution Wide screen resolution Auto adjust screen size Increase font size Decrease font size Default font size default color grey color
         
 | 
VNOI - Olympic tin học Việt Nam

Điểm tin VOJ

Số thành viên:6040
Số bài tập:1001
Số bài nộp:722923
Bài nộp hôm nay:0

Top 10 thành viên xuất sắc

HạngThành viênĐiểm
1mr_invincible587.9
2white_cobra418.6
3hieult403.4
4phaleq384.0
5vodanh9x368.2
6con_nha_ngheo352.0
7flash_mt350.2
8darksabers349.8
9yenthanh132345.3
10rockman9x_94343.1
Từ Pascal đến C (2) In E-mail
(13 votes)
Người viết: Ngô Minh Đức   
24/03/2008

Định kiểu

C cho phép chuyển đổi kiểu dữ liệu một cách trực tiếp. Thông thường bạn hay làm điều này khi sử dụng con trỏ. Định kiểu cũng hay xuất hiện trong phép gán với những dữ liệu nhất định. Ví dụ, trong đọan mã ở phần trên, giá trị integer được tự động chuyển đổi sang kiểu float.

Bạn thực hiện việc định kiểu trong C bằng cách đặt tên kiểu dữ liệu vào cặp dấu ngoặc và đặt trước giá trị bạn muốn thay đổi. Nghĩa là, trên đọan mã trên, nếu ta thay a=10/3; bằng a=(float)10/3; thì a sẽ nhận giá trị là 3.33333 bởi vì 10 được chuyển sang kiểu float trước khi thực hiện phép chia.

Kiểu dữ liệu tự định nghĩa

Trong ngôn ngữ C, lệnh typedef giúp bạn tự định nghĩa các kiểu dữ liệu. Ví dụ sau đây cho thấy một kiểu định nghĩa thường hay dùng trong C:

 

#define TRUE  1 

#define FALSE 0

typedef int boolean;

 

void main() 

{   

    boolean b;

    

    b=FALSE;   

    ...

}

 

Nếu bạn không thích từ ‘float’ cho kiểu số thực, bạn có thể viết:

typedef float real;

 

sau đó khai báo:

real r1,r2,r3;

Bạn có thể đặt lệnh typedef bất kỳ đâu trong chương trình C miễn là nó nằm trước khai báo các biến của nó.

Bản ghi

Kiểu bản ghi (record) trong C và Pascal rất giống nhau. Trước hết, bạn hãy xem đọan mã bằng Pascal:

type   

    rec=record     

        a,b,c:integer;     

        d,e,f:real;   

    end; 

var   

    r:rec;

 

Trong C, đọan mã tương đương được viết như sau:

struct rec 

{   

    int a,b,c;   

    float d,e,f; 

}; /* Lưu ý dấu chấm phẩy */

 

struct rec r;

 

Như đã thấy, mỗi khi muốn khai báo một kiểu bản ghi có tên rec, bạn phải viết lại dòng struct rec. Thông thường bạn hay quên chữ struct, do đó có thể thu gọn đọan mã lại như sau:

struct rec 

{   

    int a,b,c;   

    float d,e,f; 

} r;

Bạn truy cập vào các trường (fields) của record tương tự như trong Pascal, dùng một dấu chấm (.), ví dụ, r.a=5;

Bạn có thể khai báo typedef cho một kiểu record, ví dụ:

typedef struct rec rec_type;

 

Từ giờ bạn chỉ cần khai báo đơn giản:

rec_type r;

 

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 */

 

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 tóan tử này với 2 số nguyên thường cho ra kết qủa 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;

}

 

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 () ). Ngòai 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");    

}

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; 

}

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; 

}

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; 

}

 

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 lọai 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 đọan chương trình sau:

#include <stdio.h>

 

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, đọan 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 đọan 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; 

}

 

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. Đọan 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); 

}

Đô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ư resetrewrite 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 đọan 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);

}

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 đã hòan 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ùng fgets để đọc từng dòng và phân tích những thông tin bạn cần.

Đọan 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); 

}

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.

 
< Trước   Tiếp >