Tải bản đầy đủ (.pdf) (51 trang)

Tài liệu Tóm tắt ngôn ngữ lập trình C ppt

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (683.18 KB, 51 trang )






Tóm tắt ngôn ngữ
lập trình C
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


1

Tựa đề trang sách


Cảm nghĩ:

Tôi viết lên những dòng này không mục đích gì khác ngoài :
1. Ghi chép lại những gì mình biết.
2. Chia xẻ kiến thức với những ngời bạn thân của Tôi và mong đợc góp ý
kiến những chỗ sai và thiếu sót để đợc bổ sung kiến thức .
Vì vậy những dòng chữ này không may ai có cầm phải nó xin đừng hỏi Tôi
là ai, vì Tôi chỉ là kẻ vô danh với các bạn, và hy xem đây là những dòng chữ
nguyệch ngoạc mà thôi. ( Tôi xin nói thật môn C này Tôi còn phải thi lại đấy !)
Xin chân thành cảm ơn !



Hà Nội, ngày 20 tháng 2 năm 2004

Tác giả














Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


2




Giới thiệu



Một cuốn C dày tới hơn 500 trang đó là cuốn sách hoàn hảo. Còn đây
Tôi chỉ đa ra đợc phơng pháp đọc và hiểu đợc phần nào cuốn sách đó
thôi. Tôi hi vọng cuốn sách C và thêm những lời giải thích này của Tôi,
những ai cha biết sẽ hiểu ra phần nào.
Tôi nhắc lại đây chỉ là những lời giải thích do Tôi hiểu khi đọc sách.
Chính vì vậy mà Tôi đặt cho nó cái tên là:

Tóm tắt ngôn ngữ lập trình C












Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C



3

Phần 1 : cấu trúc một chơng trình C.
I. Các #include<.> :

Đây là các th viện của ngời lập trình đã đợc Turbo C định nghĩa sẵn cho ngời
lập trình. Khi viết chơng trình ngời lập trình cần khai báo nó.
Một số th viện thờng dùng là:
- Th viện
#include<stdio.h>
: là th viện Vào / Ra chuẩn.
- Th viện
#include<conio.h>
: là th viện
- Th viện
#include<string.h>
: là th viện cho phép sử dụng các xâu kí tự.
- Th viện
#include<math.h>
: cho phép sử dụng các hàm toán học nh
sin,cos.
- Th viện
#include<malloc.h>
: là th viện cho phép khai báo động bộ
nhớ.
Đây là một số th viện thờng dùng, ngoài ra còn một số th viện khác nữa
(mong tự tìm hiểu).


Chú ý
:
Khi viết chơng trình nhất thiết phải khai báo th viện tơng ứng, nếu không máy
sẽ báo lỗi.

2. Hàm chính:

Đó là hàm
main()
tạm thời bạn hãy sử dụng nó còn phần giải thích xin đợc trình
bày trong phần Xây dựng và sử dụng Hàm.

3.Thân chơng trình:

Đợc bắt đầu bằng dấu khóa { ,tơng đơng với BEGIN trong ngôn ngữ
Turbo Pascal và kết thúc trơng trình bằng dấu } , tơng đơng với END.
Trong thân chơng trình thờng là các trình tự sau:
- Khai báo các biến,hằngcó sử dụng trong chơng trình.
- Nhập giá trị cho các biến nếu cần.
- Xử lý các phép toán.
- Đa ra kết quả sau xử lý.
Chú ý
:
Đây chỉ là cấu trúc cơ bản của chơng trình, cấu trúc sẽ khác và phức tạp hơn rất
nhiều, nếu ta sử dụng cấu trúc tự định nghĩa.

Thanh Tùng

KS 20
_

CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


4
II. Kiểu dữ liệu và vấn đề khai báo biến, hằng :
Kiểu dữ liệu có liên quan trặt trẽ với việc khai báo biến, hằng .Điều này là đơng
nhiên, bởi lẽ khi khai báo một biến nào đó bạn phải định kiểu dữ liệu tơng ứng cho nó,
còn việc hiểu biến, hằng là gì?, kiểu dữ liệu là gì ? Tôi xin trình bày một cách nôm na,
chắc là không chặt trẽ, nhng Tôi nghĩ nó rễ hiểu:
1.
Biến
:
Là giá trị đầu vào của chơng trình, nếu nó chỉ là thành phần trung gian để tính
toán ( trong trờng hợp này bạn phải nhập giá trị cho nó ) . Ngợc lại biến là giá trị đầu
ra, nếu nó là nơi chứa kết quả sau khi tính toán.


Chú ý
:
Biến có thể thay đổi giá trị trong chơng trình.
2.H
ằng
:
Là giá trị đầu vào của chơng trình, hằng không thể thay đổi đợc giá trị trong
suốt thời gian tính toán.
3.
Kiểu dữ liệu
:
Đã đợc C định nghĩa sẵn, gồm có một số kiểu cơ bản hay sử dụng sau:

