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 C1
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 !
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
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
_
+
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
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).
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*/
}
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 C8
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 C9
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>
KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C10
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:
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
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 C13
đợ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()
KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C14
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.
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)
{
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
_
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 C18
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
Thanh Tùng
KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C19
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)
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>
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 C22
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ú ý
:
Thanh Tùng
KS 20
_
CNTT - ĐHBKHN
Tóm tắt ngôn ngữ lập trình C23
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));
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.