1. Trang chủ
  2. » Luận Văn - Báo Cáo

Giao trinh C

141 8 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Nội dung

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ệ Nh­ng 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 ngaynhancong 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 ngaydingayden 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àngaydingaydencó 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 nhom1nhom2 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 th­a

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) =

K

0

x

K

1

+

-x

K

2

+

x

K

3

+

x

K

4

+

… … … …

x

K

n-1

+

-K

n

Bµi tËp :

Viết chương trình tính tích hai ma trận C

mxn

= A

mxn

* B

nxk

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ó

Ngày đăng: 02/05/2021, 18:23

w