M¶ng cã thÓ ®îc hiÓu lµ mét tËp hîp nhiÒu phÇn tö cã cïng mét kiÓu gi¸ trÞ vµ chung mét tªn.. Cã bao nhiªu kiÓu biÕn th× cã bÊy nhiªu kiÓu m¶ng.[r]
(1)Giíi thiƯu
Tin học ngành khoa học mũi nhọn phát triển nhanh chóng vài chục năm lại ngày mở rộng lĩnh vực nghiên cứu, ứng dụng mặt đời sống xã hội.
Ngôn ngữ lập trình loại cơng cụ giúp người thể h iện vấn đề thực tế lên máy tính cách hữu hiệu Với phát triển tin học, ngơn ngữ lập trình dần tiến hoá để đáp ứng thách thức thực tế.
Khoảng cuối năm 1960 đầu 1970 xuất nhu cầu cần có ngơn ngữ bậc cao để hỗ trợ cho nhà tin học việc xây dựng phần mềm hệ thống, hệ điều hành Ngơn ngữ C đời từ đó, phát triển phịng thí nghiệm Bell Đến năm 1978, giáo trình " Ngơn ngữ lập trình C " tác giả ngơn ngữ Denni sh Ritchie và B.W Kernighan viết, xuất phổ biến rộng rãi.
C ngôn ngữ lập trình vạn Ngồi việc C dùng để viết hệ điều hành UNIX, người ta nhanh chóng nhận sức mạnh C việc xử lý cho vấn đề đại tin học C không gắn với hệ điều hành hay máy nào, gọi " ngơn ngữ lập trình hệ thống" dùng cho việc viết hệ điều hành, tiện lợi cho cả việc viết chương trình xử lý số, xử lý văn sở liệu.
Vµ tìm hiểu giới ngôn ngữ C từ khái niệm ban đầu cơ nhất.
(2)Chng 1
các khái niệm 1.1 Tập ký tự dùng ngôn ngữ C :
Mi ngụn ng lp trỡnh xây dựng từ ký tự Các ký tự nhóm lại theo nhiều cách khác để tạo nên từ Các từ lại liên kết với theo qui tắc để tạo nên câu lệnh Một chương trình bao gồm nhiều câu lệnh thể thuật tốn để giải tốn Ngơn ngữ C xây dựng ký tự sau :
26 chữ hoa : A B C Z 26 chữ thường : a b c z 10 chữ số :
C¸c ký hiƯu to¸n häc : + - * / = ( ) Ký tự gạch nối : _
Các ký tù kh¸c : , : ; [ ] {} ! \ & % # $
Dấu cách (space) dùng để tách từ Ví dụ chữ VIET NAM có ký tự, cịn VIETNAM có ký tự
Chó ý :
Khi viết chương trình, ta khơng sử dụng ký tự khác ngồi ký tự Ví dụ lập chương trình giải phương trình bậc hai ax2+bx+c=0 , ta cần tính biệt thức Delta = b2- 4ac, ngôn ngữ C không cho phép dùng ký tự , ta phải dùng ký hiệu khác để thay
1.2 Tõ kho¸ :
Từ khố từ sử dụng để khai báo kiểu liệu, để viết toán tử câu lệnh Bảng liệt kê từ khoá TURBO C :
asm break case cdecl
char const continue default
do double else enum
extern far float for
goto huge if int
interrupt long near pascal
(3)sizeof static struct switch
tipedef union unsigned void
volatile while
ý nghĩa cách sử dụng từ khoá đề cập sau này, đâ y ta cần ý : - Không dùng từ khoá để đặt tên cho hằng, biến, mảng, hàm
- Từ khoá phải viết chữ thường, ví dụ : viết từ khố khai báo kiểu nguyên int INT
1.3 Tªn :
Tên khái niệm quan trọng , dùng để xác định đại lượng khác chương trình Chúng ta có tên hằng, tên biến, tên mảng, tên hàm, tên trỏ, tên tệp, tên cấu trúc, tên nhãn,
Tên đặt theo qui tắc sau :
Tên dãy ký tự bao gồm chữ cái, số gạc h nối Ký tự tên phải chữ gạch nối Tên không trùng với khoá Độ dài cực đại tên theo mặc định 32 đặt lại giá trị từ tới 32 nhờ chức : Option -Compiler-Source-Identifier length dùng TURBO C
VÝ dô :
Các tên :
a_1 delta x1 _step GAMA Các tên sai :
3MN Ký tự số m#2 Sử dơng ký tù # f(x) Sư dơng c¸c dÊu ( ) Trïng víi tõ kho¸ te ta Sư dơng dÊu tr¾ng
Y-3 Sư dơng dÊu
-Chó ý :
(4)1.4 KiĨu d÷ liƯu :
Trong C sử dụng các kiểu liệu sau : 1.4.1 KiÓu ký tù (char) :
Mét giá trị kiểu char chiếm byte ( bit ) biểu diễn ký tự thông qua b¶ng m· ASCII VÝ dơ :
Ký tù M· ASCII
0 048
1 049
2 050
A 065
B 066
a 097
b 098
Cã hai kiĨu d÷ liƯu char : kiểu signed char unsigned char
Kiểu Phạm vi biĨu diƠn Sè ký tù KÝch
thước Char ( Signed char ) -128 đến 127 256 byte
Unsigned char đến 255 256 byte
Ví dụ sau minh hoạ khác hai kiểu liệu : Xét đoạn chương trình sau : char ch1;
unsigned char ch2;
ch1=200; ch2=200; Khi thực chất :
ch1=-56; ch2=200;
Nhưng ch1 ch2 biểu diễn ký tự có mã 200 Phân loại ký tự :
(5)Nhóm 1: Nhóm ký tự điều khiển có mã từ đến 31 Chẳng hạn ký tự mã 13 dùng để chuyển trỏ đầu dòng, ký tự 10 chuyển trỏ xuống dòng ( cột ) Các ký tự nhóm nói chung khơng hiển thị hình
Nhóm : Nhóm ký tự văn có mã từ 32 đến 126 Các ký tự đưa hình máy in
Nhóm : Nhóm ký tự đồ hoạ có mã số từ 127 đến 255 Các ký tự đưa hình khơng in ( lệ nh DOS )
1.4.2 KiĨu nguyªn :
Trong C cho phép sử dụng số nguyên kiểu int, số nguyên dài kiểu long số ngun khơng dấu kiểu unsigned Kích cỡ phạm vi biểu diễn chúng bảng :
Kiểu Phạm vi biểu diễn Kích thước
int -32768 đến 32767 byte
unsigned int đến 65535 byte long -2147483648 đến 2147483647 byte unsigned long đến 4294967295 byte Chú ý :
Kiểu ký tự xem dạng kiểu nguyên 1.4.3 Kiểu dấu phảy động :
Trong C cho phép sử dụng ba loại liệu dấu phảy động, float, double long double Kích cỡ phạm vi biểu diễn chúng bảng :
KiĨu Ph¹m vi biĨu diƠn Sè ch÷ sè
cã nghÜa
Kích thước
Float 3.4E-38 đến 3.4E+38 đến byte
Double 1.7E-308 đến 1.7E+308 15 đến 16 byte long double 3.4E-4932 đến 1.1E4932 17 đến 18 10 byte Giải thích :
(6)1.5 Định nghĩa kiểu TYPEDEF : 1.5.1 C«ng dơng :
Từ khố typedef dùng để đặt tên cho kiểu liệu Tên kiểu dùng để khai báo liệu sau Nên chọn tên kiểu ngắn gọn để dễ nhớ Chỉ cần thêm từ khoá typedef vào trước khai báo ta nhận tên kiểu liệu dùng tên để khai báo biến, mảng, cấu trúc, vv
1.5.2 C¸ch viÕt :
Viết từ khố typedef, sau kiểu liệu ( kiểu ), đến tên kiểu Ví dụ câu lệnh :
typedef int nguyen;
sẽ đặt tên kiểu int nguyen Sau ta dùng kiểu nguyen để khai báo biến, mảng int ví dụ sau ;
nguyen x,y,a[10],b[20][30]; Tương tự cho câu lệnh :
typedef float mt50[50];
Đặt tên kiểu mảng thực chiều có 50 phần tử tên mt50 typedef int m_20_30[20][30];
Đặt tên kiểu mảng thực hai chiều có 20x30 phần tử tên m_20_3 Sau ta dùng kiểu khai b¸o :
mt50 a,b; m_20_30 x,y; 1.6 H»ng :
Hằng đại lượng mà giá trị khơng thay đổi q trình tính tốn 1.6.1 Tên :
Nguyên tắc đặt tên ta xem xét mục 1.3 Để đặt tên hằng, ta dùng dịng lệnh sau :
#define tªn giá trị Ví dụ :
(7)Lúc này, tất tên MAX chương trình xuất sau thay 1000 Vì vậy, ta thường gọi MAX tên hằng, biểu diễn số 1000
Mét vÝ dơ kh¸c :
#define pi 3.141593
Đặt tên cho float pi có giá trị 3.141593 1.6.2 Các loại h»ng :
1.6.2.1 H»ng int :
Hằng int số nguyên có giá trị khoảng từ -32768 n 32767 Vớ d :
#define number1 -50 Định nghià int number1 có giá trị -50 #define sodem 2732 Định nghià int sodem có giá trị 2732 Chú ý :
Cần phân biệt hai 5056 5056.0 : 5056 số nguyên 5056.0 thực
1.6.2.2 Hằng long :
Hằng long số nguyên có g iá trị khoảng từ -2147483648 đến 2147483647 Hằng long vit theo cỏch :
1234L 1234l ( thêm L l vào đuôi )
Mt s nguyờn vượt miền xác định int xem long Ví dụ :
#define sl 8865056L Định nghià long sl có giá trị 8865056 #define sl 8865056 Định nghià long sl có giá trị 8865056 1.6.2.3 Hằng int hệ :
(8)VÝ dô :
#define h8 0345 Định nghià int hệ có giá trị 3*8*8+4*8+5=229
1.6.2.4 H»ng int hÖ 16 :
Trong hƯ nµy ta sư dơng 16 ký tù : 0,1 ,9,A,B,C,D,E,F Cách viết Giá trị
a A 10
b hc B 11
c hc C 12
d hc D 13
e hc E 14
f hc F 15
H»ng sè hƯ 16 có dạng 0xc1c2c3 hặc 0Xc1c2c3 ởđây ci mét sè hƯ 16 VÝ dơ :
#define h16 0xa5 #define h16 0xA5 #define h16 0Xa5 #define h16 0XA5
Cho ta hắng số h16 hệ 16 có giá trị Giá trị chúng hƯ 10 lµ : 10*16+5=165
1.6.2.5 H»ng ký tù :
Hằng ký tự ký tự riêng biệt viết hai dấu nháy đơn, ví d 'a'
Giá trị 'a' mà ASCII chữ a Như giá trị 'a' lµ 97 H»ng ký tù c ã thĨ tham gia vào phép toán số nguyên khác Ví dô :
'9'-'0'=57-48=9 VÝ dô :
(9)' \c1c2c3'
trong c1c2c3 số hệ mà giá trị mã ASCII ký tự cần biểu diễn
Ví dụ : chữ a có mã hệ 10 97, đổi hệ 0141 Vậy ký tự 'a' viết dạng '\141' Đối với vài ký tự đặc biệt ta cần sử dụng cách viết sau ( thêm dấu \ ) :
C¸ch viÕt Ký tù
'\'' '
'\"' "
'\\' \
'\n' \n (chun dßng )
'\0' \0 ( null )
'\t' Tab
'\b' Backspace
'\r' CR ( đầu dòng ) '\f' LF ( sang trang ) Chó ý :
Cần phân biệt ký tự '0' ' \0' Hằng '0' ứng với chữ số có mã ASCII 48, '\0' ứng với kýtự \0 ( thường gọi ký tự null ) có mã ASCII
Hằng ký tự thực số ngun, dùng số nguyên hệ 10 để biể u diễn ký tự, ví dụ lệnh printf("%c%c",65,66) in AB
1.6.2.5 H»ng x©u ký tù :
Hằng xâu ký tự dãy ký tự đặt hai dấu nháy kép Ví dụ :
#define xau1 "Ha noi"
#define xau2 "My name is Giang"
Xâu ký tự lưu trữ máy dạng bảng có phần tử ký tự riêng biệt Trình biên dịch tự động thêm ký tự null \0 vào cuối xâu ( ký tự \0 xem dấu hiệu kết thúc xõu ký t )
(10)Cần phân biƯt hai h»ng 'a' vµ "a" 'a' lµ h»ng ký tự l ưu trữ byte, "a" xâu ký tự lưu trữ mảng hai phần tử : phần tử thứ chứa chữ a phần tử thứ hai chứa \0
1.7 BiÕn :
Mỗi biến cần phải khai báo trước đưa vào sử dụng Việc khai báo biến thực theo mẫu sau :
KiÓu liệu biến tên biến ; Ví dụ :
int a,b,c; Khai báo ba biến int a,b,c long dai,mn; Khai báo hai biến long dai mn char kt1,kt2; Khai báo hai biến ký tự kt1 kt2 float x,y Khai báo hai biến float lµ x vµ y
double canh1, canh2; Khai báo hai biến double canh1 canh2 Biến kiểu int nhận giá trị kiểu int Các biến khác có ý nghĩa tương tự Các biến kiểu char chứa ký tự Để lưu trữ xâu ký tự cần sử dụng mảng kiu char
Vị trí khai báo biến :
Các khai báo cần phải đặt sau dấu { thân hàm cần đứng trước câu lệnh khác Sau ví dụ khai báo biến sai :
( Khái niệm hàm cấu trúc chương trình nghiên cứu sau này) main()
{
int a,b,c; a=2;
int d; /* Vị trí khai báo sai */
}
(11)Nếu khai báo sau tên biến ta đặt dấu = giá trị cách vừa khai báo vừa khởi đầu cho biến
VÝ dô :
int a,b=20,c,d=40;
float e=-55.2,x=27.23,y,z,t=18.98;
Việc khởi đầu việc khai báo biến gán giá trị cho sau hồn tồn tương đương Lấy địa biến :
Mỗi biến cấp phát vùng nhớ gồm số byte liên tiếp Số hiệu byte đầu địa biến Địa biến sử dụng số hàm ta nghiên cứu sau ( ví dụ hàm scanf )
Để lấy địa biến ta sử dụng phép toán : & tên biến 1.8 Mảng :
Mỗi biến biểu diễn giá trị Để biểu diễn dãy số hay bảng số ta dùng nhiều biến cách khơng thuận lợi Trong trường hợp ta có khái niệm mảng Khái niệm mảng ngôn ngữ C giống khái niệm ma trận đại số tuyến tính
Mảng hiểu tập hợp nhiều phần tử có kiểu giá trị chung tên Mỗi phần tử mảng biểu diễn giá trị Có kiểu biến có nhiêu kiểu mảng Mảng cần khai bỏo nh rừ :
Loại mảng : int, float, double Tên mảng
S chiu v kớch thước mỗ i chiều
Khái niệm kiểu mảng tên mảng giống khái niệm kiểu biến tên biến Ta giải thích khái niệm số chiều kích thước chiều thơng qua ví dụ cụ thể Các khai báo :
int a[10],b[4][2]; float x[5],y[3][3];
sẽ xác định mảng ý nghĩa chúng sau :
(12)1 A Int 10 a[0],a[1],a[2] a[9]
2 B Int 4x2 b[0][0], b[0][1]
b[1][0], b[1][1] b[2][0], b[2][1] b[3][0], b[3][1]
3 X Float x[0],x[1],x[2] x[4]
4 Y Float 3x3 y[0][0], y[0][1], y[0][2]
y[1][0], y[1][1], y[1][2] y[2][0], y[2][1], y[1][2] Chó ý :
Các phần tử mảng cấp phát khoảng nhớ liên tiếp nhớ Nói cách khác, phần tử mảng có địa liên tiếp
Trong bé nhí, c¸c phần tử mảng hai chiều xếp theo hàng Chỉ số mảng :
Mt phn t c thể mảng xác định nhờ số Chỉ số mảng phải có giá trị int khơng vượt q kích thước tương ứng Số số phải số chiều mảng
Giả sử z,b,x,y khai báo trên, giả sử i,j biến nguyên i=2, j=1 Khi :
a[j+i-1] lµ a[2] b[j+i][2-i] lµ b[3][0] y[i][j] y[2][1] Chú ý :
Mảng có chiều ta phải viết có nhiêu số Vì ta viết sau sai : y[i] ( Vì y mảng chiều ) vv
Biểu thức dùng làm số thực Khi phần nguyên biểu thức thực số mảng
VÝ dô :
(13)* Khi số vượt kích thước mả ng, máy khơng báo lỗi, truy cập đến vùng nhớ bên ngồi mảng làm rối loạn chương trình
Lấy địa phần tử mảng :
Có vài hạn chế mảng hai chiều Chẳng hạn lấy địa phần tử mảng chiều, nói chung khơng cho phép lấy địa phần tử mảng hai chiều Như máy chấp nhận phép tính : &a[i] khơng chấp nhận phép tính &y[i][j] Địa đầu mảng :
Tên mảng biểu thị địa đầu mảng Như ta có th ể dùng a thay cho &a[0] Khởi đầu cho bin mng :
Các biến mảng khai báo bên thân hàm ( kể hàm main() ) gọi biến mảng cục
Muốn khởi đầu cho mảng cục ta sử dụng toán tử gán thân hàm Các biến mảng khai báo bên thân hàm gọi biến mảng Để khởi đầu cho biến mảng ta áp dụng qui tắc sau :
Cỏc bin mng ngồi khởi đầu ( lần ) vào lúc dịch chương trình cách sử dụng biểu thức Nếu không khởi đầu máy gán cho c húng giá trị
VÝ dô :
float y[6]={3.2,0,5.1,23,0,42}; int z[3][2]={
{25,31}, {12,13}, {45,15} {
main() {
(14)Khi khởi đầu mảng ngồi khơng cần kích thước ( số phần tử ) Khi đó, máy dành cho mảng khoảng nhớ đủ để thu nhận danh sách giá trị khởi đầu
VÝ dô :
float a[]={0,5.1,23,0,42}; int m[][3]={
{25,31,4}, {12,13,89}, {45,15,22} };
Khi kích thước mảng, kích thước cần khơng nhỏ kích thư ớc khởi đầu
VÝ dơ :
float m[6]={0,5.1,23,0}; int z[6][3]={
{25,31,3}, {12,13,22}, {45,15,11} };
Đối với mảng hai chiều, khởi đầu với số giá trị khởi đầu hàng khác :
Ví dô :
float z[][3]={
{31.5}, {12,13}, {-45.76} };
(15){31.11}, {12},
{45.14,15.09} };
Khởi đầu mảng char Một danh sách ký tự Một h»ng x©u ký tù
VÝ dơ :
char ten[]={'h','a','g'} char ho[]='tran'
(16)Chương 2 Các lệnh vào
Chương giới thiệu thư viện vào/ra chuẩn tập hàm thiết kế để cung cấp hệ thống vào/ra chuẩn cho chương trình C Chúng ta khơng mơ tả tồn thư viện vào mà quan tâm nhiều đến việc nêu điều để viết chương trình C tương tác với mơi trng v h iu hnh
2.1 Thâm nhập vào th viƯn chn :
Mỗi tệp gốc có tham trỏ tới hàm thư viện chuẩn phải chứa dòng :
#include <conio.h> cho hàm getch(), putch(), clrscr(), gotoxy() #include <stdio.h> cho hàm khác gets(), fflus(), fwrite(), scanf()
ở gần chỗ bắt đầu chương trình Tệp stdio.h định nghĩa macro biến hàm dùng thư viện vào/ra Dùng dấu ngoặc < > thay cho dấu nháy thông thường để thị cho trình biên dịch tìm kiếm tệp danh mục chứa thông tin tiêu đề chuẩn
2.2 Các hàm vào chuẩn - getchar() putchar() - getch() vµ putch() : 2.2.1 Hµm getchar () :
Cơ chế vào đơn giản đọc ký tự từ thiết bị vào chuẩn, nói chung bàn phím hình người sử dụng, bng hm getchar()
Cách dùng :
Dùng câu lƯnh sau : biÕn = getchar(); C«ng dơng :
Nhận ký tự vào từ bàn phím không đưa hình Hàm trả ký tự nhận lưu vào biến
Ví dụ :
int c;
(17)2.2.2 Hµm putchar () :
Để đưa ký tự thiết bị chuẩn, nói chung hình, ta sử dụng hàm putchar() Cách dùng :
Dùng câu lệnh sau : putchar(ch); Công dụng :
Đưa ký tự ch lên hình vị trí trỏ Ký tự hiển thị với màu tr¾ng
VÝ dơ :
int c;
c = getchar(); putchar(c); 2.2.3 Hµm getch() :
Hàm nhận ký tự từ đệm bàn phím, khơng cho lên hình Cách dùng :
Dïng c©u lƯnh sau : getch(); C«ng dơng :
Nếu có sẵn ký tự đệm bàn phím hàm nhận ký tự
Nếu đệm rỗng, máy tạm dừng Khi gõ ký tự hàm nhận ký tự ( khơng cần bấm thêm phím Enter hàm nhập khác ) Ký tự vừa gõ không lên hình
NÕu dïng :
biÕn=getch();
(18)c = getch(); 2 2.4 Hàm putch() : Cách dùng :
Dùng câu lệnh sau : putch(ch); Công dơng :
Đưa ký tự ch lên hình vị trí co n trỏ Ký tự hiển thị theo màu xác định hm textcolor
Hàm trả ký tự hiển thị
2.3 Đưa kết lên hình - hàm printf : Cách dùng :
prinf(iu khin, đối số 1, đối số 2, );
Hàm printf chuyển, tạo khuôn dạng in đ ối thiết bị chuẩn điều khiển xâu điều khiển. Xâu điều khiển chứa hai kiểu đối tượng : ký tự thông thường, chúng đưa trực tiếp thiết bị ra, đặc tả chuyển dạng, đặc tả tạo việc đổi dạng in đối tiếp sau printf
Chuỗiđiều khiểncó thể có ký tự điều khiển : \n sang dßng míi
\f sang trang \b lùi lại bước \t dấu tab
Dạng tổng quát đặc tả :
%[-][fw][.pp]ký tù chuyÓn d¹ng
Mỗi đặc tả chuyển dạng đưa vào ký tự % kết thúc ký tự chuyển dạng Giữa % ký tự chuyển dạng có :
DÊu trõ :
(19)bằng khoảng trống Riêng trường số, dãy số fw bắt đầu số vị trí dư thừa bên trái lấp đầy số
Khi có dấu trừ kết dồn bên trái vị trí dư thừa bên phải ( có ) lấp đầy kho¶ng trèng
fw :
Khi fw lớn độ dài thực tế kết vị trí dư thừa lấp đầy khoảng trống số nội dung kết đẩy bên phải bên trái
Khi khơng có fw fw nhỏ hay độ dài thực tế kết độ rộng thiết bị dành cho kết độ dài
Tại vị trí fw ta đặt dấu *, fw xác định giá trị nguyên đối tương ứng
VÝ dô :
KÕt fw Dấu - Kết đưa
-2503 cã -2503
-2503 08 cã -2503
-2503 kh«ng -2503
-2503 08 kh«ng 000-2503
"abcdef" kh«ng abcdef "abcdef" 08 cã abcdef "abcdef" 08 kh«ng abcdef pp :
Tham số pp sử dụng đối tư ơng ứng xâu ký tự giá trị kiểu float hay double
Trong trường hợp đối tương ứng có giá trị kiểu float hay double pp độ xác trường Nói cách cụ thể giá trị in có pp chữ số sau số thập phân
Khi vắng mặt pp độ xác xem Khi đối xâu ký tự :
(20)VÝ dơ :
KÕt qu¶ fw pp DÊu - Kết đưa
ra
di trng
-435.645 10 cã -435.65
-435.645 10 cã -436
-435.645 v¾ng cã -435.645000 11
"alphabeta" v¾ng alp
"alphabeta" v¾ng v¾ng v¾ng alphabeta
"alpha" có alpha
Các ký tự chuyển dạng ý nghÜa cña nã :
Ký tự chuyển dạng một dãy ký hiệu xác định quy tắc chuyển dạng dạng in đối tương ứng Như có tình trạng số in theo dạng khác Cần phải sử dụng ký tự chuyển dạng theo q ui tắc định sẵn Bảng sau cho thông tin ký tự chuyển dạng
Ký tù chuyển dạng ýnghĩa
d Đối chuyển sang số nguyên hệ thập phân
o i c chuyn sang hệ tám khơng dấu ( khơng có số đứng trước ) x Đối chuyển sang hệ mưới sáu khơng d ấu ( khơng có 0x đứng
trước )
u Đối chuyển sang hệ thập phân không dấu c Đối coi ký tự riªng biƯt
s Đối xâu ký tự, ký tự xâu in gặp ký tự không đủ số lượng ký tự xác định đặc t ả độ xác pp
e Đối xem float double chuyển sang dạng thập phân có dạng [-]m.n nE[+ -] với độ dài xâu chứa n pp f Đối xem float double chuyển sang dạng thập
phân có dạng [-]m m.n n với độ dài xâu chứa n pp Độ xác mặc định Lưu ý độ xác khơng xác định số chữ số có nghĩa phải in theo khn dạng f
(21)Chó ý :
Mọi dãy ký tự không bắt đầu % không kết thúc ký tự chuyển dạng xem ký tự hiển thị
Để hiển thị ký tự đặc biệt :
Cách viết Hiển thị
\' '
\" "
\\ \
C¸c vÝ dơ :
1 printf("\" Nang suat tang : %d % \" \n\\d"",30,-50); "Nang suat tang ; 30 %" \d=-50
2 n=8
float x=25.5, y=-47.335 printf("\n%f\n%*.2f",x,n,y); Lệnh tương đương với printf("\n%f\n%8.2f",x,n,y); Vì n=8 tương ứng với vị trí *
25.500000 -47.34
2.4 Vµo sè liƯu tõ bµn phÝm - hµm scanf :
Hàm scanf hàm đọc thơng tin từ thiết bị vào chuẩn ( bàn phím ), chuyển dịch chúng ( thành số nguyên, số thực, ký tự vv ) lưu trữ vào nhớ theo địa xác định
C¸ch dïng :
scanf(điều khiển,đối 1, đối 2, );
Xâuđiều khiểnchứa đặc tả chuyển dạng, đặc tả s ẽ tạo việc đổi dạng biến tiếp sau scanf
Đặc tả viết cách tổng quát nh sau : %[*][d d]ký tù chun d¹ng
Việc có mặt dấu * nói lên trường vào dị đọc bình thường, giá trị bị bỏ qua ( khơng lưu vào nhớ ) Như đặc tả chứa dấu * khơng có đối tương ứng
(22)Nếu tham số d d vắng mặt giá trị lớn hay độ dài trường vào tương ứng tồn trường vào đọc, nội dung dịch gán cho địa tương ứng ( khơng có dấu * )
Nếu giá trị d d nhỏ độ dài trường vào phần đầu trường có kích cỡ d d đọc gán cho địa biến tương ứng Phần lại trường xem xét đặc tả đối tương ứng
VÝ dô :
int a; float x,y; char ch[6],ct[6]
scanf("%f%5f%3d%3s%s",&x&y&a&ch&ct0; Với dòng vào : 54.32e-1 25 12452348a
Kết lệnh scanf gán 5.432 cho x
25.0 cho y 124 cho a
xâu "523" dấu kết thúc \0 cho ch xâu "48a" dấu kÕt thóc \0 cho ct Ký tù chun d¹ng :
Ký tự chuyển dạng xác định cách thức dò đọc ký tự dòng vào cách chuyển dịch thông tin đọc đựợc trước gán cho địa tương ứng
Cách dị đọc thứ đọc theo trường vào, khoảng trắng bị bỏ qua Cách áp dụng cho hầu hết trường hợp
Cách dò đọc thứ hai đọc theo ký tự, khoảng trắng cũ ng xem xét bình đẳng ký tự khác Phương pháp xảy ta sử dụng ba ký tự chuyển dạng sau : C, [ dãy ký tự ], [^ dóy ký t ]
Các ký tự chuyển dạng vµ ý nghÜa cđa nã :
c Vào ký tự, đối tương ứng trỏ ký tự Có xé t ký tự khoảng trắng
d Vào giá trị kiểu int, đối tương ứng trỏ kiểu int Trường phải vào số nguyên
(23)nguyªn
o Vào giá trị kiểu int hệ 8, đối tương ứn g trỏ kiểu int Trường phải vào số nguyên hệ
lo Vào giá trị kiểu long hệ 8, đối tương ứng trỏ kiểu long Trường phải vào số nguyên hệ
x Vào giá trị kiểu int hệ 16, đối tương ứng trỏ kiểu int Trường phải vào số nguyên hệ 16
lx Vào giá trị kiểu long hệ 16, đối tương ứng trỏ kiểu long Trường phải vào số nguyên hệ 16
f hay e Vào giá trị kiểu float, đối tương ứng trỏ float, trường vào phải số dấu phảy động
lf hay le Vào giá trị kiểu double, đối tương ứng trỏ double, trường vào phải số dấu phảy động
s Vào giá trị kiểu double, đối tương ứng trỏ kiểu char, trường vào phải dãy ký tự không chứa dấu cách dấu xuống dòng
[ Dãy ký tự ], [ ^Dãy ký tự ] Các ký tự dòng vào đọc gặp ký tự không thuộc tập ký tự đặt trong[] Đối tương ứng trỏ kiểu char Trường vào dãy ký tự ( khoảng trắng xem ký tự )
VÝ dô :
int a,b;
char ch[10], ck[10];
scanf("%d%[0123456789]%[^0123456789]%3d",&a,ch,ck,&b); Với dòng vào :
35 13145 xyz 584235 Sẽ gán :
35 cho a
xâu "13145" cho ch x©u "xyz' cho ck 584 cho b Chó ý :
(24)int a,b,c;
scanf("%d%d%d,&a,&b,&c);
Để vào số liệu ta thao t¸c theo nhiỊu c¸ch kh¸c nhau: C¸ch :
Đưa ba số vào dòng, số phân cách dấu cách dấu tab Cách :
Đưa ba số vào ba dòng khác Cách :
Hai số đầu dòng ( cách nahu dấu cách hoặ tab ), số thứ ba dòng
Cách :
Số thứ dòng, hai số sau dòng ( cách nahu dấu cách hoặ tab ), số thứ ba dòng tiế p theo
Khi vào sai báo lỗi nhảy chương trình chứa lời gọi 2.5 Đưa kt qu mỏy in :
Để đưa kết máy in ta dùng hàm chuẩn fprintf có dạng sau : fprintf(stdprn, điều khiển, biến 1, biến 2, );
Tham số stdprn xác định thiết bị đư a máy in Điều khiển có dạng đặc tả lệnh printf
Dïng gièng nh lÖnh printf, khác in máy in Ví dụ :
Đoạn chương trình in ma trận A, cỡ 8x6 Mỗi hàng ma trận in dòng : float a[8][6];
int i,j;
fprintf(stdprn,"\n%20c MA TRAN A\n\n\n",' '); for (i=0;i<8;++i)
{ for (j=0;j<6;++j)
fprintf(stdprn,"%10.2f",a[i][j]); fprintf(stdprn,"\n");
(25)Chương 3 Biểu thức
Tốn hạng xem đại lượng có giá trị Tốn hạng bao gồ m hằng, biến, phần tử mảng hàm
Biểu thức lập nên từ toán hạng phép tính để tạo nên giá trị Biểu thức dùng để diễn đạt công thức, qui trình tính tốn, thành phần khơng thể thiếu chương trình
3.1 BiĨu thøc :
Biểu thức kết hợp phép toán toán hạng để diễn đạt cơng thức tốn học Mỗi biểu thức có có giá trị Như hằng, biến, phần tử mảng hàm xem biểu thức
Trong C, ta cã hai kh¸i niƯm vỊ biểu thức : Biểu thức gán
Biểu thức điều kiÖn
Biểu thức phân loại theo kiểu giá trị : nguyên thực Trong mệnh đề logic, biểu thức phân thành ( giá trị khác ) sai ( giá trị )
Biểu thức thường dùng : Vế phải câu lệnh gán Làm tham số thực hàm Làm số
Trong c¸c to¸n tư cấu trúc điều khiển
Ti õy, ta có hai khái niệm tạo nên biểu thức tốn hạng phép tốn Tốn hạng gồm : hằng, biến, phần tử mảng hàm t rước ta xét Dưới ta nói đến phép toán Hàm đề cập chương
3.2 Lệnh gán biểu thức:
Biểu thức gán biểu thức có dạng : v=e
Trong v biến ( hay phần tử mảng ), e biểu thức Giá trị biểu thức g án giá trị e, kiểu kiểu v Nếu đặt dấu ; vào sau biểu thức gán ta thu phép tốn gán có dạng :
(26)BiĨu thøc g¸n cã thĨ sư dơng c¸c phÐp to¸n câu lệnh biểu thức khác Ví dơ nh ta viÕt
a=b=5;
thì điều có nghĩa gán giá trị biểu thức b=5 cho biến a Kết qủa b=5 a=5 Hồn tồn tương tự :
a=b=c=d=6; g¸n cho a, b, c d Ví dụ :
z=(y=2)*(x=6); { * phép toán nhân } gán cho y, cho x nhân hai biểu thức lại cho ta z=12 3.3 Các phép toán số học :
Các phép toán hai số học
Phép toán ý nghià Ví dụ
+ PhÐp céng a+b
- PhÐp trõ a-b
* PhÐp nh©n a*b
/ PhÐp chia a/b
( Chia số nguyên chặt phần thập phân )
% PhÐp lÊy phÇn d a%b
( Cho phần dư phép chia a cho b ) Có phép tốn ngơi - ví du -(a+b) đảo giá trị phép cộng (a+b)
VÝ dô :
11/3=3 11%3=2 -(2+6)=-8
C¸c phÐp to¸n + - có thứ tự ưu tiên, có thứ tự ưu tiên nhỏ phép * , / , % ba phép lại có thứ tự ưu t iên nhỏ phép trừ
Các phép toán số học thực từ trái sang phải Số ưu tiên khả kết hợp phép toán mục sau nµy
(27)Phép tốn quan hệ logic cho ta giá trị ( ) giá trị sai ( ) Nói cách khác, điều kiện nêu ta nhận giá trị 1, trái lại ta nhận giá tr
Các phép toán quan hệ :
PhÐp to¸n ý nghi· VÝ dơ
> So sánh lớn a>b
4>5 có giá trị >= So sánh lớn a>=b
6>=2 có giá trị
< So sánh nhỏ a<b
6<=7 có giá trị <= So sánh nhỏ a<=b
8<=5 có giá trị
== So s¸nh b»ng a==b
6==6 có giá trị
!= So sánh khác a!=b
9!=9 có giá trị
Bốn phép toán đầu có số ưu tiên, hai phép sau có số thứ tự ưu tiên thấp số thứ tự bốn phép đầu
Các phép toán quan hệ có số thứ tự ưu tiên thấp so với phép toán số học, biểu thức :
i<n-1
được hiểu i<(n-1) C¸c phÐp to¸n logic :
Trong C sử dụng ba phép tốn logic : Phép phủ định ngơi !
a !a
kh¸c 0
b»ng
Phép (AND) && Phép ( OR ) ||
(28)kh¸c kh¸c 1
kh¸c b»ng 0
b»ng kh¸c 0
b»ng b»ng 0
C¸c phÐp quan hƯ cã số ưu tiên nhỏ so với ! lớn so với && ||, biểu thức :
(a<b)&&(c>d) viết lại thành :
a<b&&c>d Chú ý :
Cả a b nguyên thực 3.5 Phép toán tăng gi¶m :
C đưa hai phép tốn để tăng giảm biến ( nguyên thực ) Toán tử tăng ++ cộng vào tốn hạng nó, tốn tử giảm trừ tốn hạng
VÝ dơ : n=5
++n Cho ta n=6 n Cho ta n=4
Ta viết phép tốn ++ trước sau toán hạng sau : ++n, n++, n, n
Sự khác ++n n ++ chỗ : phép n++ tăng sau giá trị sử dụng, cịn phép ++n n tăng trước sử dụng Sự khác n n
VÝ dơ : n=5
x=++n Cho ta x=6 vµ n=6 x=n++ Cho ta x=5 vµ n=6 3.6 Thø tù ưu tiên phép toán :
(29)Thứ tự ưu tiên phép toán trình bày bảng sau :
TT Phép toán Trình tự kết hợp
1 () [] -> Trái qua ph¶i
2 ! ~ & * - ++ (type ) sizeof Phải qua trái
3 * ( phép nhân ) / % Trái qua phải
4 + - Trái qua phải
5 << >> Trái qua phải
6 < <= > >= Trái qua phải
7 == != Trái qua phải
8 & Trái qua phải
9 ^ Trái qua phải
10 | Trái qua phải
11 && Trái qua phải
12 || Trái qua phải
13 ?: Phải qua trái
14 = += -= *= /= %= <<= >>= &= ^= |= Ph¶i qua trái
15 , Trái qua phải
Chú thích :
Các phép tốn tên dịng có thứ tự ưu tiên, phép toán hàng có số ưu tiên cao số hàng
Đối với phép toán mức ưu tiên trình tự tính tốn từ trái qua phải hay ngược lại cột trình tự kết hợp
VÝ dơ :
* px=*( px) ( Phải qua trái ) 8/4*6=(8/4)*6 ( Trái qua ph¶i )
Nên dùng dấu ngoặc trịn để viết biểu thức cách xác Các phép tốn lạ :
Dßng
(30)Dßng
* Dùng để khai báo trỏ, ví dụ : int *a & Phép tốn lấy địa chỉ, ví dụ : &x
( type) phép chuyển đổi kiểu, ví dụ : (float)(x+y) Dịng 15
Toán tử, thường dùng để viết dãy biểu thức toán tử fo r
3.7 Chuyển đổi kiểu giá trị :
Việc chuyển đổi kiểu giá trị thường diễn cách tự động hai trường hợp sau : Khi gán biểu thức gồm toán hạng khác kiểu
Khi gán giá trị kiểu cho biến ( phần tử mảng ) kiểu khác Điều xảy toán tử gán, việc truyền giá trị tham số thực cho đối
Ngoµi ra, ta cã thĨ chun từ kiểu giá trị sang kiểu mµ ta mn b»ng phÐp chun sau :
( type ) biĨu thøc VÝ dơ :
(float) (a+b)
Chuyển đổi kiểu biểu thức :
Khi hai tốn hạng phép tốn có kiểu khác kiểu thấp nâng thành kiểu cao trước thực phép toán Kết thu giá trị kiểu cao Chẳng hn :
Giữa int long int chuyển thành long Giữa int float int chuyển thành float
Giữa float double float chuyển thành double VÝ dô :
1.5*(11/3)=4.5 1.5*11/3=5.5 (11/3)*1.5=4.5
(31)Giá trị vế phải chuyển sang kiểu vế trái kiểu c kết Kiểu int được chuyển thành float Kiểu float chuyển thành int chặt phần thập phân Kiểu double chuyển thành float cách làm tròn Kiểu long chuyển thành int cách cắt bỏ vài chữ số
VÝ dô : int n;
n=15.6 giá trị n 15 Đổi kiĨu d¹ng (type)biĨu thøc :
Theo cách này, kiểu biểu thức đổi thành kiểu type theo nguyên tắc Ví dụ :
PhÐp to¸n : (int)a
cho giá trị kiểu int Nếu a float có chuyển đổi từ float sang int Chú ý thân kiểu a khơng bị thay đổi Nói cách khác, a có kiểu float (int)a có kiểu int
Đối với hàm tốn học thư viện chuẩn, giá trị đối giá trị hàm có kiểu double, để tính bậc hai biế n nguyên n ta phải dùng phép ép kiểu để chuyển kiểu int sang double sau :
sqrt((double)n)
PhÐp Ðp kiÓu cã cïng sè ưu tiên toán tử Chú ý :
Muốn có giá trị xác phép chia hai số nguyên cần dùng phép ép kiểu : ((float)a)/b
Để đổi giá trị thực r sang nguyên, ta dùng : (int)(r+0.5)
Chó ý thø tù u tiªn :
(32)Chương 4
Cấu trúc chương trình 4.1 Lời thích :
Các lời bình luận, lời giải thích đưa vào chỗ chương trình chương trình dễ hiểu, dễ đọc mà không làm ảnh hưởng đến phần khác Lời giải thích đặt hai dấu /* */
Trong chương trình cần ( ln ln cần ) viết thêm lời giải thích để chương trình thêm rõ ràng, thêm dễ hiểu
VÝ dô :
#include "stdio.h" #include "string.h" #include "alloc.h" #include "process.h" int main()
{
char *str;
/* Cấp phát nhớ cho xâu ký tù */ if ((str = malloc(10)) == NULL) {
printf("Not enough memory to allocate buffer \n"); exit(1); /* Kết thúc chương trình thiếu nhớ */ }
/* copy "Hello" vào xâu */ strcpy(str, "Hello"); /* Hiển thị x©u */
printf("String is %s\n", str); /* Gi¶i phãng bé nhí */ free(str);
(33)4.2 LƯnh vµ khèi lƯnh : 4.2.1 LƯnh :
Mét biĨu thøc kiĨu nh x=0 hc ++i scanf( ) trở thành câu lệnh có kÌm theo dÊu ;
VÝ dơ :
x=0; ++i; scanf( );
Trong chương trình C, dấu ; dấu hiệu kết thúc câu lệnh 4.2.2 Khối lệnh :
Một dÃy câu lệnh bao dấu { } gọi khối lệnh Ví dô : {
a=2; b=3;
printf("\n%6d%6d",a,b); }
TURBO C xem khối lệnh câu lệnh riêng lẻ Nói cách khác, chỗ viết câu lệnh có quyền đặt lnh
Khai báo đầu khối lệnh :
Các khai báo biến mảng đặt đầu hàm mà cịn viết đầu khối lệnh :
{
int a,b,c[50]; float x,y,z,t[20][30]; a==b==3;
x=5.5; y=a*x; z=b*x;
printf("\n y= %8.2f\n z=%8.2f",y,z); }
(34)Bªn mét khèi lƯnh l¹i cã thĨ viÕt lång khèi lệnh khác Sự lồng theo cách không hạn chế
Khi máy bắt đầu làm việc với khối lệnh biến mảng khai báo bên hình thành hình thành cấp phát nhớ Các biến tồn thời gian máy làm việc bên khối lệnh chúng biến sau m¸y khái khèi lƯnh VËy :
Giá trị biến hay mảng khai báo bên khối lệnh đưa sử dụng chỗ bên khối lệnh
ở chỗ bên ngồi khối lệnh ta can thiệp đến biến mảng khai báo bên k hối lệnh
Nếu bên khối ta dùng biến hay mảng có tên a điều không làm thay đổi giá trị biến khác có tên a ( có ) dùng bên ngồi khối lệnh
Nếu có biến khai báo ngồi khối lệnh khơng trùng tên với biến khai báo bên khối lệnh biến sử dụng bên bên ngồi khối lệnh
VÝ dơ :
Xét đoạn chương trình sau : {
int a=5,b=2; {
int a=4; b=a+b;
printf("\n a =%3d b=%3d",a,b); }
printf("\n a ngoai =%3d b=%3d",a,b); }
Khi đoạn chương trình in kết sau : a =4 b=6
a ngoµi =5 b=6
(35)Cấu trúc chương trình hàm vấn đề quan trọng C Về hàm ta có chương nói tỉ mỷ ta đưa số qui tắc chung :
Hàm đơn vị độc lập chương trình Tính độc lập hàm thể hai điểm : Không cho phép xây dựng hàm b ên hàm khác
Mỗi hàm có biến, mảng riêng chúng sử dụng nội bên hàm Nói cách khác hàm đơn vị có tính chất khép kín
Một chương trình bao gồm nhiều hàm Hàm main() thành phần bắt buộc chương trình Chương trình bắt đầu thực câu lệnh hàm main() kết thúc gặp dấu } cuối hàm Khi chương trình làm việc, máy chạy từ hàm sang hàm khác
Các chương trình C tổ chức theo mẫu :
hµm hµm hµm n
Bên ngồi hàm vị trí ( ) chỗ đặt : toán tử #include ( dùng để khai báo sử dụng hàm chuẩn ), toán tử #define ( dùng để định nghĩa ), định nghĩa kiểu liệu typedef, khai báo biến ngồi, mảng ngồi
ViƯc trun d÷ liƯu kết từ hàm sang hàm khác thùc hiƯn theo mét hai c¸ch :
Sử dng i ca hm
Sử dụng biến ngoài, mảng ngoµi
Vậy nói tóm lại cấu truc chương trình sau : Các #include
C¸c #define
Khai báo đối tượng liệu ( biến, mảng, cấu trúc vv ) Khai báo nguyên mẫu hàm
Hµm main()
(36)VÝ dơ :
Chương trình tính x lũy thừa y rỗi in m áy in kết : #include "stdio.h"
#include "math.h" main()
{
double x,y,z;
printf("\n Nhap x va y"); scanf("%lf%lf",&x,&y);
z=pow(x,y); /* hµm lÊy luü thõa y luü thõa x */
fprintf(stdprn,"\n x= %8.2lf \n y=%8.2lf \n z=%8.2lf",x,y,z); }
4.4 Một số qui tắc cần nhớ viết chương trình : Qui tắc u tiờn cn nh l :
Mỗi câu lệnh viết hay nhiều dòng phải kết thúc bằng dấu;
Qui tắc thứ hai :
Các lời giải thích cần đặt dấu /* */ viết Trờn mt dũng
Trên nhiều dòng
Trên phần lại dòng
Qui tắc thứ ba :
Trong chương trình, ta sử dụng hàm chuẩn, ví dụ printf(), getch() , mà hàm lại chứa file stdio.h thư mục C, vì đầu chương trình ta phải khai báo sử dụng ;
#include "stdio.h "
Qui tắc thứ tư :
(37)(38)Chương 5
CÊu tróc ®iỊu khiĨn
Một chương trình bao gồm nhiều câu lệnh Thơng thường câu lệnh thực cách theo thứ tự mà chúng viết Các cấu trúc điều khiển cho phép thay đổi trật tự nói trên, máy nhảy thực câu lệnh khác ví trí trước sau cõu lnh hin thi
Xét mặt công dụng, chia cấu trúc điều khiển thành nhóm : Nhảy điều kiện
Rẽ nhánh
Tổ chức chu trình
Ngoài số toán tử khác có chức bổ trợ break, continue 5.1 Cấu trúc có điều kiện :
5.1.1 LƯnh if-else :
To¸n tư if cho phép lựa chọn chạy theo hai nhánh tuỳ thuộc vào không khác không biĨu thøc Nã cã hai c¸ch viÕt sau :
if ( biĨu thøc ) khèi lƯnh 1; /* D¹ng mét */
if ( biĨu thøc ) khèi lƯnh 1; else
khèi lƯnh ; /* D¹ng hai */
Hoạt động biểu thức dạng :
Máy tính giá trị biểu thức Nếu biểu thức ( biểu thức có giá trị khác ) máy thực khối lệnh sau thực lệnh tiếp sau lệnh if chương trình Nếu biểu thức sai ( biểu thức có giá trị ) máy bỏ qua khối lệnh mà thực lệnh tiếp sau lệnh if chương trình
Hoạt động biểu thức dạng :
(39)biểu thức sai ( biểu thức có giá trị ) máy bỏ qua khối lệnh mà thực khối lệnh sau thực tiếp lệnh tiếp sau khối lệnh chương trình
VÝ dơ :
Chương trình nhập vào hai số a b, tìm max hai số in kết lên hình Chương trình viết hai cách sau :
#include "stdio.h" main()
{
float a,b,max; printf("\n Cho a="); scanf("%f",&a); printf("\n Cho b="); scanf("%f",&b); max=a;
if (b>max) max=b;
printf(" \n Max cua hai so a=%8.2f va b=%8.2f la Max=%8.2f",a,b,max); }
#include "stdio.h" main()
{
float a,b,max; printf("\n Cho a="); scanf("%f",&a); printf("\n Cho b="); scanf("%f",&b); if (a>b) max=a; else max=b;
printf(" \n Max cua hai so a=%8.2f va b=%8.2f la Max=%8.2f",a,b,max); }
(40)C cho phép sử dụng toán tử if lồng có nghĩa khối lệnh ( ) chứa toán tử if - else khác Trong trường hợp này, khơng sử dụng dấu đóng mở ngoặc cho khối nhầm lẫn if -else
Chú ý máy gắn tốn tử else với tốn tử if khơng có else gần Chẳng hạn đoạn chương trình ví dụ sau :
if ( n>0 ) /* if thø nhÊt*/ if ( a>b ) /* if thø hai*/
z=a; else
z=b; else ®i víi if thø hai
Đoạn chương trình tương đương với : if ( n>0 ) /* if thứ nhất*/
{
if ( a>b ) /* if thø hai*/ z=a;
else
z=b; }
Trường hợp ta muốn else với if thứ ta viết sau : if ( n>0 ) /* if thứ nhất*/
{
if ( a>b ) /* if thø hai*/ z=a;
} else
z=b;
5.1.2 LÖnh else-if :
Khi muốn thực n định ta sử dụng cấu trúc sau : if ( biểu thức )
(41)else if ( biĨu thøc ) khèi lƯnh 2;
else if ( biÓu thøc n-1 ) khèi lÖnh n-1;
else
khèi lÖnh n;
Trong cấu trúc này, máy kiểm tra từ biểu thức trở đến gặp biểu thức có giá trị khác
Nếu biểu thức thứ i (1,2, n -1) có giá trị khác 0, máy thực khối lệnh i, sau thực lệnh nằm khối lệnh n chương trình
Nếu n-1 biểu thức khơng có biểu thức khác 0, máy thực khối lệnh n sau thực lệnh nằm khối lệnh n chương trình
VÝ dơ :
Chương trình giải phương trình bậc hai #include "stdio.h"
main() {
float a,b,c,d,x1,x2; printf("\n Nhap a, b, c:"); scanf("%f%f%f,&a&b&c); d=b*b-4*a*c;
if (d<0.0)
printf("\n Phuong trinh vo nghiem "); else if (d==0.0)
printf("\n Phuong trinh co nghiem kep x1,2=%8.2f", -b/(2*a)); else
{
(42)5.2 Lệnh nhảy không điều kiện - toán tử goto :
Nhãn có dạng tên biến có dấu : đứng phía sau Nhãn gán cho câu lệnh chương trình
VÝ dơ :
ts : s=s++;
thì đâyts nhÃn câu lệnh gán s=s++ Toán tử goto có dạng :
goto nhÃn;
Khi gặp toán tử máy nhảy tới câu lƯnh cã nh·n viÕt sau tõ kho¸ goto Khi dïng toán tử goto cần ý :
Cõu lnh goto nhãn cần nằm hàm, có nghĩa toán tử g oto cho phép nhảy từ vị trí đến vị trí khác thân hàm dùng để nhảy từ hàm sang hàm khác
Không cho phép dùng tốn tử goto để nhảy từ ngồi vào khối lệnh Tuy nhiên việc nhảy từ khối lệnh ngo ài hồn tồn hợp lệ Ví dụ đoạn chương trình sau sai
goto n1; {
n1: printf("\n Gia tri cua N la: ");
} VÝ dô :
TÝnh tæng s=1+2+3+ +10 #include "stdio.h"
main() {
(43)++i; s=s+i;
if (i<10) goto tong; printf("\n tong s=%d",s); }
5.3 CÊu tróc rÏ nh¸nh - to¸n tư switch:
Là cấu trúc tạo nhiều nhánh đặc biệt Nó vào giá trị biểu thức nguyên để để chọn nhiều cách nhy
Cấu trúc tổng quát : switch ( biĨu thøc nguyªn ) {
case n1
khèi lÖnh case n2
khèi lÖnh
case nk khèi lÖnh k [ default
khèi lÖnh k+1 ] }
Với ni số nguyên, ký tự biểu thức Các ni cần có giá trị khác Đoạn chương trình nằm gi ữa dấu { } gọi thân ca toỏn t switch
default thành phần không bắt buộc phải có thân switch
Sự hoạt động toán tử switch phụ thuộc vào giá trị biểu thức viết dấu ngoặc ( ) nh sau :
Khi giá trị biểu thức ni, máy nhảy tới câu lệnh có nhÃn case ni Khi giá trị biểu thức khác tất ni cách làm việc máy lại phụ thuộc vào có mặt hay kh«ng cđa lƯnh default nh sau :
(44)Máy nhảy khỏi toán tử switch gặp câu lệnh break dấu ngoặc nhọn đóng cuối thân switch Ta dùng câu lệnh goto thân toán tử switch để nhảy tới câu lệnh bên switch
Khi toán tử switch nằm thân hàm ta sử dụng câu lệnh return thân switch để khỏi hàm ( lệnh return đề cập sau )
Khi máy nhảy tới câu lệnh hoạt động tiếp t heo phụ thuộc vào câu lệnh đứng sau câu lệnh Như máy nhảy tới câu lệnh có nhãn case ni thực tất câu lệnh sau gặp câu lệnh break, goto return Nói cách khác, máy từ nhóm lệnh thuộc case ni sang nhóm lệnh thuộc case thứ ni+1 Nếu nhóm lệnh kết thúc break tốn tử switch thực nhóm lệnh
VÝ dơ :
Lập chương trình phân loại học sinh theo điểm sử dụng cấu trúc switch : #include "stdio.h"
main() {
int diem;
tt: printf("\nVao du lieu :"); printf("\n Diem ="); scanf("%d",&diem); switch (diem) {
case 0: case 1: case 2:
case 3:printf("Kem\n");break; case 4:printf("Yeu\n");break; case 5:
case 6:printf("Trung binh\n");break; case 7:
case 8:printf("Kha\n");break; case 9:
(45)}
printf("Tiep tuc 1, dung :") scanf("%d",&diem);
if (diem==1) goto tt; getch();
return; }
5.4 CÊu tróc lặp :
5.4.1 Cấu trúc lặp với toán tử while for : 5.4.1.1 Cấu trúc lặp với toán tư while :
Tốn tử while dùng để xây dựng chu trình lặp dạng : while ( biểu thức )
Lệnh khối lệnh;
Như toán tử while gồm biểu thức thân chu tr ình Thân chu trình lệnh mét khèi lƯnh
Hoạt động chu trình sau :
Máy xác định giá trị biểu thức, tuỳ thuộc giá trị máy chọn cách thực sau :
Nếu biểu thức có giá trị ( biểu thức sai ), máy khỏi c hu trình chuyển tới thực câu lệnh tiếp sau chu trình chương trình
Nếu biểu thức có giá trị khác khơng ( biểu thức ), máy thực lệnh khối lệnh thân while Khi máy thực xong khối lệnh lại thực xác đ ịnh lại giá trị biểu thức làm tiếp bước
Chó ý :
Trong dấu ngoặc ( ) sau while đặt biểu thức mà cịn đặt dãy biểu thức phân cách dấu phảy Tính sai dãy biểu thức hiểu tính sai biểu thức cuối dãy
Bên thân tốn tử while lại sử dụng toán tử while khác cách ta xây dựng chu trình lồng
(46)Trong thân while sử dụng toán tử goto để nhảy khỏi chu trình đến vị trí mong muốn Ta sử dụng tốn tử return thân while để khỏi hàm
VÝ dơ :
Chương trình tính tích vơ hướng hai véc tơ x y : Cách :
#include "stdio.h"
float x[]={2,3.4,4.6,21}, y[]={24,12.3,56.8,32.9}; main()
{
float s=0; int i=-1; while (++i<4) s+=x[i]*y[i];
printf("\n Tich vo huong hai vec to x va y la :%8.2f",s); }
C¸ch :
#include "stdio.h"
float x[]={2,3.4,4.6,21}, y[]={24,12.3,56.8,32.9}; main()
{
float s=0; int i=0; while (1) {
s+=x[i]*y[i]; if (++i>=4) goto kt; }
(47)C¸ch :
#include "stdio.h"
float x[]={2,3.4,4.6,21}, y[]={24,12.3,56.8,32.9}; main()
{
float s=0; int i=0;
while ( s+=x[i]*y[i], ++i<=3 );
printf("\n Tich vo huong hai vec to x va y la :%8.2f",s); }
5.4.1.2 Cấu trúc lặp với toán tư for :
Tốn tử for dùng để xây dựng cấu trúc lặp c ó dạng sau : for ( biểu thức 1; biểu thức 2; biểu thức 3)
Lệnh khối lệnh ;
Toán tử for gồm ba biểu thức thân for Thân for câu lệnh khối lệnh viết sau từ khoá for Bất kỳ biểu thức ba biểu thức vắng mặt n hưng phải giữ dÊu ;
Thông thường biểu thức toán tử gán để tạo giá trị ban đầu cho biến điều khiển, biểu thức quan hệ logic biểu thị điều kiện để tiếp tục chu trình, biểu thức ba toán tử gán dùng để thay đổi giá trị biến điều khiển
Hoạt động toán tử for :
Toán tử for hoạt động theo bước sau : Xác định biểu thức
Xác định biểu thức
Tuỳ thuộc vào tính sai biểu thức để máy lựa chọn hai nhánh :
NÕu biÓu thức hai có giá trị ( sai ), máy k hỏi for chuyển tới câu lệnh sau th©n for
Nếu biểu thức hai có giá trị khác ( ), máy thực câu lệnh thân for
(48)Chó ý :
Nếu biểu thức vắng mặt ln xem Trong trường hợp việc khỏi chu trình for cần phải thực nhờ lệnh break, goto return viết thân chu trình
Trong dấu ngoặc trịn sau từ khoá for gồm ba biểu thức phân cách dấu ; T rong biểu thức viết biểu thức mà có quyền viết dãy biểu thức phân cách dấu phảy Khi biểu thức phần xác định từ trái sang phải Tính sai dãy biểu thức tính tính sai biể u thức cuối dãy Trong thân for ta dùng thêm tốn tử for khác, ta xây dựng tốn tử for lồng
Khi gặp câu lệnh break thân for, máy khỏi toán tử for sâu chứa câu lệnh Trong thân for sử dụng tốn tử goto để nhảy đến ví trí mong muốn
VÝ dô 1:
Nhập dãy số đảo ngược thứ tự Cách 1:
#include “stdio.h”
float x[]={1.3,2.5,7.98,56.9,7.23}; int n=sizeof(x)/sizeof(float); main()
{
int i,j; float c;
for (i=0,j=n-1;i<j;++i, j) {
c=x[i];x[i]=x[j];x[j]=c; }
fprintf(stdprn,“\n Day so dao la \n\n”); for (i=0;i<n;++i)
(49)C¸ch :
#include “stdio.h”
float x[]={1.3,2.5,7.98,56.9,7.23}; int n=sizeof(x)/sizeof(float); main()
{
int i,j; float c;
for (i=0,j=n-1;i<j;c=x[i],x[i]=x[j],x[j]=c,++i, j) fprintf(stdprn,“\n Day so dao la \n\n”);
for (i=0;++i<n;)
fprintf(stdprn,“%8.2f”,x[i]); }
C¸ch :
#include “stdio.h”
float x[]={1.3,2.5,7.98,56.9,7.23}; int n=sizeof(x)/sizeof(float); main()
{
int i=0,j=n-1; float c; for ( ; ; ) {
c=x[i];x[i]=x[j];x[j]=c; if (++i> j) break; }
fprintf(stdprn,“\n Day so dao la \n\n”);
for (i=-1;i++<n-1; fprintf(stdprn,“%8.2f”,x[i])); }
VÝ dô 2:
(50)float x[3][2],y[2][4],z[3][4],c; main()
{
int i,j;
printf("\n nhap gia tri cho ma tran X "); for (i=0;i<=2;++i)
for (j=0;j<=1;++j) {
printf("\n x[%d][%d]=",i,j); scanf("%f",&c);
x[i][j]=c; }
printf("\n nhap gia tri cho ma tran Y "); for (i=0;i<=1;++i)
for (j=0;j<=3;++j) {
printf("\n y[%d][%d]=",i,j); scanf("%f",&c);
y[i][j]=c; }
for (i=0;i<=3;++i) for (j=0;j<=4;++j) z[i][j]
}
5.4.2 Chu tr×nh do-while
Khác với toán tử while for, việc kiểm tra điều kiện kết thúc đặt đầu chu trình, chu trình while việc kiểm tra điều kiện kết thúc đặt cuối chu trình Như thân chu trình thực mt ln
Chu trình while có dạng sau :
LƯnh hc khèi lƯnh; while ( biĨu thøc );
(51)Hoạt động chu trình sau :
M¸y thùc hiƯn c¸c lƯnh thân chu trình
Khi thc hin xong tt lệnh thân chu trình, máy xác định giá trị biểu thức sau từ khoá while định thực sau :
Nếu biểu thức ( khác ) máy thực lặp lại khối lệnh chu trình lần thứ hai thực kiểm tra lại biểu thức
Nếu biểu thức sai ( ) máy kết thúc chu trình chuyển tới thực lệnh đứng sau tốn tử while
Chó ý :
Những điều lưu ý với toán tử while hồn tồn với while Ví dụ :
Đoạn chương trình xác định phần tử âm phần tử mảng x #include "stdio.h"
float x[5],c; main()
{
int i=0;
printf("\n nhap gia tri cho ma tran x "); for (i=0;i<=4;++i)
{
printf("\n x[%d]=",i); scanf("%f",&c); y[i]=c;
}
++i;
while (x[i]>=0 && i<=4); if (i<=4)
printf("\n Phan tu am dau tien = x[%d]=%8.2f",i,x[i]); else
(52)}
5.5 C©u lƯnh break :
C©u lƯnh break cho phÐp khỏi chu trình với toán tử for, while switch Khi có nhiều chu trình lồng nhau, câu lệnh break đưa máy khỏi chu trình bên chứa không cần điều kiện Mọi c©u lƯnh break cã thĨ thay b»ng c©u lƯnh goto víi nh·n thÝch hỵp VÝ dơ :
Biết số nguyên dương n số nguyên tố không chia hết cho số nguyên khoảng từ đến bậc hai n Viết đoạn chương trình đọc vào số ngun dương n, xem n có số nguyên tố
# include "stdio.h" # include "math.h" unsigned int n; main()
{
int i,nt=1;
printf("\n cho n="); scanf("%d",&n); for (i=2;i<=sqrt(n);++i) if ((n % i)==0)
{
nt=0; break; }
if (nt)
printf("\n %d la so nguyen to",n); else
printf("\n %d khong la so nguyen to",n); }
5.6 C©u lƯnh continue :
(53)cịn for điều khiển chuyển bước khởi đầu lại ( tức bước : tính biểu thức 3, sau quay lại bước để bắt đầu vòng chu trình)
Chó ý :
LƯnh continue áp dụng cho chu trình không áp dụng cho switch VÝ dơ :
Viết chương trình để từ nhập ma trận a sau : Tính tổng phần tử dương a
Xác định số phần tử dương a
Tìm cực đại phần tử dương a #include "stdio.h"
float a[3[4]; main()
{
int i,j,soptd=0;
float tongduong=0,cucdai=0,phu; for (i=0;i<3;++i)
for (j=0;i<4;++j) {
printf("\n a[%d][%d]=",i,j ); scanf("%f",&phu);
a[i][j]=phu;
if (a[i][j]<=0) continue; tongduong+=a[i][j];
if (cucdai<a[i][j]) cucdai=a[i][j]; ++soptd;
}
printf("\n So phan tu duong la : %d",soptd);
(54)(55)Chương 6 Hàm
Một chương trình viết ngôn ngữ C dãy hàm, có hàm ( hàm main() ) Hàm chia tốn lớn thành cơng việc nhỏ hơn, giúp thực công việc lặp lại cách nhanh chóng m khơng phải viết lại đoạn chương trình Thứ tự hàm chương trình bất kỳ, song chương trình thực từ hàm main() 6.1 Cơ sở :
Hàm xem đơn vị độc lập chương trình Các hàm có vai trị ngang nhau, khơng có phép xây dựng hàm bên hàm khác
Xây dựng hàm bao gồm: khai báo kiểu hàm, đặt tên hàm, khai báo đối đưa câu lệnh cần thiết để thực yêu cầu đề cho hàm Một hàm viết theo mẫu sau :
type tên hàm ( khai báo đối ) {
Khai báo biến cục Các câu lệnh
[return[biĨu thøc];] }
Dịng tiêu đề :
Trong dịng hàm chứa thơng tin : kiểu hàm, tên hàm, kiểu tên đối
VÝ dô :
float max3s(float a, float b, float c) khai báo đối có dạng :
Kiểu đối tên đối 1, kiểu đối tên đối 2, , kiểu đối n tên đối n Thân hàm :
Sau dòng tiêu đề thân hàm Thân hàm nội dung hàm bắt đầu kết thúc dấu { }
(56)Thân hàm sử dụng câu lƯnh return, cã thĨ dïng nhiỊu c©u lƯnh return ë chỗ khác nhau, không sử dụng câu lệnh
Dạng tổng quát :
return [biểu thức];
Giá trị biểu thức câu lệnh return gán cho hàm Ví dụ :
Xét toán : Tìm giá trị lớn ba số mà giá trị mà giá trị chúng đưa vào bàn phÝm
Xây dựng chương trình tổ chức thành hai hàm : Hàm main() hàm max3s Nhiệm vụ hàm max3s tính giá trị lớn ba số đọc vào, giả sử a,b,c Nhiệm vụ hàm main() đọc ba giá trị vào từ bàn phím, dùng hàm max3s để tính trên, đưa kết hình
Chương trình viết sau : #include "stdio.h"
float max3s(float a,float b,float c ); /* Nguyên mẫu hàm*/ main()
{
float x,y,z;
printf("\n Vao ba so x,y,z:"); scanf("%f%f%f",&x&y&z);
printf("\n Max cua ba so x=%8.2f y=%8.2f z=%8.2f la : %8.2f", x,y,z,max3s(x,y,z));
} /* KÕt thóc hµm main*/ float max3s(float a,float b,float c)
{
float max; max=a;
(57)Quy tắc hoạt động hàm :
Mét c¸ch tỉng qu¸t lêi gäi hàm có dạng sau : tên hàm ([Danh sách tham sè thùc])
Số tham số thực tế thay vào danh sách đối phải số tham số hình thức chúng có kiểu tương ứng với
Khi gặp lời gọi hàm bắt đầu thực Nói cách khác, máy gặp lời gọi hàm vị trí chương trình, m áy tạm dời chỗ chuyển đến hàm tương ứng Q trình diễn theo trình tự sau :
CÊp ph¸t bé nhí cho c¸c biÕn cơc bé
Gán giá trị tham số thực cho đối tương ứng Thực câu lệnh thân hàm
Khi gặp câu lệnh return dấu } cuối thân hàm máy xố đối, biến cục khỏi hàm
NÕu trë vỊ tõ mét c©u lƯnh return cã chøa biểu thức giá trị biểu thức gán cho hàm Giá trị hàm sử dụng c¸c biĨu thøc chøa nã
Các tham số thực, đối biến cục :
Do đối biến cục có phạm vi hoạt động hàm nên đối biến cục cần có tên khác
Đối biến cục biến tự động Chúng cấp phát nhớ hàm xét đến bị xố khỏi h àm nên ta khơng thể mang giá trị đối khỏi hàm
Đối biến cục trùng tên với đại lượng ngồi hàm mà khơng gây nhầm lẫn
Khi hàm gọi tới, việc giá trị tham số thực gán cho đối ( ví dụ hàm max3s, tham số thực x,y,z, đối tương ứng a,b,c ) Như đối tham số thực Hàm làm việc đối
Các đối bị biến đổi thân hàm, tham số thực khơng bị thay đổi Chú ý :
Khi hàm khai báo khơng có kiểu trước mặc định kiểu int
(58)Nguyên mẫu hàm thực chất dòng hàm thêm vào dấu ; Tuy nhiên nguyên mẫu bỏ tên đối
Hàm thường có vài đối Ví dụ hàm max3s có ba đối a,b,c ba đối có giá trị float Tuy nhiên, có hàm không đối hà m main
Hàm thường cho ta giá trị Lẽ dĩ nhiên giá trị hàm phụ thuộc vào giá trị i
6.2 Hàm không cho giá trị :
Các hàm không cho giá trị giống thủ tục ( procedure ) ngơn ngữ lập trình PASCAL Trong trường hợp này, k iểu void
Ví dụ hàm tìm giá trị max ba số max3s viết thành thủ tục hiển thị số cực đại ba số sau :
void htmax3s(float a, float b, float c) {
float max; max=a;
if (max<b) max=b; if (max<c) max=c; }
Lóc nµy, hµm main ta gọi hàm htmax3s câu lệnh : htmax3s(x,y,z);
6.3 Hàm đệ qui : 6.3.3 Mở đầu :
C cho phép từ hàm gọi tới hàm khác, mà cịn cho phép từ điểm thân hàm gọi tới hàm Hàm gọi hàm đệ qui
Khi hàm gọi đệ qui đến nó, lần gọi máy tạo tập biến cục hoàn toàn độc lập với tập biến cục tạo lần gọi trước
Để minh hoạ chi tiết điều trên, ta xét ví dụ tính giai thừa số nguyên dương n Khi không dùng phương pháp đệ qui hàm viết sau :
long int gt(int n) /* TÝnh n! víi n>=0*/ {
(59)for (i=1;i<=n;++i) gtphu*=i;
return s; }
Ta nhËn thÊy r»ng n! cã thÓ tÝnh theo c«ng thøc truy håi sau :
n!=1 nÕu n=0
n!=n*(n-1)! nÕu n>0
Hàm tính n! theo phương pháp đệ qui viết sau : long int gtdq(int n)
{
if (n==0 || n==1) return 1; else
return(n*gtdq(n-1)); }
Ta giải thích hoạt động hàm đệ qui sử dụng hàm main : #include "stdio.h"
main() {
printf("\n 3!=%d",gtdq(3)); }
Lần gọi tới hàm gtdq thực từ hàm main() Máy tạo tập biến tự động hàm gtdq Tập ch ỉ gồm đối n Ta gọi đối n tạo lần thứ n thứ Giá trị tham số thực ( số ) gán cho n thứ Lúc biến n thân hàm xem n thứ Do n thứ có giá trị nên điều kiện tốn tử if sai máy lựa chọn câu lệnh else Theo câu lệnh này, máy tính giá trị biểu thức :
n*gtdq(n-1) (*)
Để tính biểu thức trên, máy cần gọi hàm gtdq lần gọi thứ hai thực Máy tạo đối n mới, ta gọi n thứ hai Giá trị củ a n-1 lại đối hàm , truyền cho hàm hiểu n thứ hai, n thứ hai có giá trị Bây giờ, n thứ hai chưa thoả mãn điều kiện if nên máy lại tiếp tục tính biểu thức :
(60)Biểu thức lại gọi hàm gtdq lầ n thứ ba Máy lại tạo đối n lần thứ ba n thứ ba có giá trị Đối n=1 thứ ba lại truyền cho hàm, lúc điều kiện lệnh if thoả mãn, máy thực câu lệnh :
return 1=gtdq(1) (***)
Bắt đầu từ đây, máy thực b a lần khỏi hàm gtdq Lần khỏi hàm thứ ứng với lần vào thứ ba Kết đối n thứ ba giải phóng, hàm gtdq(1) cho giá trị máy trở xét giá trị biểu thức
n*gtdq(1) kết (**)
õy, n n thứ hai có giá trị bằ ng Theo câu lệnh return, máy thực lần khỏi hàm lần thứ hai, đối n thứ hai giải phóng, kết biểu thức (**) có giá trị 2.1 Sau máy trở biểu thức (*) lúc :
n*gtdq(2)=n*2*1
n lại hiểu thứ nhất, có gi trị 3, giá trị biểu thức (*) 3.2.1=6 Chính giá trị sử dụng câu lệnh printf hàm main() nên kết in hình :
3!=6 Chó ý :
Hàm đệ qui so với hàm dùng vịng lặp đơn giản hơn, nhi ên với máy tính dùng hàm đệ qui dùng nhiều nhớ ngăn xếp dẫn đến tràn ngăn xếp Vì gặp tốn mà có cách giải lặp ( khơng dùng đệ qui ) ta nên dùng cách lặp Song tồn tốn gi ải đệ qui
6.3.2 Các tốn dùng đệ qui :
Phương pháp đệ qui thường áp dụng cho tốn phụ thuộc tham số có hai đặc điểm sau :
Bài toán dễ dàng giải số trường hợp riêng ứng với giá trị đặc biệt tham số Người ta thường gọi trường hợp suy biến
Trong trường hợp tổng qt, tốn qui tốn dạng giá trị tham số bị thay đổi Sau số hữu hạn bước biến đổi dệ qui dẫn tới trường hợp suy biến
Bài tốn tính n giai thừa nêu thể rõ nét đặc điểu 6.3.3 Cách xây dựng hàm đệ qui :
(61)if ( trng hp suy bin) {
Trình bày cách giải toán suy biến }
else /* Trường hợp tổng quát */ {
Gọi đệ qui tới hàm ( viết ) với giá trị khác tham số
}
6.3.4 Các ví dụ dùng hàm đệ qui : Ví dụ :
Bài tốn dùng đệ qui tìm USCLN hai số nguyên dương a b
Trong trường hợp suy biến, a=b USCLN a b giá trị chúng Trong trường hợp chung :
uscln(a,b)=uscln(a-b,b) a>b uscln(a,b)=uscln(a,b-a) a<b Ta viết chương trình sau :
#include "stdio.h"
int uscln(int a,int b ); /* Nguyªn mÉu hµm*/ main()
{ int m,n;
printf("\n Nhap cac gia tri cua a va b :"); scanf("%d%d",&m,&n);
printf("\n USCLN cua a=%d va b=%d la :%d",m,m,uscln(m,n)) }
int uscln(int a,int b) {
if (a==b) return a; else
if (a>b)
(62)else
return uscln(a,b-a); }
VÝ dô :
Chương trình đọc vào số in dạng ký tự liên tiếp # include "stdio.h"
# include "conio.h" void prind(int n); main()
{ int a; clrscr(); printf("n="); scanf("%d",&a); prind(a);
getch(); }
void prind(int n) {
int i; if (n<0) { putchar('-'); n=-n; }
if ((i=n/10)!=0) prind(i);
putchar(n%10+'0'); }
(63)C đưa số cách mở rộng ngôn ngữ tiền sử lý macro đơn giản Có hai cách mở rộng #define mà ta học khả bao hàm nội dung file khác vào file dịch
Bao hµm file :
Để dễ dàng xử lý tập #define khai báo ( đối tượng khác ), C đưa cách bao hàm file khác vào file dịch có dạng :
#include "tªn file"
Dịng khai báo thay nội dung file có tên tên file Thơng thường có vài dịng xuất đầu file gốc để gọi vào câu lệnh #define chung khai báo cho biến ngồi Các #include phép lồng Thường #include dùng nhiều chương trình lớn, đảm bảo file gốc cung cấp định nghĩa khai báo biến, tránh lỗi khó chịu việc thiếu khai báo định nghĩa Tất nhiên thay đổi file bao hàm vào file phụ thuộc vào phải dịch lại Phép MACRO :
Định nghĩa có dạng :
#define biu thc [ biểu thức ] gọi tới macro để thay biểu thức (nếu có) cho biểu thức Ví dụ :
#define YES
Macro thay biến YES giá tr ị có nghĩa có chỗ chương trình có xuất biến YES thay giá trị
Phạm vi cho tên định nghĩa #define từ điểm định nghĩa đến cuối file gốc Có thể định nghĩa lại tên định nghĩa sử dụng đ ịnh nghĩa khác trước Phép khơng thực cho xâu dấu nháy, ví dụ YES tên định nghĩa khơng có việc thay thực đoạn lệnh có "YES"
Vì việc thiết lập #define bước chuẩn bị khơng phải phần chương trình biên dịch nên có hạn chế văn phạm việc phải định nghĩa Chẳng hạn người lập trình ưa thích PASCAL định nghĩa :
(64)sau viết đoạn chương trình : if (i>0) then
begin a=i; end;
Ta định nghĩa macro có đối, văn thay phụ thuộc vào cách gọi tới macro
VÝ dô :
Định nghĩa macro gọi max sau : #define max(a,b) ((a)>(b) ?(a):(b)) ViƯc sư dơng :
x=max(p+q,r+s); tương đương với :
x=((p+q)>(r+s) ? (p+q):(r+s));
Như ta có hàm tính cực đại viết dịng Chừng đối cịn giữ tính qn macro có giá trị với kiểu liệu, khơng cần phải có loại hàm max khác cho kiểu liệu khác phải có đối cho hàm
Tất nhiên ta kiểm tra lại việc mở rộng hàm max trên, ta thấy gây số bẫy Biểu thức tính lại hai lần điều khơng tốt gây hiệu phụ kiểu lời gọi hàm toán tử tăng Cần phải thận trọng dùng thêm dấu ngoặc để đảm bảo trật tự tính tốn Tuy vậy, macro có giá trị
Chó ý :
Không viết dấu cách tên macro với dấu mở ngoặc bao quanh danh sách đối Ví dụ :
Xét chương trình sau : main()
{
(65)y=10*5; z=x+y; z=x+y+6; z=5*x+y; z=5*(x+y); z=5*((x)+(y)); printf("Z=%d",z); getch();
return; }
Chương trình sử dụng MACRO sau : #define BEGIN {
#define END } #define INTEGER int #define NB 10 #define LIMIT NB*5 #define SUMXY x+y #define SUM1 (x+y) #define SUM2 ((x)+(y)) main()
BEGIN
INTEGER x,y,z; x=5;
y=LIMIT; z=SUMXY; z=5*SUMXY; z=5*SUM1; z=5*SUM2;
printf("\n Z=%d",z); getch();
(66)Chương 7 Con trỏ
Con trỏ biến chứa địa biến khác Con trỏ sử dụng nhiều C, phần chúng cách để biểu diễn tính tốn, phần chúng thường làm cho chương trình ngắn gọn có hiệu cách khác
Con trỏ bị coi có hại chẳng lệnh goto cách sử dụng chúng tạo chương trình khó hiểu Điều chắn người ta sử dụng chúng cách lôn xộn tạo trỏ trỏ đến trước
7.1 Con trỏ địa :
Vì trỏ chứa địa đối tượng nên xâm nhập vào đối tượng gián tiếp qua trỏ Giả sử x biến kiểu int, giả sử px trỏ tạo theo cách Phép tốn ngơi & cho địa đối tượng, nê n câu lệnh :
px=&x;
sẽ gán địa biến x cho trỏ px, px gọi " trỏ tới biến x " Phép toán & áp dụng cho biến phần tử bảng, kết cấu kiểu &(x+1) &3 không hợp lệ Lấy đại biến register sai
Phép tốn ngơi * coi tốn hạng đại cần xét thâm nhập tới địa để lấy nội dung Nếu biến y có kiểu int thỡ thỡ lnh :
y=*px; gán giá trị cđa biÕn mµ trá px trá tíi VËy d·y lƯnh :
px=&x; y=*px;
sẽ gán giá trị x cho y nh lÖnh : y=x;
Các khai báo cho biến trỏ có dạng : tªn kiĨu *tªn trá VÝ dơ :
(67)Trong khai báo ta ngụ ý nói cách tượng trưng, tổ hợp *px có kiểu int, tức px xuất ngữ cảnh *px tương đương với biến có kiểu int
Con trá cã thể xuất biểu thức Chẳng hạn, px trỏ tới số nguyên x *px xuất ngữ cảnh mà x cã thĨ xt h iƯn
VÝ dơ :
LÖnh y=*px+1;
sẽ đặt y lớn x đơn vị Lệnh printf("%d",*px); in giá trị x Lệnh :
d=sqrt((double) *px);
sẽ gán cho biến d bậc hai x, giá trị bị buộc phải chuyển sang double trước chuyền cho sqrt ( cách dùng hàm sqrt )
Trong c¸c biĨu thøc kiĨu nh : y=*px+1;
phép toán * & có mức ưu tiên cao phép toán số học, biểu thức lấy bất ký giá trị mà px trỏ tới, cộng với gán cho y
Con trá cịng cã thĨ xt hiƯn bªn vÕ tr¸i cđa phÐp g¸n NÕu px trá tíi x th× sau lƯnh : *px=0;
x có giá trị Cũng tương tự lệnh: *px+=1;
(*px)++;
sẽ tăng giá trị x lên dơn vị
Cỏc du ngoc n cõu lnh cuối cần thiết , khơng biểu thức tăng px thay cho tăng biến mà trỏ tới phép tốn ngơi * ++ tính từ phải sang trái
Cuối cùng, trỏ biến nên ta có thao tác chúng biến khác Nếu py trỏ int lệnh :
py=px;
(68)Trong C có mối quan hệ chặt chẽ trỏ mảng : phần tử mảng xác định nhờ số thơng qua trỏ
7.2.1.Phép tốn lấy địa ch :
Phép toán áp dụng cho phần tử mảng chiều Giả sử ta cã khai b¸o : double b[20];
Khi phép toán : &b[9]
sẽ cho địa phần tử b[9] 7.2.2 Tên mảng địa :
Khi khai b¸o : float a[10];
máy bố trí bố trí cho mảng a mười khoảng nhớ liên tiếp, khoảng nhớ byte Như vậy, biết địa phần tử mảng a, ta dễ dàng suy địa phần tử khác mảng
Víi C ta cã :
a tương đương với &a[0] a+i tương đương với &a[i ] *(a+i) tương đương với a[i]
7.2.3 Con trá trá tíi phần tử mảng chiều : Khi trỏ pa trỏ tới phần tử a[k] :
pa+i trỏ tới phần tử thứ i sau a[k], có nghĩa trỏ tới a[k+i] pa-i trỏ tới phần tử thứ i trước a[k], có nghĩa trỏ tới a[k-i] *(pa+i) tương đương với pa[i]
Nh vËy, sau hai câu lệnh : float a[20],*p; p=a;
thì c¸ch viÕt sau cã t¸c dơng nh : a[i] *(a+i) p[i] *(p+i) VÝ dô :
(69)C¸ch 1:
#include "stdio.h" main()
{
float a[4],tong; int i;
for (i=0;i<4;++i) {
printf("\n a[%d]=",i); scanf("%f",a+i); }
tong=0;
for (i=0;i<4;++i) tong+=a[i];
printf("\n Tong cac phan tu mang la :%8.2f ",tong); }
C¸ch :
#include "stdio.h" main()
{
float a[4],tong, *troa; int i;
troa=a;
for (i=0;i<4;++i) {
printf("\n a[%d]=",i); scanf("%f",&troa[i]); }
tong=0;
for (i=0;i<4;++i) tong+=troa[i];
(70)} C¸ch :
#include "stdio.h" main()
{
float a[4],tong,*troa; int i;
troa=a;
for (i=0;i<4;++i) {
printf("\n a[%d]=",i); scanf("%f",troa+i); }
tong=0;
for (i=0;i<4;++i)
tong+=*(troa+i);
printf("\n Tong cac phan tu mang la :%8.2f ",tong); }
Chó ý :
Mảng chiều trỏ tương ứng phải kiểu 7.2.4 Mảng, trỏ xâu ký tự :
Như ta biết trước đây, xâu ký tự dãy ký tự đặt hai dấu nháy kép, ví dụ :
"Viet nam"
Khi gặp xâu ký tự, máy cấp phát khoảng nhớ cho mảng kiểu char đủ lớn để chứa ký tự xâu chứa thêm ký tự ' \0' ký tự dùng làm ký tự kết thúc xâu ký tự Mỗi ký tự xâu chứa phần tử mảng
Cũng giống tên mảng, xâu ký tự m ột hàng địa biểu thị địa đầu mảng chứa Vì ta khai báo biến xau trỏ kiểu char :
(71)xau="Ha noi"
là hồn tồn có nghĩa Sau thực câu lệnh trỏ xau có địa đầu mảng (kiểu char) chứa xâu ký tự bên phải Khi câu lệnh :
puts("Ha noi"); puts(xau);
sÏ cã tác dụng cho lên hình dòng chữ Ha noi.
Mng kiu char thng dựng để chứa dãy ký tự đọc vào nhớ Ví dụ, để nạp từ bàn phím tên người ta dùng mảng kiểu char với độ dài 25, ta sử dụng câu lệnh sau :
char ten[25];
printf("\n Ho ten :"); gets(ten);
B©y ta xem mảng kiểu char trỏ kiểu char có giống khác Để thấy khác chúng, ta đưa sù so s¸nh sau :
char *xau, ten[15]; ten="Ha noi" gets(xau);
Các câu lệnh không hợp lệ Câu lệnh thứ hai sai chỗ : ten địa ta gán địa cho địa khác Câu lệnh thứ ba kh ông thực được, mục đích câu lệnh đọc từ bàn phím dãy ký tự lưu vào vùng nhớ mà trỏ xau trỏ tới Song nội dung trỏ xau chưa xác định Nếu trỏ xau trỏ tới vùng nhớ câu lệnh hồn tồn có ý nghĩa Ch ẳng hạn sau thực câu lệnh :
xau=ten; cách viết :
gets(ten) ; v gets(xau); u có tác dụng
7.3 Con trá vµ m¶ng nhiỊu chiỊu :
Việc sử lý mảng nhiều chiều phức tạp so với mảng chiều Không phải qui tắc với mảng chiều áp dụng cho mảng nhiều chiều
7.3.1.Phép lấy địa :
(72)Thủ thuật đọc từ bàn phím phần tử mảng hai chiều dùng lệnh scanf :
Chương trình đọc vào số liệu cho ma trận hai chiều thực thông qua việc đọc vào biến trung gian, đọc giá trị chứa tạm vào biến trung gian sau ta gán biến cho phần tử mảng:
#include "stdio.h" main()
{
float a[2][3], tg; int i,j;
for (i=0;i<2;++i) for (j=0;j<2;++j) {
printf("\n a[%d][%d]=",i,j); scanf("%8.2f",&tg);
a[i][j]=tg; }
}
7.3.2 Phép cộng địa mảng hai chiều:
Giả sử ta có mảng hai chiều a[2][3] có phần tử úng với sáu địa liên tiếp nhớ xếp theo thứ tự sau :
Phần tử a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
Địa chØ
Tên mảng a biểu thị địa mảng Phép cộng địa thực sau : C coi mảng hai chiều mảng ( chiều ) mảng, khai báo
float a[2][3];
thì a mảng mà phần tử c đa nã lµ mét d·y sè thùc ( hàng mảng ) Vì :
a trỏ phần tử thứ mảng : phần tử a[0][0]
(73)7.3.3 Con trỏ mảng hai chiÒu :
Để duyệt phần tử củ a mảng hai chiều ta dùng trỏ minh hoạ ví dụ sau :
float *pa,a[2][3]; pa=(float*)a; lúc :
pa trá tíi a[0][0] pa+1 trá tíi a[0][1] pa+2 trá tíi a[0][2] pa+3 trá tíi a[1][0] pa+4 trá tíi a[1][1] pa+5 trá tíi a[1][2] VÝ dơ :
Dùng trỏ để vào số liệu cho mảng hai chiều Cách :
#include "stdio.h" main()
{
float a[2][3],*pa; int i;
pa=(float*)a; for (i=0;i<6;++i) scanf("%f",pa+i); }
C¸ch :
#include "stdio.h" main()
{
float a[2][3],*pa; int i;
(74)scanf("%f",(float*)a+i); }
7.4 Kiểu trỏ, kiểu địa chỉ, phép toán trỏ : 7.4.1 Kiểu trỏ kiểu địa :
Con trỏ dùng để lưu địa Mỗi kiểu địa cần có kiểu trỏ tương ứng Phép gán địa cho trỏ thực kiểu địa phù hợp với kiểu trỏ
VÝ dô theo khai báo :
float a[20][30],*pa,(*pm)[30]; :
pa trá float
pm trỏ kiểu float [30] a địa kiểu float [30] Vì phộp gỏn :
pa=a;
là không hợp lệ Nhng phÐp g¸n : pm=a;
7.4.2 C¸c phÐp to¸n trªn trá:
Có phép tốn liên quan đến trỏ đại : Phép gán
Phép tăng giảm địa Phép truy cập nhớ Phép so sánh
PhÐp g¸n :
PhÐp g¸n chØ thùc hiƯn víi c¸c trá cïng kiĨu Muốn gán trỏ khác kiểu phải dùng phép Ðp kiĨu nh vÝ dơ sau :
(75)Để minh hoạ chi tiết cho phép toán này, ta xét ví dụ sau : Các câu lệnh :
float x[30],*px; px=&x[10];
cho trỏ px trỏ float trỏ tới phần tử x[10] Kiểu địa float kiểu địa byte, nên phép tăng giảm địa thực byte Vì :
px+i trá tíi phÇn tư x[10+i] px-i trá tíi phÇn tư x[10-i] XÐt vÝ dơ khác :
Giả sử ta khai báo : float b[40][50];
Khai báo cho ta mảng b gồm dòng 50 phần tử thực Kiểu địa b 50*4=200 byte
Do vËy :
b trỏ tới đầu dòng thứ ( phần tử b[0][0]) b+1 trỏ tới đầu dòng thứ hai ( phần tử b[1][0])
b+i trỏ tới đầu dòng thứ i ( phÇn tư b[i][0]) PhÐp truy cËp bé nhí :
Con trá float truy nhËp tíi byte, trá int truy nhËp byte, trá char truy nhập byte Giả sử ta có cá khai b¸o :
float *pf; int *pi; char *pc; Khi :
Nếu trỏ pi trỏ đến byte thứ 100 *pf biểu thị vùng nhớ byte liên tiếp từ byte 100 đến 103
Nếu trỏ pi trỏ đến byte thứ 100 *pi biểu thị vùng nhớ byte liên tiếp từ byte 100 đến 101
(76)PhÐp so s¸nh :
Cho phÐp so s¸nh c¸c trá c ïng kiĨu, vÝ dụ p1 p2 trỏ kiĨu th× nÕu :
p1<p2 địa p1 trỏ tới thấp địa p2 trỏ tới p1=p2 địa p1 trỏ tới địa p2 trỏ tới p1>p2 địa p1 trỏ tới cao địa p2 trỏ tới Ví dụ :
VÝ dơ :
Đoạn chương trình tính tổng số thực dùng phép so sánh trỏ : float a[100],*p,*pcuoi,tong=0.0;
int n;
pcuoi=a+n-1; /* Địa chØ cuèi d·y*/ for (p=a;p<=pcuoi;++p)
s+=*p; VÝ dô :
Dùng trỏ char để tách byte biến nguyên, ta làm sau : Giả sử ta có lệnh :
unsigned int n=0xABCD; /* Sè nguyªn hƯ 16*/ char *pc;
pc=(char*)(&n); Khi :
*pc=0xAB (byte thø nhÊt cña n) *pc+1=0xCD (byte thø hai cđa n) 7.4.3 Con trá kiĨu void :
Con trỏ kiểu void khai báo nh sau : void *tªn_con_trá;
Đây trỏ đặc biệt, trỏ khơng kiểu, nhận kiểu Chẳng hạn câu lệnh sau hợp lệ :
(77)float a[20][30]; pa=a;
Con trỏ void thường dùng làm đối để nhận địa kiểu từ tham số t hực Trong thân hàm phải dùng phép chuyển đổi kiểu để chuyển sang dạng địa cần sử lý
Chó ý :
Các phép toán tăng giảm địa chỉ, so sánh truy cập nhớ không dùng trỏ void
VÝ dô :
ViÕt hàm thực công ma trận :
void congmt(void *a,void *b,void *c,int N,int N, int m); {
float *pa,*pb,*pc; int i,j;
pa=(float*)a; pb=(float*)b; pc=(float*)c; for (i=1;i<m;++i) for (j=1;j<m;++j)
*(pc+i*N+j)=*(pa+i*N+j)+*(pb+i*N+j); }
Vì đối trỏ void nên có th ể nhận địa ma trận lời gọi hàm Tuy nhiên ta sử dụng trực tiếp đối trỏ void thân hàm mà phải chuyển kiểu chúng sang thành float
7.5 M¶ng trá :
Mảng trỏ mở rộng khái niệm trỏ Mảng trỏ mảng mà phần tử chứa địa Cũng giống trỏ, mảng trỏ có nhiều kiểu : Mỗi phần tử mảng trỏ kiểu int chứa địa kiểu int Tương tự cho mảng trỏ kiểu khỏc
(78)Kiểu *Tên_mảng_con_trỏ[N];
Trong ú Kiểu int, float, double, char cịn Tên_mảng_con_trỏ tên mảng, N số ngun xác định độ lớn mảng
Khi gỈp khai báo trên, máy cấp phát N khoảng nhớ liên tiếp cho N phần tử mảng Tên_mảng_con_trỏ
VÝ dơ : LƯnh :
double *pa[100];
Khai báo mảng trỏ kiểu double gồm 100 phần tử Mỗi phần tử pa[i] dùng để lưu trữ địa kiểu double
Chó ý :
Bản thân mảng trỏ không dùng để lư u trữ số liệu Tuy nhiên mảng trỏ cho phép sử dụng mảng khác để lưu trữ số liệu cách có hiệu theo cách : chia mảng thành phần ghi nhớ địa đầu phần vào phần tử mảng trỏ
Trước sử dụng mảng trỏ ta cần gán cho phần tử giá trị Giá trị phải giá trị biến phần tử mảng Các phần tử mảng trỏ kiểu char khởi đầu xâu ký tự
VÝ dơ :
Xét tổ lao động có 10 người, mã người chín h số thứ tự Ta lập hàm để biết mã số nhân viên xác định họ tên nhân viên
#include "stdio.h" #include "ctype.h" void tim(int code); main()
{
int i;
tt:printf("\n Tim nguoi co so TT la :"); scanf("%d",&i);
tim(i);
(79)goto tt; }
void tim(int code); {
static char *list[]= {
"Khong co so thu tu " " Nguyen Van Toan" "Huynh Tuan Nghia" "Le Hong Son" "Tran Quang Tung" "Chu Thanh Tu" "Mac Thi Nga" "Hoang Hung" "Pham Trong Ha" "Vu Trung Duc" "Mai Trong Quat" };
printf("\n\n Ma so : %d",code); printf(": %s",());
}
7.6 Con trá tới hàm :
7.6.1 Cách khai báo trỏ hàm mảng trỏ hàm : Ta trình bày quy tắc khai báo thông qua ví dụ : VÝ dơ 1:
C©u lƯnh :
float (*f)(float),(*mf[50])(int); Để khai báo :
f l trỏ hàm kiểu float có đối float
(80)C©u lƯnh :
double (*g)(int, double),(*mg[30])(double, float); §Ĩ khai b¸o :
g trỏ hàm kiểu double có đối kiểu int double
mg mảng trỏ hàm kiểu double có đối kiểu double float ( có 30 phần tử ) 7.6.2 Tác dụng trỏ hàm :
Con trỏ hàm dùng để chứa địa hàm Muốn ta thực phép gán tên hàm cho trỏ hàm Để phép gán có ý nghĩa kiểu hàm kiểu trỏ phải tương thích Sau phép gán, ta dùng tên trỏ hàm thay cho tên hàm
VÝ dô 1:
#include "stdio.h"
double fmax(double x, double y ) /* TÝnh max x,y */ {
return(x>y ? x:y); }
double (*pf)(double,double)=fmax; /*Khai báo gán tên hàm cho trá hµm */ main() /* Sư dơng trá hµm*/
{
printf("\n max=%f",pf(5.0,9.6)); }
VÝ dô 2:
#include "stdio.h"
double fmax(double x, double y ) /* TÝnh max x,y */ {
return(x>y ? x:y); }
double (*pf)(double,double); /* Khai b¸o trá hµm*/ main() /* Sư dơng trá hµm*/
(81)pf=fmax;
printf("\n max=%f",pf(5.0,9.6)); }
7.6.3 §èi cđa trá hµm :
C cho phép thiết kế hàm mà tham số thực lời gọi tới lại tên hàm khác Khi tham số hình thức tương ứng phải trỏ hàm
Cách dùng trỏ hàm thân hàm : Nếu đối khai báo :
double (*f)(double, int);
thì thân hàm ta dùng cách viết sau để xác định giá trị hàm ( trỏ f trỏ tới ) :
f(x,m) hc (f)(x,m) hc (*f)(x,m) ë x biến kiểu double m biến kiĨu int VÝ dơ :
Dùng mảng trỏ để lập bảng giá trị cho hà m : x*x, sin(x), cos(x), exp(x) sqrt(x) Biến x chay từ 1.0 đến 10.0 theo bước 0.5
#include "stdio.h" #include "math.h"
double bp(double x) /* Hµm tÝnh x*x */ {
return x*x; }
main() {
int i,j;
double x=1.0;
(82)ham f[6]; /* Khai bao mảng trỏ hàm*/
/* Có thĨ khai b¸o nh sau double (*f[6](double)*/ f[1]=bp; f[2]=sin; f[3]=cos; f[4]=exp; f[5]=sqrt; /* Gán tên hàm cho phần tử mẩng trỏ hàm */ while (x<=10.0) /* Lập bảng giá trị */
{
printf("\n"); for (j=1;j<=5;++j)
printf("%10.2f ",f[j](x)); x+=0.5;
(83)Chương 8 Cấu trúc
Cấu trúc tập hợp nhiều biến, chúng khác kiểu nhau, nhóm lại tên để tiện sử lý Cấu trúc gọi ghi số ngôn ngữ khác, chẳng hạn PASCAL
Cấu trúc giúp cho việc tổ chức liệu phức tạp, đặc biệt chương trình lớn nhiều tình chúng cho phép nhóm biến có liên quan lại để xử lý đơn vị thay thực thể tách biệt
Một ví dụ đề cập nhiều đến cấu trúc phiếu ghi lương, nhân viên mơ tả tập thuộc tính chẳng hạn : tên, địa chỉ, lương, phụ cấp vv số thuộc tính lại cấu trúc chứa nhiều thành phần : Tên ( Họ, đệm, tên ), Địa ( Phố, số nhà ) vv
Trong chương minh hoạ cách sử dụng cấu trúc chương trình
8.1 KiĨu cÊu tróc :
Khi xây dựng cấu trúc, ta cần mô tả kiểu Điều tương tự việc phải thiết kế kiểu nhà trước ta xây dựng nhà thực địa điểm khác Công việc định nghĩa kiểu cấu trúc bao gồm việc nêu tên kiểu cấu trúc thành phần theo mẫu sau :
struct tên_kiểu _cấu_trúc {
Khai báo thành phần cấu trúc (1) };
Trong ú :
struct từ khoá
tên_kiểu _cấu_trúc tên người lập trình tự đặt theo qui tắc đặt tên nêu chương
Thành phần cấu trúc : biến, mảng, cấu trúc khác định nghĩa trước vv Ví dụ :
(84)Đoạn chương trình : struct {
int ngaythu; char thang[12]; int nam; };
m« tả kiểu cấu trúc có tên ngay gồm có ba thành phần : Biến nguyên ngaythu, mảng thang, biến nguyênnam
Ví dụ 2:
on chng trình : struct nhancong
{
char ten[15]; char diachi[20] double bacluong; struc ngaysinh;
struc ngaybatdaucongtac; };
tạo kiểu cấu trúc có tên nhanconggồm có năm thành phần Ba thành phần đầu khơng có cần nói thêm Chỉ có hai thành phần lại cấu trúc ngaysinh ngaybatdaucongtac xây dựng theo cấu trúc ngay định nghĩa vớ d
Định nghĩa cấu trúc typedef :
Có thể dùng tốn tử typedef để định nghĩa kiểu cấu trúc ngay vànhancong sau :
typedef struct {
(85)} ngay; typedef struct
{
char ten[15]; char diachi[20] double bacluong; struc ngaysinh;
struc ngaybatdaucongtac; } nhancong;
8.2 Khai báo theomột kiểu cấu trúc định nghĩa :
Xây dựng cấu trúc thực theo kiểu khai báo trước Vấn đề hồn tồn giống việc khai báo biến mảng Giả sử ta có kiểu cấu trúc ngay nhancong mục Khi ta khai báo :
VÝ dô :
struct ngaydi, ngayden;
sẽ cho ta hai cấu trúc với tên ngaydi vàngayden Cả hai cấu trúc xây dựng theo cấu trúc kiểungay
VÝ dô :
struct nhancong nhom1,nhom2;
sẽ cho ta hai cấu trúc với tên nhom1 nhom2 Cả hai cấu trúc xây dựng theo cấu trúc kiểunhancong
Nh vËy, mét c¸ch tỉng qu¸t, viƯc khai b¸o cÊu trúc thực th eo mẫu sau : Cách :
struct tên_kiểu_cấu_trúc_đã_khai_báo danh_sách_tên_các_cấu_trúc; (2) Chú ý :
(86)Việc khai báo thực h iện đồng thời với việc định nghĩa kiểu cấu trúc Muốn vậy, cần đặt danh sách tên biến cấu trúc cần khai báo sau dấu } (* )
Nói cách khác, để vừa khai báo kiểu vừa khai báo biến ta dùng cách sau : Cách :
struct tªn_kiĨu_cÊu_tróc {
Các thành phần cấu trúc (3) } danh_sách_tên_các_cấu_trúc;
VÝ dô : VÝ dô :
struct {
int ngaythu; char thang[12]; int nam;
} ngaydi,ngayden; VÝ dô :
struct nhancong {
char ten[15]; char diachi[20]; double bacluong; struc ngaysinh;
struc ngaybatdaucongtac; } nhom1,nhom2;
Khi vừa định nghĩa kiểu cấu trúc vừa khai báo cấu trúc ví dụ trên, ta khơng thể khơng cần đến tên kiểu cấu trúc Nói cách khác cấu trúc khai báo theo cách sau :
(87){
Các thành phần cấu trúc (4) } danh_sách_tên_các_cấu_trúc;
Ví dụ :
struct {
int ngaythu; char thang[12]; int nam;
} ngaydi,ngayden;
Sự khác cách khai báo cấu trúc (3) (4) chỗ : Với (3) ta vừa khai báo kiểu cấu trúc vừa khai báo cấu trúc, dùng kiểu cấu trúc để khai báo cho cấu trúc khác (2), (4) khai báo đ ược cấu trúc
Chó ý :
Nếu dùng từ khố typedef để định nghĩa kiểu cấu trúc mục 8.1 khai báo cấu trúc ta không cần dùng từ khoá struct, cần dùng tên kiểu
Ví dụ kiểu cấu trúc ngay khai báo typedef 8.1 khai báo cấu trúc làngaydivàngaydencó kiểungayta dùng dòng lệnh sau :
ngay ngaydi,ngayden; 8.3 Truy nhập đến thành phần cấu trúc :
Ta quen với việc sử dụng biến, phần tử mảng tên mảng câu lệnh Trên ta đề cập đến thành phần cấu trúc biến mảng Việc xử lý cấu trúc phải thực thông qua thành phần
Để truy cập đến thành phần ( biến mảng ) cấu trúc ta sử dụng cỏch vit sau :
tên_cấu_trúc.tên_thành_phần
tên_cấu_trúc.tên_cấu_trúc.tên_thành_phần
(88)
C¸ch viÕt thø nhÊt nh sử dụng biến mảng thành phÇn trùc ti Õp cđa mét cÊu tróc VÝ dơ biến ngaythu, biến nam mảng thang thành phần trực tiếp cấu trúc ngaydi, ngayden Các biến bacluong, mảng ten, diachi thành phần trực tiếp cấu trúc nhancong
Các cách viết lại trê n sử dụng biến mảng thành phần trực tiếp cấu trúc mà thân cấu trúc lại thành phần cấu trúc lớn
Ví dụ :
Ta xét phép toán thành phần cấu trúc nhom1, nhom2: Câu lệnh :
printf("%s",nhom1.ten); đưa lên hình tên nhom1
C©u lƯnh :
tongluong=nhom1.bacluong+nhom2.bacluong;
sẽ gán tổng lương nhom1 vànhom2 gán cho biến tongluong Câu lnh :
printf("%d",nhom1.ngaysinh.ten); đưa lên hình ngày sinh cđa nhom1
C©u lƯnh :
printf("%d",nhom1 ngaybatdaucongtac.nam); đưa lên hình ngày bắt đầu công tác cđa nhom1
Chó ý :
Có thể sử dụng phép toán lấy địa thành phần cấu trúc để nhập số liệu trực tiếp vào thành phần cấu trúc Ví dụ ta viết :
scanf("%d",&nhom1 ngaybatdaucongtac.nam);
Nhưng thành phần khơng ngun, việc làm dẫn đến treo máy Vì nên nhập số liệu vào biến trung gian sau gán cho thành phn ca cu trỳc
Cách làm sau : int year;
(89)nhom1 ngaybatdaucongtac.nam=year;
Để tránh dài dòng làm việc với thành phÇn cÊu tróc ta cã thĨ dïng lƯnh #define VÝ dụ câu lênh scanf ví dụ trên, ta cã thÓ viÕt nh sau :
#define p nhom1 ngaybatdaucongtac
scanf("%d",&p.nam); VÝ dơ :
Gi¶ sư ta lập trình quản lý thông tin cán Giả sử liệu cán gồm : Ngày tháng năm sinh
Ngy thỏng nm vào quan Bậc lương
Yêu cầu viết chương trình để :
X©y dùng cÊu trúc sở liệu cho cán Vào sè lƯu cđa mét c¸n bé
Đưa số liệu máy in Chương trình viết sau : #include "stdio.h"
typedef struct {
int ngay; char thang[10]; int nam; } date;
typedef struct {
date ngaysinh; date ngayvaocq; float luong; } canbo;
main() {
(90)printf("\n Sinh : "); scanf("%d",&p.ngaysinh.ngay); printf("\n Thang : ");
scanf("%d",&p.ngaysinh.thang); printf("\n Nam : ");
scanf("%d",&p.ngaysinh.nam); printf("\n Vao co quan : "); scanf("%d",&p.ngayvaocq.ngay); printf("\n Thang : ");
scanf("%d",&p.ngayvaocq.thang); printf("\n Nam : ");
scanf("%d",&p.ngayvaocq.nam); printf("\n Luong : ");
scanf("%d",&p.luong);
fprintf(stdprn,"\n Ngay sinh:%d%s%d",p.ngaysinh.ngay,p.ngaysinh.thang, p.ngaysinh.nam);
fprintf(stdprn,"\n Ngay vao co quan:%d%s%d",p.ngayvaocq.ngay, p.ngayvaocq.thang,p.ngayvaocq.nam);
fprintf(stdprn,"\n Luong : %8.2f",p.luong); }
8.4 M¶ng cÊu tróc :
Như đề cập chương trước, sử dụng kiểu giá trị ( v í dụ kiểu int ) ta khai báo biến mảng kiểu Ví dụ khai báo :
int a,b,c[10];
cho ta hai biến nguyên a,b mảng nguyên c có 10 phần tử
Hon ton tương tự : ta sử dụng kiểu cấu trúc mô tả để kha i báo cấu trúc mảng cấu trúc
C¸ch khai báo mảng cấu trúc :
struct tờn_kiu_cu_trỳc_ó_nh_ngha tờn_mng_cu_trỳc[s phần tử mảng]; Ví dụ :
VÝ dơ :
(91)struct canbo cb1,cb2,nhom1[10],nhom2[7]; sÏ cho :
Hai biÕn cÊu tróc cb1 vµ cb2
Hai mảng cấu trúc nhom1 co 10 phần tử nhom2 có phần tử phần tử cđa hai nhãm nµy cã kiĨu canbo
VÝ dơ :
Đoạn chương trình sau tính tổng lương cho phần tử n hóm 1: double tongluong=0;
for (i=0;i<10;++i)
tongluong+=nhom1[i].luong; Chó ý :
Khơng cho phép sử dụng phép toán lấy địa thành phần mảng cấu trúc khác kiểu nguyên Chẳng hạn không cho phép sử dụng câu lệnh sau :
scanf("%f",&nhom1[5].luong);
Trong trường hợp ta dùng biến trung gian 8.5 Khởi đầu cấu trúc :
Có thể khởi đầu cho cấu trúc ngoài, cấu trúc tĩnh, mảng cấu trúc mảng cÊu tróc tÜnh
8.6 PhÐp g¸n cÊu tróc :
Có thể thực phép gán biế n phần tử mảng cấu trúc kiểu sau : G¸n hai biÕn cÊu tróc cho
Gán biến cấu trúc cho phần tử mảng cấu trúc Gán phần tử mảng cấu trúc cho biến cấu trúc Gán hai phần tử mảng cấu tróc cho
Mỗi phép gán tương đương với dãy phép gán thành phần tương ứng Ví dụ :
(92)struct thisinh {
char ht[25]; float td; } tg,ts[100]; for (i=1;i<=n-1;++i) for (j=1;j<=n;++j)
if (ts[i].td<ts[j].td) {
tg=ts[i]; ts[i]=ts[j]; ts[j]=tg; }
8.7 Con trỏ cấu trúc địa cấu trúc : 8.7.1 Con trỏ địa :
Ta xÐt vÝ dô sau : struct
{
int ngaythu; char thang[10]; int nam; };
struct nhancong {
char ten[20]; char diachi[25]; double bacluong; struct ngaysinh; };
NÕu khai b¸o :
struct nhancong *p,*p1,*p2,nc1,nc2,ds[100]; ta cã :
(93)nc1, nc2 biến cấu trúc ds mảng cấu trúc
Con tr cu trỳc dựng để lưu trữ địa biến cấu trúc mảng cấu trúc Ví dụ :
p1=&nc1; /* Gửi địa nc1 vào p1 */ p2=&ds[4]; /* Gửi địa ds[4] vào p2 */ p=ds; /* Gửi địa ds[0] vào p */ 8.7.2 Truy nhập qua trỏ:
Có thể truy nhập đến thành phần thơng qua trỏ theo hai cách sau : Cỏch mt :
Tên_con_trỏ->Tên_thành_phần Cách hai :
(*Tên_con_trỏ).Tên_thành_phần VÝ dô :
nc1.ngaysinh.nam p1-> ngaysinh.nam ds[4].ngaysinh.thang (*p2) ngaysinh.thang 8.7.3 Phép gán qua trỏ: Giả sử ta gán :
p1=&nc1; p2=&ds[4]; Khi dùng :
*p1 thay cho nc1 *p2 thay cho ds[4] Tøc lµ viÕt:
(94)ds[5]=*p1; *p2=nc2; 8.7.4 Phép cộng địa : Sau phép gán :
p=ds; p2=&ds[4];
thì p trỏ thới ds[[0]] p2 trỏ tới ds[4] Ta dùng phép cộng, trừ địa để làm cho p p2 trỏ tới thành phần khác
VÝ dơ :
Sau c¸c lƯnh : p=p+10; p2=p2-4;
thì p trỏ tới ds[10] p2 trỏ tới ds[0] 8.7.5 Con trỏ mảng :
Gi s trỏ p trỏ tới đầu mảng ds, :
Ta truy nhập tới thành phần cấu trúc cách sau : + ds[i].thành_phần ds[i].ngaysinh.nam
+ p[i].thành_phần p[i].ngaysinh.nam + (p+i)->thành_phần (p+i)->ngaysinh.nam
Khi ta sử dụng cấu trúc cách viết sau tương đương :
ds[i] p[i] *(p+i)
8.8 Cấu trúc tự trỏ danh sách liªn kÕt :
Khi ta lập chương trình quản lý mà thân số biến (cấu trúc) chưa biết trước, ta sử dụng mảng ( cấp phát nhớ tĩnh ) ta ph ải sử dụng số phần tử tối đa Như có nhiều vùng nhớ cấp phát mà khơng dùng đến Lúc ta có cách để cấp phát nhớ động Số vùng nhớ cấp đủ số biến cần dùng
(95)VÝ dô :
Các cách để định nghĩa cấu trúc tự trỏ person: Cách :
typedef struct pp {
char ht[20]; char qq[25]; int tuoi; struct pp *tiep; } person;
C¸ch :
typedef struct pp person struct pp
{
char ht[20]; char qq[25]; int tuoi; person *tiep; };
C¸ch : struct pp {
char ht[20]; char qq[25]; int tuoi; struct pp *tiep; };
typedef pp person;
(96) Biết địa cấu trúc đầu lưu trữ trỏ
Trong cấu trúc ( trừ cấu trúc cuối ) chứa địa cấu trúc tiếp sau danh sách
CÊu tróc cuèi chøa h»ng NULL VÝ dô :
Với danh sách này, ta từ cấu trúc đầu đến cấu trúc cuối theo chiều từ xuống
Nhóm cấu trúc móc nối theo chiều ngược có tính chất sau : Biết địa cấu trúc cuối
Trong cấu trúc ( trừ cấu trúc đầu ) địa ch ỉ cấu trúc trước Cấu trúc đầu chứa NULL
Với danh sách này, ta từ cấu trúc cuối lên cấu trúc đầu theo chiều từ lên Ngồi ra, ta xây dựng danh sách mà phần tử chứa hai địa cấu trúc trước cấu trúc sau Với loại danh sách này, ta truy nhập theo hai chiều
Khi làm việc với danh sách móc nối, ta thường phải tiến hành công việc sau sau :
( Gi¶ sư ta cã trá p, trỏpdau cấu trúc đầu danh sách, trỏ tiep thành phần trỏ cấu trúc )
Tạo danh sách :
Cấp ph¸t bé nhí cho mét cÊu tróc
NhËp mét biÕn cÊu tróc vµo vïng nhí võa cÊp
Gán địa cấu trúc sau cho thành phần trỏ cấu trúc trước Duyệt qua tất phần tử danh sách :
§a trá p vỊ trá cïng cÊu tróc víi pdau b»ng lÖnh : p=pdau
Để chuyển tiếp đến người ta dùng lệnh : p=p->tiep
Dấu hiệu để biết xét cấu trúc cuối danh sách :
(97)p->tiep==NULL Loại cấu trúc khỏi danh sách :
Lưu trữ địa cấu trú c cần loại vào trỏ (Để giải phóng nhớ cấu trúc này)
Sửa để cấu trúc trước có địa cấu trúc cần loại Giải phóng nhớ cấu trúc cần loi
Bổ xung chèn cấu trúc vào danh sách: Cấp phát nhớ nhập bổ xung
Sửa thành phần trỏ cấu trúc có liên quan để đảm bảo cấu trúc chứa địa cấu trúc
Hàm cấp phát nhớ :
void *malloc(kichthuoc_t kichthuoc); Hàm lấy thư viện alloc.h stdlib.h
kichthuoc tính số by te Hàm đưa trỏ vị trí nhớ vừa cấp NULL không đủ nhớ cần thiết Nếu kichthuoc == 0thì trả NULL
VÝ dơ :
#include "stdio.h" #include "string.h" #include "alloc.h" #include "process.h" int main()
{
char *str;
/* Cấp phát nhớ cho xâu ký tự */ if ((str = malloc(10)) == NULL) {
printf("Not enough memory to allocate buffer \n"); exit(1); /* Kết thúc chương trình thiếu nhớ */ }
(98)/* HiÓn thị xâu */
printf("String is %s\n", str); /* Gi¶i phãng bé nhí */ free(str);
return 0; }
VÝ dô :
Tạo danh sách liên kết Các biến cấu trúc gồm trường : Họ tên, Quê quán, tuổi, trường trỏ Tiếp
Móc nối theo chiều thuận (Vào trước trước FIFO first in first out ): #include "stdio.h"
#include "alloc.h" #include "conio.h" #include "string.h" typedef struct pp
{
char ht[25]; char qq[20]; int tuoi; struct pp *tiep; } nhansu;
main() {
char tt;
nhansu *pdau,*pcuoi,*p; char tam[10];
clrscr(); pdau=NULL;
{
p=(nhansu*)malloc(sizeof(nhansu)); printf("\n Ho ten : ");
(99)printf(" Que quan : "); gets(p->qq); printf(" Tuoi: ");
gets(tam);
p->tuoi=atoi(tam); if (pdau==NULL)
{
pdau=p; pcuoi=p;
p->tiep=NULL; }
else {
pcuoi->tiep=p; pcuoi=p;
p->tiep=NULL; }
printf("\nBam phim bat ky de tiep tuc, ESC de dung"); tt=getch();
} while(tt!=27) ;
/* Đưa danh sách liên kết hình, trỏ pdau tro */ printf("\n Danh sach nhu sau :\n");
p=pdau;
while (p!=NULL) {
printf("\n Ho ten: %25s Que : %20s Tuoi : %d",(*p).ht,(*p).qq,(*p).tuoi);
p=p->tiep; }
getch(); }
Móc nối theo chiều ngược ( Vào sau trước LIFO last in first out ): #include "stdio.h"
(100)#include "conio.h" #include "string.h" typedef struct pp
{
char ht[25]; char qq[20]; int tuoi; struct pp *tiep; } nhansu;
main() {
char tt;
nhansu *pdau,*pcuoi,*p; char tam[10];
clrscr(); pdau=NULL;
{
p=(nhansu*)malloc(sizeof(nhansu)); printf("\n Ho ten : ");
gets(p->ht); printf(" Que quan : "); gets(p->qq); printf(" Tuoi: ");
gets(tam);
p->tuoi=atoi(tam); if (pdau==NULL)
{
pdau=p; pcuoi=p;
p->tiep=NULL; }
(101)p->tiep=pcuoi; pcuoi=p;
}
printf("\nBam phim bat ky de tiep tuc, ESC de dung"); tt=getch();
} while(tt!=27) ;
/* Đưa danh sách liên kết hình, trỏ pdau tro */ printf("\n Danh sach nhu sau :\n");
p=pcuoi;
while (p!=NULL) {
printf("\n Ho ten: %25s Que : %20s Tuoi : %d",(*p).ht,(*p).qq,(*p).tuoi);
p=p->tiep; }
(102)Chương 9 tập tin - file 9.1 Khái niệm tệp tin :
Tệp tin hay tệp liệu tập hợp liệu có liên quan với có kiểu nhóm lại với thành dãy Chúng thường chứa thiết bị nhớ ngồi tính (đĩa mềm, đĩa cứng ) tên
Tên tiếng Anh tệp làfile,nó dùng để hộp đựng phiếu hay thẻ ghi thư viện Một hình ảnh rõ nét giúp ta hình dung tệp tủ phiếu thư viện Một hộp có nhiều phiếu giống hình thức tổ chức, song lại khác nội dung , tủ phiếu tệp, phiếu thành phần tệp Trong máy tính, đĩa cứng đĩa mềm đóng vai trị tủ (để chứa nhiều tệp)
Tệp chứa nhớ ngồi, điều có nghĩa tệp lưu trữ để dùng nhiều lần tồn chương trình kết thúc điện Chính lý trên, liệu cần lưu trữ ( hồ sơ chẳng hạn) ta nên dùng đến tệp
Tệp kiểu liệu có cấu trúc Định nghĩa tệp có phần giống mảng chỗ chúng tập hợp phần tử liệu kiểu, song mảng thường có số phần tử cố định, số phần tử tệp không xác định định nghĩa
Trong C, thao tác tệp thực nhờ hàm thư viện Các hàm chia làm hai nhóm : nhóm nhóm Các hàm cấp hàm nhập / xuất hệ thống, chúng thực việc đọc ghi DOS Các hàm cấp làm việc với tệp thông qua biến trỏ tệp
Do hàm cấp có nhiều kiểu truy xuất dễ dùng so với hàm cấp nên chương trình viết C, cá c hàm cấp hay sử dụng
Một tệp tin dù xây dựng cách đơn giản dãy byte ghi đĩa (có giá trị từ đến 255) Số byte dãy độ dài tệp
Cã hai kiểu nhập xuất liệu lên tệp : Nhập xuất n hị phân nhập xuất văn Nhập xuất nhị phân :
D liu ghi lờn tệp theo byte nhị phân nhớ, q trình nhập xuất, liệu khơng bị biến đổi
Khi đọc tệp, gặp cuối tệp ta nhận mã kết thúc tệp EOF ( định nghĩa stdio.h -1) hàm feof cho giá trị khác
(103) Kiểu nhập xuất văn khác kiểu nhị phân xử lý ký tự chuyển dòng ( mã 10) ký tự mã 26 Đối với ký tự khác, hai kiểu đọc ghi
M· chun dßng :
Khi ghi, mét ký tù LF (mà 10) chuyển thành ký tự CR (mà 13) vµ LF
Khi đọc, ký tự liên tiếp CR LF tệp cho ta ký tự LF Mã kết thúc tệp :
Trong đọc, gặp ký tự có mã 26 cuối tệp ta nhận mã kết thúc tệp EOF ( -1) hàm feof(fp) cho giá trị khác ( 1)
9.2 Khai báo sử dụng tệp - số hàm thường dùng thao tác tệp : 9.2.1 Khai báo sử dụng :
Để khai báo sử dụng tệp, ta dïng lƯnh sau : FILE biÕn_con_trá_tƯp;
Trong biến_con_trỏ_tệp bi ến đơn hay danh sách biến phân cách dấu phảy ( dấu,)
VÝ dô :
FILE *vb, *np; /* Khai b¸o hai biÕn trá tƯp */ 9.2.2 Më tệp - hàm fopen :
Cấu trúc ngữ pháp hàm :
FILE *fopen(const char *tên_tệp, const char *kiểu); Nguyên hàm : stdio.h
Trong ú :
Đối thứ tên tệp, đối thứ hai kiểu truy nhập Công dụng :
(104)Bảng sau giá trị kiĨu :
Tªn kiĨu ý nghÜa
"r" "rt" Mở tệp để đọc theo kiểu văn Tệp cần đọc phải tồn tại, khơng có lỗi
"w" "wt" Mở tệp để ghi theo kiểu văn Nếu tệp tồn bị xoá
"a" "at" Mở tệp để ghi bổ xung theo kiểu văn Nếu tệp chưa tồn tạo tệp
"rb" Mở tệp để đọc theo kiểu nhị phân Tệp cần đọc phải tồn tại, khơng có lỗi "wb" Mở tệp để ghi theo kiểu nhị phân
Nếu tệp tồn bị xoá
"ab" Mở tệp để ghi bổ xung theo kiểu nhị phân Nếu tệp chưa tồn tạo tệp
"r+" "r+t" Mở tệp để đọc/ghi theo kiểu văn Tệp cần đọc phải tồn tại, khơng có lỗi "w+" "w+t" Mở tệp để đọc/ghi theo kiểu văn Nếu
tệp tồn bị xố
"a+" "a+t" Mở tệp để đọc/ghi bổ xung theo kiểu văn Nếu tệp chưa tồn tạo tệp "r+b" Mở tệp để đọc/ghi theo kiểu nhị phân Tệp
cần đọc phải tồn tại, k hơng có lỗi "w+b" Mở tệp để đọc/ghi theo kiểu nhị phân
Nếu tệp tồn bị xố
"a+b" Mở tệp để đọc/ghi bổ xung theo kiểu nhị phân Nếu tệp chưa tồn tạo tệp Chú ý :
Trong kiểu đọc ghi, ta nên lầm vùng đệm trước chuyển từ đọc sang ghi ngược lại Ta đề cập đến hàm với tính xố sau
VÝ dụ :
(105)Cấu trúc ngữ pháp hàm :
int fclose(FILE *fp); Nguyên hàm : stdio.h
Trong :
fp trỏ ứng với tệp cần đóng Cơng dụng :
Hàm dùng để đóng tệp kết thúc thao tác Khi đóng tệp, máy thực công việc sau :
Khi ghi liệu máy đẩy liệu cịn vùng đệm lên đĩa Khi đọc liệu máy xố vùng đệm
Gi¶i phãng biến trỏ tệp
Nếu lệnh thành công, hàm cho giá trị 0, trái lại cho hàm EOF Ví dụ :
fclose(f); 9.2.4 Đóng tất tệp mở - hàm fcloseall : Cấu trúc ngữ pháp hàm :
int fcloseall(void); Nguyên hàm : stdio.h C«ng dơng :
Hàm dùng để đóng tất tệp mở Nếu lệnh thành công, hàm cho giá trị số số tệp đóng, trái lại cho hàm EOF
VÝ dô :
fcloseall(); 9.2.5 Làm vùng đệm - hàm fflush :
CÊu tróc ng÷ pháp hàm :
(106)Nguyên hàm : stdio.h C«ng dơng :
Dùng làm vùng đệm tệp fp Nếu lệnh thành công, hàm cho giá trị 0, trái lại cho hàm EOF
VÝ dô :
fflush(f);
9.2.6 Làm vùng đệm tệp mở - hàm fflushall : Cấu trúc ngữ pháp hàm :
int fflushall(void); Nguyên hàm : stdio.h Công dông :
Dùng làm vùng đệm tất tệp mở Nếu lệnh thành công, hàm cho giá trị số tệp mở, trái lại cho hàm EOF
VÝ dơ :
fflushall(); 9.2.7 Kiểm tra lỗi file - hàm ferror :
Cấu trúc ngữ pháp hàm :
int ferror(FILE *fp); Nguyên hàm : stdio.h Trong fp trỏ tệp Cơng dụng :
Hàm dùng để kiểm tra lỗi thao tác tệp fp Hàm cho giá trị khơng có lỗi, trái lại hàm cho giá trị khác
9.2.8 KiĨmtra ci tƯp - hµm feof : CÊu tróc ngữ pháp hàm :
(107)Nguyờn hàm : stdio.h Trong fp trỏ tệp Công dụng :
Hàm dùng để kiểm tra cuối tệp Hàm cho giá trị khác gặp cu ối tệp đọc, trái lại hàm cho giá trị
9.2.9 Truy nhËp ngÉu nhiªn - hàm di chuyên trỏ vị : 9.2.7.1 Chuyển trỏ vị đầu tệp - Hàm rewind :
Cấu trúc ngữ pháp :
void rewind(FILE *fp); Nguyên hàm : stdio.h Trong fp trỏ tệp Công dụng :
Chuyển trỏ vị tệp fp đầu tệp Khi việc nhập xuất tệp fp thực từ đầu
VÝ dô :
rewind(f); 9.2.9.2 Chuyển trỏ vị trí cần thiết - Hàm fseek : Cấu trúc ngữ pháp :
int fseek(FILE *fp, long sb, int xp); Nguyên hàm : stdio.h
Trong
fp lµ trá tƯp
sb số byte cần di chuyển
xp cho biết vị trí xuất phát mà việc dịch chuyển xp nhận giá trị sau :
xp=SEEK_SET hay : XuÊt phát từ đầu tệp
(108)Công dụng :
Chuyển trỏ vị tệp fp vị trí xác định xp qua số byte xác định giá trị tuyệt đối sb Chiều di chuyển l cuối tệp sb dương, trái lại di chuyển đầu tệp Khi thành công, hàm trả giá trị Khi có lỗi hàm trả giá trị khác khơng
Chó ý :
Khơng nên dùng fseek tệp tin văn bản, chuyển đổi ký tự làm cho việc định vị thiếu xác
VÝ dơ :
fseek(stream, SEEK_SET, 0);
9.2.9.3 VÞ trÝ trỏ vị - Hàm ftell : Cấu trúc ngữ pháp :
int ftell(FILE *fp); Nguyên hàm : stdio.h Trong
fp trỏ tệp Công dụng :
Hàm cho biết vị trí c on trỏ vị (byte thứ tệp fp) thành công Số thứ tự tính từ Trái lại hàm cho giá trị -1L
Ví dụ :
Sau lệnh fseek(fp,0,SEEK_END); ftell(fp) cho giá trị
Sau lệnh fseek(fp,-1,SEEK_END); ftell(fp) cho giá trị
9.2.10 Ghi mẫu tin lên tệp - hàm fwrite : Cấu trúc ngữ pháp hàm :
(109)Nguyờn hm : stdio.h Trong :
ptr trỏ trỏ tới vùng nhớ chứa liệu cần ghi sizelà kích thước mẫu tin theo byte
n số mẫu tin cần ghi fp trá tƯp
C«ng dơng :
Hàm ghi n mẫu tin kích thước sizebyte từ vùng nhớ ptrlên tệpfp Hàm trả giá trị số mẫu tin thực ghi Ví dụ :
#include "stdio.h" struct mystruct {
int i; char ch; }; main() {
FILE *stream; struct mystruct s;
stream = fopen("TEST.TXT", "wb") /* Më tÖp TEST.TXT */ s.i = 0;
s.ch = 'A';
fwrite(&s, sizeof(s), 1, stream); /* ViÕt cÊu tróc vµo tƯp */ fclose(stream); /* §ãng tƯp */
return 0; }
9.2.11 Đọc mẫu tin từ tệp - hàm fread : Cấu trúc ngữ pháp hàm :
(110)Nguyên hàm : stdio.h Trong :
ptr trỏ trỏ tới vùng nhớ chứa liệu cần ghi sizelà kích thước mẫu tin theo byte
n lµ sè mẫu tin cần ghi fp trỏ tệp
C«ng dơng :
Hàm đọc n mẫu tin kích thước sizebyte từ tệpfplên lên vùng nhớ ptr Hàm trả giá trị số mẫu tin thực đọc
VÝ dô :
#include "string.h" #include "stdio.h" main()
{
FILE *stream;
char msg[] = "KiÓm tra"; char buf[20];
stream = fopen("DUMMY.FIL", "w+"); /* Viết vài liệu lên tƯp */
fwrite(msg, strlen(msg)+1, 1, stream); /* T×m ®iĨm ®Çu cđa file */
fseek(stream, SEEK_SET, 0); /* Đọc số liệu hiển thị */
fread(buf, strlen(msg)+1, 1, stream); printf("%s\n", buf);
fclose(stream); return 0; }
9.2.10 NhËp xuÊt ký tù :
(111)int putc(int ch, FILE *fp); int fputc(int ch, FILE *fp); Nguyên hàm : stdio.h Trong ú :
ch giá trị nguyên fp trỏ tệp Công dụng :
Hàm ghi lªn tƯp fp mét ký tù cã mÉ b»ng m=ch % 256
ch xem giá trị nguyên không dấu Nếu thành công hàm cho mà ký tự ghi, trái lại cho EO F
VÝ dô :
#include "stdio.h" main()
{
char msg[] = "Hello world \n"; int i = 0;
while (msg[i])
putc(msg[i++], stdout); /* stdout thiết bị chuẩn - Màn hình*/ return 0;
}
9.2.12.2 Các hàm getc fgettc : Cấu trúc ngữ pháp :
int gretc(FILE *fp); int fputc(FILE *fp); Nguyên hàm : stdio.h Trong :
(112)C«ng dơng :
Hàm đọc ký tự từ tệp fp Nếu thành cơng hàm cho mã đọc ( có giá trị từ đến 255) Nếu gặp cuối tệp hay có lỗi hàm trả EOF
Trong kiểu văn bản, hàm đọc lượt hai mã 13, 10 trả giá trị 10 Khi gặp mã 26 hàm trả EOF
VÝ dô :
#include "string.h" #include "stdio.h" #include "conio.h" main()
{
FILE *stream;
char string[] = "Kiem tra"; char ch;
/* Mở tệp để cập nhật*/
stream = fopen("DUMMY.FIL", "w+"); /*ViÕt mét xâu ký tự vào tệp */
fwrite(string, strlen(string), 1, stream); /* Tìm vị trí đầu tệp */
fseek(stream, 0, SEEK_SET);
{
/* §äc mét ký tù tõ tƯp */ ch = fgetc(stream); /* HiĨn thÞ ký tù */ putch(ch);
} while (ch != EOF); fclose(stream); return 0; }
(113)int unlink(const char *tên_tệp) Nguyên hàm : dos.h, io.h, stdio.h Trong ú
tên_tệplà tên tệp cần xoá Công dơng :
Dùng để xố tệp đĩa Nếu thành công, hàm cho giá trị 0, trái lại hàm cho giá trị EOF
VÝ dô :
#include <stdio.h> #include <io.h> int main(void) {
FILE *fp = fopen("junk.jnk","w"); int status;
fprintf(fp,"junk");
status = access("junk.jnk",0); if (status == 0)
printf("Tệp tồn tại\n"); else
printf("Tệp không tồn t¹i \n"); fclose(fp);
unlink("junk.jnk");
status = access("junk.jnk",0); if (status == 0)
printf("TÖp tån tại\n"); else
printf("Tệp không tồn \n"); return 0;
(114)(115)Chương 10 Đồ hoạ
Chương giới thiệu hàm thủ tục để khởi động hệ đồ hoạ, vẽ đường hình trịn, cung elip, hình quạt, đường gãy khúc, đa g iác, đường thẳng, hình chữ nhật, hình hộp chữ nhật
Các hàm thủ tục đồ hoạ khai báo file graphics.h 10.1 Khởi động đồ hoạ :
Mục đích việc khởi động hệ thống đồ hoạ xác định thiết bị đồ hoạ (màn hình) mode đồ hoạ sử dụng chương trình Để làm cơng việc này, ta có hàm sau :
void initgraph(int *graphdriver,int graphmode,char *driverpath); Trong :
driverpath xâu ký tự đường dẫn đến thư mục chứa tập tin điều khiển đồ hoạ
graphdriver cho biết hình đồ h oạ sử dụng chương trình graphmode cho biết mode đồ hoạ sử dụng chương trình Bảng cho giá trị graphdriver graphmode :
graphdriver DETECT (0)
graphmode Độ phân giải
CGA (1) CGAC0 (0)
CGAC1 (1) CGAC2 (2) CGAC3 (3) CGAHi (4) 320x200 320x200 320x200 320x200 640x200
MCGA (2) MCGA0 (0)
MCGA1 (1) MCGA2 (2) MCGA3 (3) MCGAMed (4) MCGAHi (5) 320x200 320x200 320x200 320x200 640x200 640x480
EGA (3) EGAL0 (0)
EGAHi (1)
(116)EGA64 (4) EGA64LO (0) EGA64Hi (1)
640x200 640x350
EGAMONO (5) EGAMONOHi (0) 640x350
VGA (9) VGALO (0)
VGAMED (1) VGAHI (2)
640x200 640x350 640x480
HERCMONO (7) HERCMONOHI 720x348
ATT400 (8) ATT400C0 (0)
ATT400C1 (1) ATT400C2 (2) ATT400C3 (3) ATT400MED (4) ATT400HI (5) 320x200 320x200 320x200 320x200 640x400 640x400
PC3270 (10) PC3270HI (0) 720x350
IBM8514 (6) PC3270LO (0)
PC3270HI (1)
640x480 256 mÇu 1024x768 256 mÇu Chó ý :
Bảng cho ta giá trị chúng mà biến graphdtriver graphmode nhận Chẳng hạn DETE CT có giá trị 0, VGA có giá trị 9, VGALO có giá trị vv
Khi lập trình ta thay vào vị trí tương ứng chúng hàm tên giá trị
VÝ dơ :
Giả sử máy tính có hình VGA, tập tin đồ hoạ chứa thư mục C: \TC \BGI, ta khởi động hệ thống đồ hoạ sau :
#include "graphics.h" main()
{
int mh=VGA,mode=VGAHI; /*Hc mh=9,mode=2*/ initgraph(&mh,&mode,"C: \\TC\\BGI");
(117) Bảng cho thấy độ phân giải phụ thuộc vào hình mode Ví dụ hình EGA dùng EGALo độ phân giải 640x200 ( Hàm getmaxx() cho giá trị cực đại số điểm theo chiều ngang hình Với hình EGA : 639, Hàm getmaxy() cho giá trị cực đại số điểm theo chiều dọc hình Với hình EGA : 199 )
Nếu khơng biết xác kiểu hình sử dụng ta gán cho biến graphdriver DETECT hay giá trị Khi đó, kết ca initgraph s l :
Kiểu hình sử dụng phát hiện, giá trị g¸n cho biÕn graphdriver
Mode đồ hoạ độ phân giải cao ứng với hành sử dụng phát trị số gán cho biến graphmode
Như dùng số DETECT khởi động hệ thống đồ hoạ với hình có theo mode có độ phân giải cao mà cịn giúp ta xác định kiểu hình sử dụng
VÝ dơ :
Chương trình xác định kiểu hình sử dụng : #include "graphics.h"
#include "stdio.h" main()
{
int mh=0, mode;
initgraph(&mh,&mode,"C: \\TC\\BGI"); printf("\n Gia tri so cua man hinh la : %d",mh); printf("\n Gia tri so mode hoa la : %d",mode); closegraph();
}
Nếu chuỗi dùng để xác định dri verpath chuỗi rỗng chương trình dịch tìm kiếm file điều khiển đồ hoạ thư mục chủ ( Thư mục thời )
10.2 Các hàm đồ hoạ : 10.2.1 Mẫu mu :
Đặt màu :
(118)void setbkcolor(int màu); Đặt màu đường vẽ :
Để đặt màu vẽ đường ta dùng thủ tc sau : void setcolor(int mu);
Đặt mẫu (kiểu) tô màu tô :
t mu (kiểu) tô màu tô ta dùng thủ tục sau : void setfillstyle(int mẫu, int màu);
Trong ba trường hợp màuxác định mã màu Các giá trị màucho bảng :
Bảng giá trị màu
Tên Giá trị số Màu hiển thị
BLACK §en
BLUE Xanh da trêi
GREEN Xanh
CYAN Xanh lơ
RED Đỏ
MAGENTA Tím
BROWN Nâu
LIGHTGRAY Xám nhạt
DARKGRAY Xám đậm
LIGHTBLUE Xanh xa trêi nh¹t
LIGHTGREEN 10 Xanh nhạt
LIGHTCYAN 11 Xanh lơ nhạt
LIGHTRED 12 Đỏ nhạt
LIGHTMAGENTA 13 Tím nhạt
YELLOW 14 Vàng
WHITE 16 Trắng
Cỏc giá trị mẫucho bảng :
Bảng giá trị c mẫu
Tên Giá trị số Kiểu mẫu tô
EMPTY_FILL Tô mầu
SOLID_FILL Tô đường liền nét
(119)-LTSLASH_FILL T« b»ng ///
SLASH_FILL T« b»ng /// in đậm
BKSLASH_FILL Tô \\\ in ®Ëm
LTBKSLASH_FILL T« b»ng \\\
HATCH_FILL Tô đường gạch bóng nhạt
XHATCH_FILL Tô đường gạch bóng chữ thập
INTERLEAVE_FILL Tụ đường đứt quãng
WIDE_DOT_FILL 10 T« b»ng dÊu chÊm tha
CLOSE_DOT_FILL 11 T« b»ng dÊu chÊm mau
Chọn giải màu :
thay i gii màu định nghĩa bảng trên, ta sử dụng hàm : void setpalete(int số_thứ_tự_màu, int màu );
VÝ dơ :
C©u lƯnh :
setpalete(0,lightcyan);
biến màu bảng màu thành màu xanh lơ nhạt Các màu khác không bị ảnh hưởng Lấy giải màu thời :
+ Hàm getcolor trả mầu xác định thủ tục setcolor trước
+ Hàm getbkcolor trả mầu xác định hàm setbkcolor trước
10.2.2 Vẽ tô màu :
Có thể chia đường hình thành bốn nhóm chí nh : Cung tròn hình tròn
Đường gấp khúc đa giác Đường thẳng
Hình chữ nhật 10.2.2.1 Cung tròn đường tròn :
(120)Cung tròn :
Để vẽ cung tròn ta dùng hàm :
void arc(int x, int y, int gd, int gc, int r); Trong :
(x,y) toạ độ tâm cung trịn
gd góc đầu cung trịn(0 đến 360 độ) gc góc cuối cung trịn (gd đến 360 độ) r bán kính cung trịn
VÝ dơ :
Vẽ cung tròn có tâm (100,50), góc đầu 0, góc cuố i 180, bán kính 30 arc(100,50,0,180,30);
Đường tròn :
vẽ đường tròn ta dùng hàm : void circle(int x, int y, int r); Trong :
(x,y) toạ độ tâm cung trịn r bán kính đường trũn Vớ d :
Vẽ đường tròn có tâm (100,50) bán k ính 30 circle(100,50,30);
Cung elip
§Ĩ vÏ mét cung elip ta dïng hµm :
void ellipse(int x, int y, int gd, int gc, int xr, int yr); Trong :
(x,y) toạ độ tâm cung elip
gd góc đầu cung trịn(0 đến 360 độ) gc góc cuối cung trịn (gd đế n 360 độ) xr bán trục nằm ngang
(121)Vẽ cung elip có tâm (100,50), góc đầu 0, góc cuối 180, bán trục ngang 30, bán trc ng l 20
ellipse(100,50,0,180,30,20); Hình quạt :
Để vẽ tơ màu hình quạt ta dùng hàm : void pieslice(int x, int y, int gd, int gc, int r); Trong :
(x,y) toạ độ tâm hình quạt
gd góc đầu hình quạt (0 đến 360 độ) gc góc cuối hình quạt (gd đến 360 độ) r bán kính hình quạt
VÝ dơ :
Chương trình vẽ cung trịn góc phần tư thứ nhất, cung elip góc phần tư thứ ba, đường trịn hình quạt qt từ 90 đến 360 độ
# include "graphics.h" #include "stdio.h" #include "conio.h" main()
{
int md=0,mode;
initgraph(&md,&mode,"C:\\TC\\BGI"); setbkcolor(BLUE);
setcolor(YELLOW);
setfillstyle(SOLID_FILL,RED);; arc(160,50,0,90,45);
circle(160,150,45);
pieslice(480,150,90,360,45); getch();
closegraph(); }
(122) VÏ ®êng gÊp khóc :
Muốn vẽ đường gấp khúc qua n điểm : (x1,y1), (x2,y2), , (xn,yn) trước hết ta phải gán toạ độ (xi,yi) cho mảng a kiểu int theo nguyên tắc sau :
Toạ độ x1 gán cho a[0] Toạ độ y1 gán cho a[1] Toạ độ x2 gán cho a[2] Toạ độ y2 gán cho a[3]
Toạ độ xn gán cho a[2n-2] Toạ độ yn gán cho a[2n-1] Sau gọi hàm :
drawpoly(n,a);
NÕu điểm cuối (xn,yn) trùng với điểm đầu (x1,y1) ta nhận đường gấp khúc khép kín
Tô màu đa giác :
Gi s ta có a mảng đề cập đến mục trên, ta gọi hàm : fillpoly(n,a);
sẽ vẽ tơ màu đa giác có đỉnh điểm (x1,y1), (x2,y2), , (xn,yn) Ví dụ :
Vẽ đường gấp khúc hai đường tam giác #include "graphics.h"
#include "stdio.h" #include "conio.h"
int poly1[]={5,200,190,5,100,300}; int poly2[]={205,200,390,5,300,300};
int poly3[]={405,200,590,5,500,300,405,200}; main()
{
int md=0,mode;
initgraph(&md,&mode,"C: \\TC\\BGI"); setbkcolor(CYAN);
(123)setfillstyle(SOLID_FILL,MAGEN TA); drawpoly(3,poly1);
fillpoly(3,poly2); fillpoly(4,poly3); getch();
closegraph(); }
Vẽ đường thẳng :
v ng thẳng nối hai điểm có toạ độ (x1,y1) (x2,y2) ta sử dụng hàm sau : void line(int x1, int y1, int x2, int y2);
Con chạy đồ hoạ giữ nguyên vị trí
Để vẽ đường thẳng nối từ điểm chạy đồ hoạ đến điểm bất có toạ độ (x,y) ta sử dụng hàm sau :
void lineto(int x, int y); Con chạy chuyển đến vị trí (x,y)
Để vẽ đường thẳng từ ví trí chạy tạ i ( giả sử điểm x,y ) đến điểm có toạ độ (x+dx,y+dy) ta sử dụng hàm sau :
void linerel(int dx, int dy); Con chạy chuyển đến vị trí (x+dx,y+dy) Di chuyển chạy đồ hoạ :
Để di chuyển chạy đến vị trí (x,y), ta sử dụng hàm sau : void moveto(int x, int y);
Chän kiĨu ®êng :
Hàm void setlinestyle(int kiểu_đường, int mẫu, int độ_dày);
tác động đến nét vẽ thủ tục vẽ đường line, lineto,linerel , circle, rectangle (hàm vẽ hình chữ nhật, ta học phần vẽ miền dưới)
Hàm cho phép ta xác định ba yếu tố vẽ đường thẳng, : Kiểu đường, bề dày mẫu tự tạo
(124)Tªn Giá trị số Kiểu đường
SOLID_LINE Nét liÒn
DOTTED_LINE NÐt chÊm
CENTER_LINE NÐt chÊm g¹ch
DASHED_LINE NÐt g¹ch
USERBIT_LINE MÉu tù t¹o
Bề dày đường vẽ tham số độ_dày xác định, bảng cho giỏ tr kh d ca_dy:
Tên Giá trị sè BỊ dµy
NORM_WIDTH Bề dày bình thường
THICK_WIDTH BỊ dµy gÊp ba
Mẫu tự tạo : Nếu tham số thứ USERBIT_LINE ta tạo mẫu đường thẳng tham số mẫu.Ví dụ ta xét đoạn chương trình :
int pattern = 0x1010;
setlinestile(USERBIT_LINE,pattern,NORM_WIDTH); line(0,0,100,200);
Giá trị cđa pattern hƯ 16 lµ 1010, hƯ lµ : 0001 0000 0001 0000
Bit sÏ cho điểm sáng, bit làm tắt điểm ảnh VÝ dơ :
Chương trình vẽ đường gấp khúc đoạn thẳng Đường gấp khúc qua đỉnh sau :
(20,20),(620,20),(620,180),(20,180) vµ (320,100) #include "graphics.h"
#include "stdio.h" #include "conio.h" main()
{
int mh=0, mode;
initgraph(&mh,&mode,"C: \\TC\\BGI"); setbkcolor(BLUE);
(125)setlinestyle(SOLID-LINE,0,THICK_WIDTH); moveto(320,100); /* chạy vị trí ( 320,100 ) */ line(20,20,620,20); /* chạy vị trí ( 320,100 ) */ linerel(-300,80);
lineto(620,180); lineto(620,20); getch(); closegraph(); }
10.2.4 VÏ ®iĨm, miỊn : VÏ ®iĨm :
Hµm :
void putpixel(int x, int y, int color); tô điểm (x,y) theo mầu xác định color.
Hµm :
unsigned getpixel(int x, int y);
sẽ trả số hiệu mầu điểm ¶nh ë vÞ trÝ (x,y) Chó ý :
NÕu điểm chưa tô màu hàm vẽ hàm putpixel (mà tạo màu setbkcolor) hàm cho giá trị
T« miỊn :
Để tơ màu cho miền hình, ta dùng hàm sau : void floodfill(int x, int y, int border);
ở :
(x,y) toạ độ điểm gọi điểm gieo Tham số border chứa mã màu
(126)- NÕu ®iĨm gieo (x,y) nằm tron g miền miền giới hạn phía đường tô màu
- Nu điểm gieo (x,y) nằm ngồi miền miền phía ngồi đường tơ màu + Trong trường hợp hình khơng có đường cong hình tơ màu
VÝ dơ :
Vẽ đường trịn màu đỏ hình màu xanh Toạ độ (x,y) điểm gieo nạp từ bàn phím Tuỳ thuộc giá trị cụ thể x,y chương trình tơ màu vàng cho hình trịn phần hình bên ngồi hình tròn
#include "graphics.h" #include "stdio.h" main()
{
int mh=mode=0, x, y; printf("\nVao toa x,y:"); scanf("%d%d",&x,&y); initgraph(&mh,&mode,""); if (graphresult != grOk) exit(1); setbkcolor(BLUE);
setcolor(RED);
setfillstyle(11,YELLOW); circle(320,100,50); moveto(1,150); floodfill(x,y,RED); closegraph(); }
10.2.5 Hình chữ nhật : Hµm :
void rectangle(int x1, int y1, int x2, int y2);
(127) Hµm :
void bar(int x1, int y1, int x2, int y2);
sẽ vẽ tơ màu hình chữ nhật Toạ độ đỉnh trái hình chữ nhật (x1,y1) toạ độ đỉnh phải hành chữ nhật (x2,y2)
Hµm :
void bar3d(int x1, int y1, int x2, int y2, int depth, int top);
sẽ vẽ khối hộp chữ nhật, mặt ngồi hình chữ nhật xác định toạ độ (x1,y1), (x2,y2) Hình chữ nhật tô màu thông qua hàm setfillstyle Tham số depth xác định số điểm ảnh bề sâu khối chiều Tham số top nhận giá trị hay khối chiều tương ứng có nắp khơng
VÝ dơ :
Chương trình tạo nên hình chữ nhật, khối hình chữ nhật hình hộp có nắp :
#include "graphics.h" main()
{
int mh=mode=0;
initgraph(&mh,&mode,""); if (graphresult != grOk) exit(1); setbkcolor(GREEN);
setcolor(RED);
setfillstyle(CLOSE_DOT_FILL,YELLOW); rectangle(5,5,300,160);
bar(3,175,300,340);
bar3d(320,100,500,340,100,1); closegraph();
(128)}
10.2.6 Cưa sỉ (Viewport) : ThiÕt lËp viewport :
Viewport vùng chữ nhật hình đồ hoạ Để thiết lập viewport ta dùng hàm : void setviewport(int x1, int y1, int x2, int y2, int clip);
trong (x1,y1) toạ độ góc bên trái, (x2,y 2) toạ độ góc bên phải Bốn giá trị phải thoả mãn :
0 x1 x2 0 y1 y2 Tham sè clip cã thÓ nhËn hai giá trị :
clip=1 không cho phÐp vÏ ngoµi viewport clip=0 cho phÐp vÏ ngoµi viewport VÝ dơ :
setviewport(100,50,200,150,1);
Lập nên vùng viewport hình chữ nhật có toạ độ góc trái cao (100,50) toạ độ góc phải thấp (200,150) (là toạ độ trước đặt viewport)
Chó ý :
Sau lập viewport, ta có hệ toạ độ mà góc bên trái có toạ đ ộ (0,0) Nhận diện viewport hành :
§Ĩ nhËn viewport hiƯn thêi ta dïng hµm :
void getviewsetting(struct viewporttype *vp); kiểu viewporttype định nghĩa sau :
struct viewporttype {
int left,top,right,bottom; int clip;
}; Xãa viewport :
(129)void clearviewport(void);
Xố hình, đưa chạy tạo độ (0,0) hình : Sử dụng hàm :
void cleardevice(void); Toạ độ âm dương :
Nhờ sử dụng viewport viết chương trình đồ hoạ theo toạ độ âm dương Muốn ta thiết lập viewport cho clip để vẽ giới hạn viewport
Sau đoạn chương trình thực cơng việc : int xc,yc;
xc=getmaxx()/2; yc=getmaxy()/2;
setviewport(xc,yc,getmaxx(),getmaxy(),0);
Như thế, hình chia làm bốn phần với toạ độ âm dương sau : Phần tư trái : x âm, y âm
x : từ -getmaxx()/2 đến y : từ -getmaxy()/2 đến Phần tư trái : x âm, y dương
x : từ -getmaxx()/2 đến y : từ đến getmaxy()/2 Phần tư phải : x dương, y âm
x : từ đến getmaxx()/2 y : từ -getmaxy()/2 đến Phần tư phải : x dương, y dương
x : từ đến getmaxx()/2 y : từ đến getmaxy()/2 Ví dụ :
Chương trình vẽ đồ thị hàm sin x hệ trục toạ độ âm dương Hoành độ x lấy giá trị từ -4 đến 4 Trong chương trình có sử dụng hai hàm settextjustify outtextxy ta đề cập phần sau
(130)#include "math.h" #define TYLEX 20 #define TYLEY 60 main()
{
int mh=mode=DETECT; int x,y,i;
initgraph(mh,mode,"");
if (graphresult!=grOK ) exit(1);
setviewport(getmaxx()/2,getmaxy()/2,getmaxx(),getmaxy(),0); setbkcolor(BLUE);
setcolor(YELLOW);
line(-getmaxx()/2,0,getmaxx()/2,0); line(0,-getmaxy()/2,0,getmaxy()/2,0); settextjustify(1,1);
setcolor(WHITE); outtextxy(0,0,"(0,0)"); for (i=-400;i<=400;++i)
{
x=floor(2*M_PI*i*TYLEX/200); y=floor(sin(2*M_PI*i/200)*TYLEY); putpixel(x,y,WHITE);
} getch(); closegraph(); }
10.3 Xử lý văn hình đồ hoạ : Hiển thị văn hình đồ hoạ :
Hµm :
void outtext(char *s);
(131)void outtextxy(int x, int y,char *s); cho chuỗi ký tự ( trỏ s trỏ tới ) vị trí (x,y) Ví dụ :
Hai cách viết :
outtextxy(50,50," Say HELLO"); vµ
moveto(50,50);
outtext(" Say HELLO"); cho cïng kÕt
Sử dụng Fonts chữ :
Các Fonts chữ nằm tập tin *.CHR đĩ a Các Fonts cho kích thước kiểu chữ khác nhau, chúng hiển thị lên hình hàm outtext outtextxy Để chọn nạp Fonts ta dùng hàm :
void settextstyle(int font, int direction, int charsize); Tham số font để chọn kiểu chữ nhận sau :
DEFAULT_FONT=0 TRIPLEX_FONT=1 SMALL_FONT=2 SANS_SERIF_FONT=3 GOTHIC_FONT=4
Tham số derection để chọn hướng chữ nhận sau :
HORIZ_DIR=0 văn hiển thị theo hướng nằm ngang từ trái qua phải
VERT_DIR=1 văn hiển thị theo hướng thẳng đứng từ lên Tham số charsize hệ số phóng to ký tự có giá trị khoảng từ n 10
Khi charsize=1, font hiển thị hình chữ nhật 8*8 pixel Khi charsize=2 font hiển thị tron g hình chữ nhật 16*16 pixel
(132)
Ví dụ :
Các dòng lệnh :
settextstyle(3,VERT_DIR,2);
outtextxy(30,30,"GODS TRUST YOU");
sẽ hiển thị vị trí (30,30) dịng chữ GODS TRUST YOU theo chiều từ lên trên, font chữ chọn SANS_SERIF_FONT v c ch l
Đạt vị trí hiển thị xâu ký tự cho outtext vµ outtextxy :
Hàm settextjustify cho phép định nơi hiển thị văn outtext theo quan hệ với vị trí chạy outtextxy theo quan hệ với toạ độ (x,y);
Hàm có dạng sau :
void settextjustify(int horiz, int vert); Tham sè horiz cã thĨ lµ mét c¸c h»ng s è sau :
LEFT_TEXT=0 ( Văn xuất bên phải chạy) CENTER_TEXT ( Chỉnh tâm văn theo vị trí chạy) RIGHT_TEXT (Văn xuất bên trái chạy) Tham số vert c¸c h»ng sè sau :
BOTTOM_TEXT=0 ( Văn xuất phía chạy) CENTER_TEXT=1 ( Chỉnh tâm văn theo vị trí chạy) TOP_TEXT=2 ( Văn xuất phía chạy) Ví dụ :
settextjustify(1,1);
outtextxy(100,100,"ABC");
sẽ cho dòng chữ ABC điể m (100,100) nằm chữ B Bề rộng chiều cao văn :
ChiỊu cao : Hµm :
textheight(char *s);
(133)Với font bit map hệ số phóng đại textheight("A") ch giá trị l Ví dụ :
#include "stdio.h" #include "graphics.h" main()
{
int mh=mode=DETECT, y,size; initgraph(mh,mode,"C:\\TC\\BGI"); y=10;
settextjustify(0,0);
for (size=1;size<5;++size) {
settextstyle(0,0,size);
outtextxy(0,y,"SACRIFICE" ); y+=textheight("SACRIFICE")+10; }
getch(); closegraph(); }
BÒ réng : Hµm :
textwidth(char *s);
(134)Mơc lơc Giíi thiƯu
Chương 1
C¸c kh¸i niệm bản
1.1 Tập ký tự dùng ngôn ngữ C 1.2 Từ khoá
1.3 Tên
1.4 Kiểu liệu 1.4.1 Kiểu ký tự (char) 1.4.2 Kiu nguyờn 1.4.3 Kiu du phy ng
1.5 Định nghĩa kiểu TYPEDEF 1.5.1 Công dụng
1.5.2 Cách viết 1.6 Hằng 1.6.1 Tên 1.6.2 Các loại 1.6.2.1 H»ng int 1.6.2.2 H»ng long 1.6.2.3 H»ng int hÖ 1.6.2.4 H»ng int hÖ 16 1.6.2.5 H»ng ký tù 1.6.2.5 H»ng x©u ký tù 1.7 BiÕn
1.8 Mảng Chng 2
Các lệnh vào
2.1 Thâm nhập vào thư viện chuẩn
2.2 Các hàm vào chuÈn - getchar() vµ putchar() 2.2.1 Hµm getchar()
(135)2.2.4 Hàm putch()
2.3 Đưa kết lên hình - hàm printf 2.4 Vào số liệu từ bàn phím - hàm scanf 2.5 Đưa kết máy in
Chng 3 Biu thc 3.1 Biu thc
3.2 Lệnh gán biểu thức 3.3 C¸c phÐp to¸n sè häc
3.4 C¸c phÐp to¸n quan hệ logic 3.5 Phép toán tăng giảm
3.6 Thứ tự ưu tiên phép toán 3.7 Chuyển đổi kiểu giá trị Chương 4
Cấu trúc chương trình 4.1 Lời thích
4.2 LƯnh vµ khèi lƯnh 4.2.1 LƯnh
4.2.2 Khèi lƯnh
4.3 Cấu trúc chương trình
4.4 Một số qui tắc cần nhớ viết chương trình Chương 5
CÊu tróc ®iỊu khiĨn 5.1 CÊu tróc cã ®iỊu kiƯn 5.1.1 LƯnh if-else 5.1.2 LƯnh else-if
5.2 Lệnh nhảy không điều kiện - toán tử goto 5.3 CÊu tróc rÏ nh¸nh - to¸n tư switch 5.4 CÊu tróc lỈp
(136)5.4.1.2 CÊu trúc lặp với toán tử for : 5.4.2 Chu trình do-while
5.5 Câu lệnh break 5.6 Câu lệnh continue Chng 6
Hàm 6.1 Cơ sở
6.2 Hm không cho giá trị 6.3 Hàm đệ qui
6.3.3 Mở đầu
6.3.2 Cỏc bi toỏn cú th dùng đệ qui 6.3.3 Cách xây dựng hàm đệ qui 6.3.4 Các ví dụ dùng hàm đệ qui 6.4 Bộ tiền sử lý C
Chương 7 Con trỏ
7.1 Con trỏ địa
7.2 Con trỏ mảng chiều 7.2.1.Phép toán lấy địa
7.2.2 Tên mảng địa
7.2.3 Con trỏ trỏ tới phần tử mảng chiều 7.2.4 Mảng, trỏ xâu ký tự
7.3 Con trỏ mảng nhiều chiều 7.3.1.Phép lấy địa
7.3.2 Phép cộng địa mảng hai chiều 7.3.3 Con trỏ mảng hai chiều
7.4 Kiểu trỏ kiểu địa chỉ, phép toán trỏ 7.4.1 Kiểu trỏ kiểu địa ch
7.4.2 Các phép toán trỏ 7.4.3 Con trá kiĨu void
(137)7.6.1 C¸ch khai báo trỏ hàm mảng trỏ hàm 7.6.2 Tác dụng trỏ hàm
7.6.3 i trỏ hàm Chương 8
CÊu tróc 8.1 KiĨu cÊu tróc
8.2 Khai báo theo kiểu cấu t rúc định nghĩa 8.3 Truy nhập đến thành phần cấu trúc
8.4 M¶ng cÊu tróc
8.5 Khởi đầu cấu trúc 8.6 Phép gán cÊu tróc
8.7 Con trỏ cấu trúc địa cấu trúc 8.7.1 Con trỏ địa
8.7.2 Truy nhập qua trỏ 8.7.3 Phép gán qua trỏ 8.7.4 Phép cộng địa 8.7.5 Con trỏ mảng
8.8 Cấu trúc tự trỏ danh sách liên kết Chương 9
TËp tin - file
9.1 Kh¸i niƯm vỊ tƯp tin
9.2 Khai báo sử dụng tệp - số hàm thường dùng thao tác tệp 9.2.1 Khai báo sử dụng
9.2.2 Mở tệp - hàm fopen 9.2.3 Đóng tƯp - hµm fclose
9.2.4 Đóng tất tệp mở - hàm fcloseall 9.2.5 Làm vùng đệm - hàm fflush
9.2.6 Làm vùng đệm tệp mở - hàm fflushall 9.2.7 Kiểm tra lỗi file - hàm ferror
9.2.8 KiÓmtra cuèi tƯp - hµm feof
(138)9.2.9.2 Chun trỏ vị trí cần thiết - Hàm fseek 9.2.9.3 Vị trí cuẩ trỏ vị - Hàm ftell 9.2.10 Ghi mẫu tin lên tệp - hàm fwrite 9.2.11 Đọc mẫu tin từ tệp - hµm fread 9.2.12 NhËp xuÊt ký tù
9.2.12.1 Các hàm putc fputc 9.2.12.2 Các hàm getc fgettc 9.2.13 Xoá tệp - hàm unlink Chương 10
Đồ hoạ
10.1 Khi ng ho 10.2 Cỏc hàm đồ hoạ 10.2.1 Mẫu màu 10.2.2 Vẽ tụ mu
10.2.3 Vẽ đường gấp khúc đa giác 10.2.4 Vẽ điểm, miền
10.2.5 Hình chữ nhật 10.2.6 Cưa sỉ (Viewport)
10.3 Sử lý văn trờn mn hỡnh ho
Bài tập
Phần thứ nhất : Nhóm tập tính toán,hàm chu trình
Bài tập :
(139)tài liệu tham khảo 1 Các tài liƯu tiÕng ViƯt :
1.1 Ng« Trung ViƯt - Ngôn ngữ lập trình C C++ - Bài giảng- Bài tập - Lời giải mẫu NXB giao thông vận tải 1995
1.2 Viện tin học - Ngôn ngữ lập trình C Hà nội 1990
1.3 Lờ Văn Doanh - 101 thuật tốn chương trình ngôn ngữ C 2 Các tài liệu tiếng Anh :
2.1 B Kernighan and D Ritchie - The C programming language Prentice Hall 1989
2.2 Programmer's guide Borland C++ Version 4.0 Borland International, Inc 1993
2.3 Bile - Nabaiyoti - TURBO C++ The Waite Group's UNIX 1991
BàI tập
Ngôn ngữ lập trình C
Phần : Nhóm bàI tập tính toán, hàm c hu trình
BàI tËp :
Viết chương trình hiển thị tháp PASCAL : 1 121 12321 1234321 123454321 12345654321 1234567654321 123456787654321 12345678987654321 Viết chương trình hiển thị tháp đảo ngược.
(140)Viết chương trình nhập ba số thực Kiểm tra xem ba số chiều dài ba cạnh của tam giác khơng? Nếu tính chu vi diện tích tam giác đó.
BµI tËp :
Viết chương trình tính hàm số :
f(x) = K0
x
K1+ -x
K2 + x
K3+
x
K4 +
… … … … x Kn-1+
-Kn
Bµi tËp :
Viết chương trình tính tích hai ma trận C mxn = Amxn * Bnxk
Bµi tËp :
Viết chương trình nhập vào dãy số sau tách dãy thành hai dãy chứa các số dương chứa số âm Tí nh tổng số phần tử dãy sau xếp để hai dãy có giá trị giảm dần.
Bµi tËp :
Viết chương trình nhập vào ma trận A nxm Tìm giá trị cực đại cực tiểu các phần tử mảng
Bµi tËp :
Trăm trâu,trăm cỏ Trâu đứng ăn năm Trâu nằm ăn ba Lụ khụ trâu già Ba bó. Tính số trâu loại Bi :
(141)Một trăm chân chẵn Tính số gà, số chó