Sử dụng mảng
Trong phần này, bạn sẽ viết một chương trình tạo ra 10 số ngẫu nhiên và sau đó sắp xếp chúng:
#include <stdio.h>
#define MAX 10
int a[MAX];
int rand_seed=10;
int rand()/* trả về một số ngẫu nhiên giữa 0 và 32767*/
{
rand_seed = rand_seed * 1103515245 + 12345;
return (unsigned int)(rand_seed / 65536) % 32768;
}
void main()
{
int i,t,x,y;
/* tạo mảng */
for (i=0; i < MAX; i++)
{
a[i]=rand();
printf("%d\n",a[i]);
}
/* còn những lệnh khác sẽ được thêm vào vị trí này */
}
#define MAX 10
int a[MAX];
int rand_seed=10;
int rand()/* trả về một số ngẫu nhiên giữa 0 và 32767*/
{
rand_seed = rand_seed * 1103515245 + 12345;
return (unsigned int)(rand_seed / 65536) % 32768;
}
void main()
{
int i,t,x,y;
/* tạo mảng */
for (i=0; i < MAX; i++)
{
a[i]=rand();
printf("%d\n",a[i]);
}
/* còn những lệnh khác sẽ được thêm vào vị trí này */
}
Đoạn mã này chứa nhiều khái niệm mới. Dòng int a[MAX]; cho thấy cách khai báo mảng số nguyên trong C. Để ví dụ, khai báo int a[10]; trong Pascal sẽ tương ứng như sau:
a:array [0..9] of integer;
Trong ngôn ngữ C, tất cả các mảng đều có chỉ số bắt đầu từ 0 và kết thúc tại n-1. Do đó lệnh int a[10]; khai báo một mảng 10 phần tử, và chỉ số lớn nhất hợp lệ là 9. Không như Pascal, C không cho phép chỉ định phạm vi của các chỉ số.
Dòng int rand_seed=10 cũng khai báo một biến toàn cục. Biến này được gán giá trị mặc định bằng 10 khi chương trình bắt đầu. Lưu ý rằng trong một bộ sinh số ngẫu nhiên thực, giá trị seed cần được gán bằng các giá trị ngẫu nhiên, chẳng hạn như gán bằng giờ hệ thống,v.v… Còn ở đây, do rand_seed được gán cố định nên thủ tục rand sẽ cho ra các giá trị như nhau mỗi khi chạy chương trình.
Dòng int rand() khai báo một hàm (function). Câu lệnh tương đương trong Pascal là:
function rand:integer;
Có nghĩa là hàm rand không cần tham số và trả về một giá trị có kiểu integer.
Bốn dòng tiếp theo là phần thân của hàm rand.
Thủ tục main không có gì lạ: ta khai báo bốn biến địa phương; và điền vào mảng 10 số ngẫu nhiên nhờ một vòng for. Bây giờ bạn hãy thêm đoạn mã sau vào sau dòng chú thích còn những lệnh khác…
/* bubble sort */
for (x=0; x < MAX-1; x++)
for (y=0; y < MAX-x-1; y++)
if (a[y] > a[y+1])
{
t=a[y];
a[y]=a[y+1];
a[y+1]=t;
}
/* in ra mảng đã được sắp xếp */
printf("--------------------\n");
for (i=0; i < MAX; i++)
printf("%d\n",a[i]);
for (x=0; x < MAX-1; x++)
for (y=0; y < MAX-x-1; y++)
if (a[y] > a[y+1])
{
t=a[y];
a[y]=a[y+1];
a[y+1]=t;
}
/* in ra mảng đã được sắp xếp */
printf("--------------------\n");
for (i=0; i < MAX; i++)
printf("%d\n",a[i]);
Những lỗi cần tránh:
- C không kiểm tra range check, do đó bạn có thể sử dụng chỉ số vượt qúa phạm vi của mảng mà không biết.
- Lệnh gọi đến một hàm/thủ tục cần phải có dấu ngoặc , ngay cả khi không có tham số. Ví dụ, C vẫn chấp nhận lệnh x=rand; nhưng thủ tục sẽ không được thực thi; thay vào đó biến x sẽ nhận địa chỉ nhớ của thủ tục rand. Bạn phải viết là x=rand();
Các toán tử trong C
Các toán tử trong C cũng tương tự như trong Pascal:
Pascal | C |
+ | + |
- | - |
/ | / |
* | * |
div | / |
Mod | % |
Toán tử / thực thi phép chia nguyên khi cả hai toán hạng đều là số nguyên; trong những trường hợp còn lại nó thực thi phép chia thực
void main()
{
float a;
a=10/3;
printf("%f\n",a);
}
{
float a;
a=10/3;
printf("%f\n",a);
}
Đoạn mã trên sẽ in ra một giá trị thực bởi vì a được khai báo kiểu float, nhưng a sẽ nhận giá trị là 3.0 bởi vì đoạn mã thực hiện một phép chia nguyên
Trong C, thứ tự ưu tiên các toán tử cũng giống như của Pascal; dấu ngoặc đơn cũng điều khiển thứ tự thực hiện các phép tính. Chúng ta sẽ bàn kỹ hơn về vấn đề này khi đề cập đến kiểu con trỏ (pointer)
Đị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 đoạn 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 đoạn 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;
...
}
#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;
và 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 đoạn mã bằng Pascal:
type
rec = record
a,b,c:integer;
d,e,f:real;
end;
var
r:rec;
rec = record
a,b,c:integer;
d,e,f:real;
end;
var
r:rec;
Trong C, đoạn 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;
{
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 đoạn mã lại như sau:
struct rec
{
int a,b,c;
float d,e,f;
} r;
{
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;
0 nhận xét