+
Kiểu số nguyên
: Trong C nó đợc đặt tên là
int,
chiếm 2 byte trong bộ nhớ ,
có giá trị từ -32768 -> 32767 (2 byte). Tức là khi khai báo một biến nào đó, biến ấy
không thể nhận giá trị vợt quá giới hạn này đợc.
VD: int a=2345 đúng.
int a=32768 sai do vợt quá giới hạn.
Tuy nhiên kết quả tính toán đợc của một biến nào đó cũng không đợc vợt quá giới
hạn trên.
+
Kiểu số thực
: Có tên là
float,
chiếm 4 byte trong bộ nhớ phạm vi biểu diễn từ
-3.4E-38 đến 3.4E+38.
+
Kiểu kí tự
: Có tên là
char
, chiếm 1 byte trong bộ nhớ.
Đây là 3 kiểu dữ liệu đơn giản nhất và hay sử dụng nhất, ngoài ra còn rất nhiều kiểu
dữ liệu khác mục đích làm tăng phạm vi biểu diễn của 3 kiểu dữ liệu trên.
( nếu có nhu cầu xin tự tham khảo thêm ).




Thanh Tùng


KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


5
III. Lệnh vào ( nhập dữ liệu ), ra ( xuất dữ liệu ) trong C:

1.Cách khai báo trong C:

- Nếu là số nguyên:
int a;
với khai báo này ta nhận đợc một biến a có kiểu là số
nguyên.
- Nếu là số thực :
float b;
giải thích tơng tự trên.
- Nếu là mảng: VD :
float a[10];
mảng tên là a kiểu thực và có 10 phần tử,

int b[10];
mảng b kiểu nguyên có 10 phần tử.
Chú ý :

Khi nhập dữ liệu kiểu của biến tơng ứng.
2.Nhập ( vào dữ liệu ), xuất dữ liệu trong C:



a. Nhập dữ liệu
:
Cú pháp:

scanf(%.kiểu dữ liệu,&.biến);

VD : Giả sử có khai báo : float a;hoặc int b;
Câu lệnh nhập là : scanf(%f ,&a); hoặc scanf(%d,&b);
trong đó : - % : Bắt buộc phải có.
- Kiểu dữ liệu : Có thể là số thực (kí hiệu là
f
).
Có thể là số nguyên (kí hiệu là
d
).
Có thể là kí tự ( k/hiệu là
c
),
- & : Đại diện cho phép lấy địa chỉ.
- biến : Là 1 biến bất kì do bạn tự đặt.
b. Xuất dữ liệu:

Cú pháp :

printf( %.đặc tả.kiểu dữ liệu,biến);

trong đó: - Đặc tả : Là kĩ thuật lấy phần nguyên và phần thập phân.
+ Nếu viết đặc tả = 4.2f nghĩa là 4 số phần nguyên và 2 số phần
thập phân (cách viết này chỉ dùng cho số thực).

+ Đặc tả = 4d nghĩa là 4 chỗ cho chữ số đó. (chỉ sử dụng cho số
nguyên).
VD: printf(%4.2f,a); hoặc printf(%4d,b);


Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


6
IV.Chơng trình:
Trong 3 phần trên Tôi đã giới thiệu sơ qua những yếu tố cần thiết khi viết một
chơng trình. Trong phần này xẽ giới thiệu 1 cấu trúc chơng trình hoàn hảo và một số
câu lệnh cần thiết, bắt buộc trong chơng trình. Có ví dụ minh họa:
a. Cấu trúc:

1. Khai báo các th viện có liên quan.
2. Sau dấu
{
là phần khai báo các biến, hằng .. có sử dụng trong chơng trình.
3. Nhập dữ liệu cho các biến cần thiết.
4. Xử lý theo yêu cầu của đề bài để có đợc kết quả.
5. Xuất dữ liệu ra màn hình.
6. Kết thúc trơng trình bằng dấu
}
.

b.Các câu lệnh cần thiết:

1. Lệnh
getch();
: Lệnh này yêu cầu dừng màn hình để xem kết quả.
2. Lệnh
clrscr();
:Lệnh này dùng để xóa màn hình trớc khi xuất dữ liệu.

c. Ví dụ:

Tôi xin đa ra 1 ví dụ hết sức đơn giản là :
Cho hai số a, b là 2 số thực đợc nhập vào từ bàn phím . Yêu cầu tính tổng
của hai số đó kết quả đợc bao nhiêu chứa vào biến c, sau đó in kết quả ra màn hình.
Tóm tắt : Dữ liệu đầu vào gồm có : 2 biến a và b kiểu số thực .
Đầu ra : In giá trị nhận đợc của biến c (c phải là số thực).
Viết chơng trình
:
#include<stdio.h>
#include<conio.h >
main() /*hàm chính bắt buộc phải có*/
{
clrscr();
float a,b,c; /*khai báo biến*/
printf(nhập giá trị cho 2 biến:\ n);scanf(%f,&a);
scanf(%f,&b); /*nhập */
c=a+b; /*tính toán*/
printf(kết quả là c=%4.2f,c); /* xuất dữ liệu*/
getch(); /*dừng màn hình*/
}


Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


7
Bạn có thể tự lấy cho mình ví dụ đơn giản đề làm quen với ngôn ngữ này.
Bài tập ví dụ:
Giải phơng trình bậc nhất : ax + b = 0 ; với a,b là hai số thực nhập từ bàn
phím,và in kết quả ra màn hình.
Tóm lại:

- Khi viết một chơng trình bạn phải nắm đợc đề bài cho gì và yêu cầu làm gì.
Để đơn giản hóa Tôi thiết nghĩ bạn nên giải bài toán một cách bình thờng ra giấy. Sau
đó bạn tìm cách đa nó vào khuôn khổ của ngôn ngữ, với chú ý là.
Biến nhận kết quả (giá trị đầu ra) luôn nằm bên trái của phép toán.
Biến, hằng số tham gia thực hiện pháp toán (còn gọi là đầu vào) nằm bên phải
biểu thức.
VD: Viết ax=b; /*viết sai*/
Viết x=b/a /*viết đúng*/
- Sau khi viết đợc chơng trình này rồi, Tôi tin chắc rằng bạn xẽ đa ra kết luận
rằng Tôi phức tạp quá viết ra giấy còn nhanh và đơn giản gấp vạn lần. Bạn yên tâm cứ
hãy cố gắng đi, còn rất nhiều điều thú vị đang chờ bạn khi đó Tôi tin chắc bạn xẽ có
một cách nghĩ khác cho mà xem.

V. Các vòng lặp xác định và không xác định:



1. Cách thức lu trữ:

Trớc hết Tôi muốn giải thích cách lu trữ trong bộ nhớ của máy tính nh sau:
Khi mà bạn nhập dữ liệu vào máy tính đơng nhiên máy tính phải cấp phát
một khoảng nhớ để lu trữ dữ liệu, và nó có địa chỉ xác định

a.Với số thực
:
Cứ một giá trị bất kì nào đợc nhập vào đều chiếm 4 byte=32 bit số này đợc mã
hóa bằng dãy nhị phân 0.1
VD : float a; => mô hình cấp phát là:
Bit cao nhất => (mỗi ô 1 bit) => bit thấp nhất

Với khai báo : float a=23; thì số 23 đợc mã hóa thành dãy nhị phân:
0000 0000 0000 0000 0000 0000 0001 0111 => mô hình lu trữ là
bit cao nhất => => bit thấp nhất
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 111

Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


8


b. Với số nguyên:

Máy sẽ cấp phát 2 byte=16 bit để lu trữ .
Mô hình lu trữ =>
Bit cao nhất => =>bit thấp nhất


VD: Với khai báo: int a=23; => mô hình cấp phát là:
0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1

Tơng tự nh trên bạn có thể biểu diễn đợc với kiểu kí tự.
c. Nhận xét:

Thật đơn giản khi bạn nhập một số bất kì nào đó, thì lập tức máy xẽ tự mã hóa và
cấp phát một vùng nhớ cho biến đó. Nhng vấn đề không phải là nhập vào nh thế nào,
mà là địa chỉ của nó . Bạn phải biết đợc địa chỉ của nó thì bạn mới mong gọi đợc nó
ra. Đây quả là một vấn đề hết sức phức tạp đối với những ngời bắt đầu làm quen với
ngôn ngữ lập trình.Tôi xin đa ra hai cách lấy địa chỉ nh sau:
a
. goi theo tên biến
: Là cách gọi bằng chính cái tên của biến do bạn đặt.
b.
gọi theo địa chỉ
: Là cách gọi theo chỗ nhớ của biến tơng ứng. Cách này
rất có hiệu quả trong việc lu trữ biến nhiều phần tử, tuy nhiên bạn phải sử dụng 1 con
trỏ để lu trữ địa chỉ (Tôi xẽ giới thiệu sau) VD nh biến mảng, biến cấu trúc).Trong
Pascal đã giới thiệu rất kĩ về mảng tuy nhiên Tôi xin nhắc lại định nghĩa mảng.
Mảng là một số các phần tử phân bố kế tiếp nhau trong bộ nhớ.
VD : với khai báo int a[20]; Mảng a có 20 phần tử vì vậy
a[0] : Là phần tử đầu tiên trong mảng

a[1] : Là phần tử thứ 2 trong mảng.

a[19] : Là phần tử cuối cùng trong mảng.

2. Câu lệnh điều kiện:

C
ú pháp
: If<điều kiện>
{
công việc;
}
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


9
else {
công việc;
}
VD:
Giải phơng trình bậc nhất ax2+b=c (điều kiện a#0)với a,b,c đợc nhập từ bàn
phím.
Viết chơng trình

#include<stdio.h>

#include<conio.h>
main()
{
float a,b,c,x;
printf(nhập a,b,c=);scanf(%f%f%f,&a&b&c);
x2=(c-b)/a;
If((c-b)>0)
{
printf(phơng trình có 2 nghiệm);
printf(x1=%4.2f,sqrt(x));
printf(x2=%4.2f,-sqrt(x));
}
if((c-b)=0) printf(co 1 nghiem x=0.);
if((c-b)<0) printf(phuong trinh vo nghiem.);
getch();
}

3. Vòng lặp xác định:

Là vòng lặp cho bạn biết trớc số lần lặp là bao nhiêu. Mục đích là để lu trữ
(nhập/xuất) các phần tử mảng cho thuận tiện
Cú pháp : for(i=0;i<n;i++)
{
khối lệnh;
}
trong đó: i : Là biến chạy cho biết địa chỉ của phần tử thứ i, i++ là sau 1 vòng
lặp i sẽ tự động tăng thêm 1 đơn vị.
n : Là số phần tử của mảng.
Thanh Tùng


KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


10
VD:
Hãy nhập một mảng (10 phần tử) số nguyên bất kì tiên sau đó cho hiện ra màn
hình dãy số vừa nhập.
Chơng trình
:
#include<stdio.h>
#include<conio.h>
main()
{
int a[10],i;
for(i=0;i<10;i++)
{
printf(nhap gia tri cho mang:\ n);
printf(phan tu thu: %d \ n,i);scanf(%d,&a[i]);
} /*đến đây bạn đã có 1 mảng 10 phần tử*/
for(i=0;i<10;i++)
{
printf(hiện gia tri mang vừa nhập:\ n);
printf(phần tử thứ %d %d,i,a[i]);
}
getch();
}
Tơng tự vậy bạn có thể làm ví dụ sau:

Bài Tập : Nhập mảng 10 số thực bất kì sau đó:
- Cho hiện lên màn hình dãy số vừa nhập.
- Tính tổng của 10 số đó và cho hiện tổng tính đợc lên màn hình .
Gợi ý: Công thức tính tổng s=s+a[i] ;

4.
Vòng lặp không xác định
:
Có 2 vòng cơ bản :
a. Vòng lặp while.do :
Cú pháp : while (điều kiện)
{
khối lệnh;
}
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


11
Giải thích : Vòng lặp trên có ý nghĩa là:
Trong khi (while) (điều kiện (còn đúng))
{
thì còn làm các công việc;
}

VD:

Tìm giá trị của n để có đợc giai thừa lớn hơn 120.
Chơng trình
:
#include<stdio.h>
#include<conio.h>
main()
{
int n,gt;
gt=1;
n=0;
while(gt<120)
{
n=n+1;
gt=gt*n;
}
printf(gia tri n can tim la n= : %d,n);
printf(giai thua tai n la:%d),gt;
getch();
}
Nhận xét :
Khác với vòng lặp for bởi vì nó không biết nó phải lặp bao nhiêu lần. Nếu không có
điều kiện(còn đúng) thì nó xẽ lặp mãi không dừng. Nhng vấn đề không phải ở đó. Bạn
nên hiểu rằng khi ngời ta đa ra một vòng lặp thì chắc chắn nó sẽ có những công dụng
khác nhau, giải quyết loại bài toán khác nhau.Tôi lấy ví dụ đơn giản bạn có thể dùng
vòng for để nhập dữ liệu cho mảng, ngợc lại trong 1 phép tính nào đó VD :y=x/5 điều
kiện là hãy nhập vào giá trị của x để có đợc y<0.0004 và in giá trị của x tơng ứng với
loại bài toán này thì vòng for tỏ ra không có hiệu quả.

Thanh Tùng


KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


12
Tóm lại:
Để phân biệt đợc sự khác nhau giữa các vòng lặp là vô cùng khó khăn. Thực
ra mà nói thì giữa chúng gần nh không có danh giới, mà chỉ tỏ ra u việt hơn trong
từng loại bài toán mà thôi. Vì vậy bạn cần nắm vững và phân biệt các loại bài toán để
áp dụng nó một cách chính xác.
Bạn có thể xem các vòng lặp nh là những công cụ làm việc, còn dữ liệu là
nguyên liệu. Tôi lấy ví dụ nh có bao giờ bạn dùng dao để trặt đá không trong khi đó
bạn có búa, tuy nhiên bạn cố tình thì vẫn có thể làm đợc.
b. Vòng lặp dowhile:
Cú pháp: do
{
công việc;
}
while <điều kiện>;
Vòng lặp này chỉ khác vòng lặp trên ở chỗ while đợc đặt ở cuối câu còn nội dung
thì giống nhau.
Ghi chú:
Đối với 2 vòng lặp b, c bạn cần kết hợp thêm câu lệnh sau thì rất có hiệu quả.
(tham khảo trong sách).
- break ; mục đích để thoát khỏi vòng lặp không cần đến điều kiện.
- Continue; Khi gặp lệnh này nó xẽ bỏ công việc đang thực hiện và quay
lại thực hiện công việc tiếp theo.
Chú ý:

Bạn phải hết sức quan tâm đến phần này, vì nó là công cụ duy nhất để giải quyết
bài toán. Nếu nh không hiểu phần này coi nh bạn chẳng biết gì cả. Cách tốt nhất bạn
nên làm nhiều bài tập để hiểu cặn kẽ vấn đề.

VI. Con trỏ và hàm:

1.
Con trỏ:

Con trỏ rất có lợi trong mọi ngôn ngữ vì nó rất tiện lợi sử dụng trong việc lu trữ
địa chỉ. Có những việc nếu nh không có con trỏ bạn không thể thực hiện đợc công
việc nh ý muốn. Ví dụ việc lấy kết quả từ một chơng trình con sang chơng trình
chính, nếu không sử dụng con trỏ bạn không thể lấy kết quả ra khỏi chơng trình đó
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


13
đợc. Tuy nhiên việc sử dụng con trỏ làm cho chúng ta cảm thấy rất phức tạp.Thực ra
nó cũng đơn giản thôi bạn thấy gì sự khác nhau giữa hai chơng trình sau:
Chơng trình 1
:
<không có con trỏ>
#include<stdio.h>
#include<conio.h>
main()

{
int a=34;
printf(gia tri của a la a= : %d,a);
getch();
}
kết quả in a=34;

Chơng trình 2
:
< có con trỏ>
#include<stdio.h>
#include<conio.h>
main()
{
int a=34,*p;
*p=a;
printf(gia tri của a la a= : %d,p);
getch();
}
kết quả in a=844;
Vì sao vậy bởi vì con trỏ chỉ lu địa chỉ của biến a chứ nó không lu giá trị của biến
a. Mà địa chỉ trong bộ nhớ thì đơng nhiên không phải là giá trị của biến nào đó. Đến
đây Tôi tin chắc bạn đã hình dung ra rồi trứ, nếu cha Tôi xin đợc lấy một ví dụ vui
thế này:Bạn của bạn nhờ bạn cất giữ hộ một cái va li đơng nhiên bạn không thể mở nó
ra đợc, chiếc va li đó chẳng may bị mất, khi trình báo với công an thì bạn chỉ có thể
trình bày là chiếc va li để chỗ nào thôi chứ không biết đợc trong đó có gì, còn bạn của
bạn lại biết bên trong có gì nhng không biết nó nằm chỗ nào.
Tức là gì:
Thanh Tùng


KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


14
Con trỏ chỉ lu trữ địa chỉ chứ không lu trữ giá trị của biến đó,đơng nhiên
giá trị phải nằm trong địa chỉ
Hi vọng bạn không còn nhầm lẫn nữa. Và sau đây Tôi xẽ cho các bạn thấy sự tác
dụng của con trỏ và việc sử dụng nó. Tôi xẽ nói tiếp về con trỏ sau, vì nó gắn liền với
việc sử dụng hàm.
2.Hàm và chơng trình:

Bạn có phân biệt đợc hai từ này không còn theo Tôi thì:
+ Hàm là 1 phần chơng trình lớn, gồm có các hàm sau:
2.1. Hàm void() : Là hàm không chả lại kết quả trong tên hàm khi chơng
trình chính gọi đến nó.
VD: Có hàm void tim(int n); Khi đó trong chơng trình chính đa ra lời gọi hàm
là printf(kết quả tìm là%d,tim(n)); thì chắc trắn bạn không có đợc kết quả đúng.

2.2. Hàm main() : Hàm này bắt buộc cho mọi chơng trình(còn gọi là hàm
chính).

2.3. Hàm có kiểu : Trong đó có thể là các kiểu nguyên, thực,char.
VD: int gt(int n); hoặc hàm float tbc(float a,float b);
Loại hàm này sau khi thực hiện bạn đa ra câu lệnh sau
return(biến tổng); thì tự khắc kết quả đợc tự động chứa vào tên hàm là
tbc , khi đó ở chơng trình chính bạn gọi tới nó thì nó sẽ cho kết quả mà nó nhận
đợc.


2.4. Hàm tự định nghĩa:
(Tôi xin giới thiệu hàm này trong phần dữ liệu có cấu trúc vì phần này cha cần sử
dụng đến).

+ Chơng trình :
Là một dãy các hàm kết hợp lại với nhau trong đó có hàm chính đợc định nghĩa
là hàm main().
3.
Sử dụng hàm
:
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


15
Từ đầu đến giờ cứ mỗi một ví dụ đều phải sử dụng hàm đó là hàm main().
Nhng trong phần này Tôi muốn trình bày cách kết hợp nhiều hàm trong 1 chơng
trình, kết hợp với việc sử dụng con trỏ nh thế nào.
a.Kết hợp hàm main và hàm có kiểu:
Tôi sẽ xây dựng 1 chơng trình có 2 hàm trong đó hàm main sẽ gọi đến hàm void
VD (bt 4,trang 133,chơng 5,sách của ông ất):
Viết chơng trình tính
sinx=x-x
3
/3!+x

5
/5!- ..+(-1)
n
x
2n+1
/(2*n+1)!

Với độ chính xác là 0.0001.
Gơị ý:
Ta thấy x luôn tỷ lệ với n, tức n tăng thì mũ của x cũng tăng theo, khi n tăng thêm 1
đơn vị thì ta lại có đợc 1 thơng mới, nếu n lẻ thì thơng này mang dấu trừ và ngợc
lại. Độ chính xác 0.0001 tức là khi có một thơng mới, nếu thơng này <0.0001 tức là
điều kiện đợc thỏa mãn
Đầu vào : Nhập x bất kì.
n: Là biến chạy nhằm thỏa mãn độ chính xác.
Đầu ra : Giá trị của sinx ;
Tôi sử dụng 2 hàm:
- Hàm int gt(int n); để tính giai thừa n kiểu hàm là nguyên tên hàm là gt ,đối
n kiểu nguyên.
- Hàm main() là hàm chính làm nhiệm vụ nhập x và gọi tới hàm gt để lấy kết
quả tính toàn và cuối cùng là in giá trị của sinx
Để viết đợc chơng trình này bạn phải hình dung đợc là:
- Mẫu số là biểu thức tính giai thừa. Vì vậy để đơn giản bài toán ta xây dựng
1 hàm tính giai thừa là mẫu số, khi n tăng tự nó xẽ đa ra lời gọi giai thừa.
- Tử số tuy nó phức tạp nhng rất may trong c đã có hàm pow(y,x) y
x
để
tính x
n
và (-1)

n
tức là (-1)
n
<=> pow(-1,n);và x
n
<=>pow(x,n) ;
- Chơng trình sử dụng 1 biến kt để chứa giá trị thơng nhận đợc, đồng thời
nó cũng là điều kiện để vòng lặp kết thúc. Nếu kt>0.0001.biến sinx để chứa kết quả
nhận đợc.
Sau đây là chơng trình
:
#include<stdio.h>
#include<conio.h>
#include<math.h>
int gt(int n);
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


16
/*bắt đầu hàm gt*/
int gt(int n)
{
int i,tg;
tg=1;
for(i=1;i<=2*n+1; )

{
i=i+2;
tg=tg*i;
}
return tg; /*là câu lệnh chứa kết quả của tg vào tên hàm chú ý nếu là con trỏ thì
phảI là return (&tg)*/
}
/*bắt đầu hàm chính*/
main()
{
clrscr();
int n;
float x,sinx,dk;
printf("\n nhap gia tri cua x= ");scanf("%f",&x);
n=1;
do
{
dk=(pow(-1,n)* pow(x,n)) /gt(n); /*đây là lời gọi tới hàm gt*/
sinx=sinx+dk;
n=n+1;
}
while (abs(dk)<0.0001); /*abs là lấy giá trị tuyệt đối*/
printf("\n gia tri cua sinx =%4.8f",sinx);
printf("\n n=%d",n);
getch();
}
Thanh Tùng

KS 20
_

CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


17
Nếu cũng với bài toán này Tôi khai báo là: int *gt(int n);tức là sử dụng con trỏ
thì điều gì xẽ xảy ra: Bạn hãy tự chạy chơng trình này thì bạn xẽ hiểu những gì Tôi nói
trong phần con trỏ.
Sau đây là chơng trình
:
#include<stdio.h>
#include<conio.h>
#include<math.h>
int *gt(int n);
/*bắt đầu hàm gt*/
int *gt(int n)
{
int i,tg;
tg=1;
for(i=1;i<=2*n+1; )
{
i=i+2;
tg=tg*i;
}
return (&tg);
}
/*bắt đầu hàm chính*/
main()
{
clrscr();

int n;
float x,sinx,dk;
printf("\n nhap gia tri cua x= ");scanf("%f",&x);
n=1;
do
{
dk=(pow(-1,n)* pow(x,n)) /gt(n);/*đây là lời gọi tới hàm gt*/
sinx=sinx+dk;
n=n+1;
}
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


18
while (abs(dk)<0.0001); /*abs là lấy giá trị tuyệt đối*/
printf("\n gia tri cua sinx =%4.8f",sinx);
printf("\n n=%d",n);
getch();
}
Chú ý:
Bạn có biết tại sao trong hàm gt Tôi lại sử dụng biến tg, mà lại không sử dụng trực
tiếp biến gt không. Bởi vì không nên sử dụng lời gọi hàm lớn hơn 1 lần trong chơng
trình.
Tơng tự vậy bạn hãy làm bài tập sau:
Tính giá trị của e

x
=1+x/1!+x
2
/2!+.+x
n
/n!;

b. Hàm main và hàm void:
- Nh ta đã biết hàm void không trả lại kết quả cho tên hàm vì vậy muốn lấy kết
quả ra khỏi chơng trình thì bắt buộc bạn phải dùng đến con trỏ.
- Tôi lại xin nhắc lại cho nhớ hai câu mà bạn không đợc pháp quên đó là:
1. Con trỏ chỉ lu địa chỉ của biến chứ không lu giá trị.
2. Khi nào cần lấy giá trị của biến ra khỏi chơng trình thì bắt buộc phải sử
dụng con trỏ.
Vì sao Tôi nhắc lại điều này vì từ bây giờ trở đi con trỏ là công cụ đắc lực khi giải
quyết bài toán. Việc sử dụng hàm bạn đã quá quen thuộc vì vậy sau đây Tôi muốn bạn
hiểu thông qua ví dụ sau:
VD: Viết chơng trình hoán vị hai số a,b cho nhau sủ sụng 2 hàm:
- Hàm void vh(float *p1,float *p2) để hoán vị 2 số cho nhau.
- Hàm main() để nhập dữ liệu và in kết quả hoán vị.
Chơng trình
:
#include<stdio.h>
#include<conio.h>
void hv(float *p1,float *p2); /*khai báo nguyên mẫu*/
void hv(float *p1, float *p2); /*bắt đầu hàm void*/
{
float tg;
tg=*p1; *p1=*p2; *p2=tg;
}

Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


19
main()
{
float a,b;
printf("\n nhap gia tri cua a= ");scanf("%f",&a);
printf("\n nhap gia tri cua b= ");scanf("%f",&b);
vh(&a,&b);
printf("\n nhap gia tri cua a= %4.2f",a);
printf("\n nhap gia tri cua b= %4.2f",b);
getch();
}
nhập a=2.4;b=3.0;
kết quả chạy: a=3.00;b=2.40;
Để tỏ rõ uy lực của con trỏ bạn thử bỏ * ở p1 và p2 mà xem.

4.
Các lỗi thờng gặp trong khi sử dụng con trỏ:

Đa ra phần này Tôi, bản thân cảm thấy rất xấu hổ bởi vì vốn tiếng anh của Tôi vô
cùng khiêm tốn. Có gì mong bỏ quá cho.
+ Máy báo : inconpatible type conversion : lỗi này là do lời gọi hàm sai lẽ ra là tên
hàm (&biến) bạn chỉ viết tênhàm(biến)

+ Máy báo : illegal use of floating point :bạn đã viết thiếu dấu * trong 1 biểu thức
nào đó vì đây là con trỏ.
+ Máy báo : cannot covert int to int :thiếu dấu & trong return(tênhàm)
+ Máy báo : too few parameters in callto :đối trong lời gọi hàm không tơng thích
với trong hàm.
+ Máy báo : linler error undefined symbol .:sai đờng dẫn giữa lời gọi hàm và
hàm.
Ngoài ra còn rất nhiều lỗi khác nữa mong tự tìm hiểu.Đặc biệt có 1 lỗi mà chơng
trình không báo lỗi, nhng chơng trình cho kết quả sai, thì đó là do thuật toán của bạn
sai hoặc là bạn sử dụng con trỏ không đúng, tức là bàn vẫn cha hiểu gì về con trỏ .

VII. Mảng và con trỏ
:
Mảng là một số các phần tử có cùng kiểu dữ liệu đợc lu trữ kế tiếp nhau trong
bộ nhớ.
Việc truy nhập vào mảng bắt buộc phải thông qua chỉ số của mảng.
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


20
Chú ý:
Trong C quy định chỉ số của 1 mảng bắt đầu từ 0. Và bạn đừng nghĩ mảng và biến
là một (hi vọng Tôi nhắc điều này là không thừa).Nếu bạn lấy chỉ số là 1 thì khi truy
nhập mảng xẽ truy nhập ra ngoài vùng nhớ của mảng=>kết quả sai.
VD : for(i=1;i<n;i++) là sai tuy nhiên máy không báo lỗi.

Còn for(i=0;i<n;i++) là đúng;
Trong ngôn ngữ C có 2 loại mảng đó là mảng tĩnh và mảng động :
1. Mảng tĩnh
:
Là mảng cho ta biết trớc số phần tử là bao nhiêu.
VD: int a[10]; với khai báo này bạn đã có một mảng số nguyên có10 phần tử do chính
bạn sẽ nhập vào trong chơng trình bằng câu lệnh:
for(i=0;i<10;i++)
{
printf(nhập mảng a[%d]=,i);scanf(%d,&a[i]);
}
Khi đó máy sẽ lu trong bộ nhớ nh sau:(giả thiết đây là 1 khoảng trong bộ nhớ).
a[0] chiếm 8bit(=8 ô)=>..vùng nhó liên tiếp. =>a[9] chiếm 8bit.

Công việc về mảng thờng có một số công việc sau:
- Nhập mảng.
- Sắp xếp mảng.
- Tìm phần tử mảng.
- Bổ sung phần tử cho mảng.
- Loại phần tử mảng.
- In mảng.
VD:
Lập một chơng trình sử dụng 2 hàm . Hàm void làm nhiệm vụ sắp xếp mảng.
Hàm main làm nhiệm vụ nhập mảng và hiển thị mảng.
Nhận xét:
Trong hàm void làm nhiệm vụ sắp xếp. Sau khi sắp xếp nó xẽ trả kết quả lại cho
hàm main.Vì vậy để lấy đợc kết quả này bắt buộc phải sử dụng con trỏ:
Chơng trình
:
#include<stdio.h>

#include<conio.h>
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


21
#include<alloc.h>
void sxep(float *p);
float a[5];
void sxep(float *p)
{
int i,j;
float tg;
for(i=0;i<5;i++)
for(j=i+1;j<=5;j++)
if(p[i]>p[j])
{
tg=p[i];
p[i]=p[j];
p[j]=tg;
}
}
main()
{
int i;
clrscr();

for(i=0;i<=5;i++)
{
printf("\n nhap phan tu thu: %d \n",i);scanf("%f",&a[i]);
}
else*/ printf("\n ket qua sap xep:\n");
sxep(a);
for(i=0;i<5;i++)
printf("\n a[i]=%4.2f",a[i]);
getch();
}

Sau khi chạy chơng trình này bạn :
1.Thử bỏ * trong p xem điều gì xẽ sảy ra.
2.Trong lời gọi hàm bạn viết sxep(&a[i])
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


22
3.Thử viết for(i=0;I<=5;i++) hoặc for(i=1;i<5;i++)
4. Thay lời gọi trên bằng for(i=0;i<5;i++)
sxep(&a[i])đối chiếu với lời gọi trên và cho nhận
xét. (Đây là hai cách gọi hàm đều đúng mà Tôi phải tìm hiểu mãi mới nhận ra đợc
quy luật của nó bạn phản thử mới nhớ đợc).
Chú ý
:

Bạn phải thử mới biết cái thú vị của nó.Nếu bạn không thử trong những hớng dẫn
này, đến 1 lúc nào đó bạn làm chơng trình nó không báo lỗi, mà lại cho kết quả sai,
khi đó bạn xẽ tức điên lên cho mà xem.
2. Khai báo động: (mảng động)

Cú pháp: a=(kiểu dữ liệu*)malloc(n*sizeof(a));
Trong đó: a : Là mảng phần tử(a phảI là con trỏ mảng).
n : Là chỉ số lớn nhất của mảng.
+ Kiểu dữ liệu: Là kiểu dữ liệu của mảng.
Thực ra phần này tơng tự với phần trên nó chỉ khác ở hai điểm sau:
- Tên mảng phải là con trỏ, số lợng phần tử (n) phải nhập vào.
- Không biết trớc số lợng phần tử. Đây là lý do của việc phải sử dụng con
trỏ,và vì n nhập từ bàn phím chứ không ấn định cho nên tiết kiệm đợc bộ nhớ.
- Trớc khi sử dụng khai báo động phải khai báo th viện là:
#include<stdio.h>
Do vậy Tôi mong các bạn hiểu phần này thông qua ví dụ sau:
VD:
Viết CT nhập n phần tử từ bàn phím. CT sử dụng hai hàm:
1.Hàm float tbc(float p[],int n);để tính trung bình cộng của mảng
2.Hàm main() để nhập dữ liệu và in kết quả.
Chơng trình
:
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
float tbc(float p[],int n);
float tbc(float p[],int n)
{
int i,d=0;
float s;

Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


23

for(i=0;i<n;i++)
{
s=s+p[i];
d=d+1;
}
return(s/d);
}
main()
{
int i,n;
float *a;
clrscr();
printf("\n nhap so phan tu cua mang n=:");scanf("%d",&n);
a=(float*)malloc(n*sizeof(float));
for(i=0;i<n;i++)
{
printf("\n nhap phan tu thu: %d \n",i);scanf("%f",&a[i]);
}
tbc(a,n);
printf("\n trung binh cong la %8.2f",tbc(a,n));


getch();
}

Nhận xét:
Bạn có thấy điều gì khác biệt trong phần này không . Trong phần con trỏ Tôi
nói: Con trỏ chỉ lu giữ địa chỉ chứ không lu kết quả. Còn trong phần này thì nó lại
lu kết quả, lúc in ra vần hoàn toàn đúng: Tôi xin lấy tiếp ví dụ vui trong phần con trỏ
nh sau:Lần trớc là chiếc va li của ngời bạn nhờ bạn cất giữ hộ. Còn bây giờ chiếc
va li ấy là của bạn thì đơng nhiên bạn phải biết trong đó có gì, và nó đợc cất ở đâu.
Có nghĩa là: Khi bạn nhập giá trị cho 1 biến a nào đó, bạn gán *(p)=a (tức là cất
hộ),còn bạn nhập trực tiếp *p[i]=?(nh ví dụ trên đã chứng minh) Thì thử hỏi hai điều
này có khác nhau không.
Thanh Tùng

KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C


24
Phần 2. cấu trúc
I. Cách lu trữ của máy tính:
Phần này Tôi cứ loay hoay từ đầu CT đến giờ xem giới thiệu vào chỗ nào là hợp lý
nhất, bạn biết vì sao không: Vì nó cực kì quan trọng, vì Tôi sợ bạn quên mất. Nếu bạn
quên thì bạn mất đi cơ hội biết đợc máy tính làm gì, và làm nh thế nào, khi bạn tác
động vào nó. Nếu không hiểu đơng nhiên những việc bạn làm chỉ là mò mẫm mà thôi.
Bạn chú ý câu nói này: Trong ngôn ngữ C quy định lu trữ trong máy tính
bằng 2 dạng đó là: Lu trữ kế tiếp và lu trữ móc nối đối với dữ liệu có cấu trúc.

Mô hình lu trữ :
1.
Dạng kế tiếp
:
Ví dụ có khai báo trong phần II(xem ở dới). Đầu chơng trình bạn: Viết khai báo
1 biến cấu trúc tên là danh sách và 1 mảng cấu trúc tên là ds[10] .
a. Với biến cấu trúc tên là danh sách:
=>giả thiết các ô nhớ có thứ tự từ trái qua phải và từ trên xuống.
ô 1 2 3 ..

.. .. 150 ô 160

- 8 ô cho 1 kí tự=>mảng char họtên[20] cần 160 kí tự => lu trữ xong trờng
họtên[20].
- Tơng tự tiếp theo cần 160 kí tự cho trờng quêquán[20]=>bắt đầu từ ô
161=>hết ô 320.
ô 161 162 .. ..

.. .. 319 320

- Tiếp theo đến trờng ngày sinh có kiểu là int => cần 2 byte để lu trữ=>bắt
đầu từ ô 321=>hết ô thứ 336.
321 ô 336

Hết 1 biến cấu trúc.
b. Với mảng cấu trúc.

×