1. Trang chủ
  2. » Công Nghệ Thông Tin

Giáo trình Lập Trình C

133 266 0
Tài liệu đã được kiểm tra trùng lặp

Đ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

Thông tin cơ bản

Tiêu đề Giáo trình Lập Trình C
Tác giả TS. Phan Đăng Cầu
Trường học Đại học Bách khoa Hà Nội
Chuyên ngành Lập Trình C
Thể loại Giáo trình
Năm xuất bản 2004
Thành phố Hà Nội
Định dạng
Số trang 133
Dung lượng 654,5 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Giáo trình Lập Trình C, giáo trình ngôn ngữ lập trình C căn bản, dành cho các bạn học sinh, sinh viên ngành công nghệ thông tin, một ngôn ngữ căn bản, một tài liệu cần thiết cho các học viên trong các trường đại học

Trang 1

LËp tr×nh C

Biªn so¹n

TS Phan §¨ng CÇu

Hµ néi, th¸ng 01/ 2004

Trang 2

lời nói đầu

Tài liệu này chúng tôi biên soạn nhằm mục đích hỗ trợ các bạn học viêntrong quá trình tiếp thu bài giảng môn học "Lập trình C" Thực ra có thể gọichính xác hơn là “Lập trình C trong môi trờng C++”, vì môi trờng chúng ta

sử dụng là C++, và các lệnh cũng không hoàn toàn là của C mà đã có sửdụng cú pháp của C++ khi cần thiết; thậm chí chơng 13 nói về tính đónggói, thừa kế và đa hình là của C++ (chúng tôi viết chơng này chủ yếu đểcác bạn tham khảo và tự tìm hiểu) Chúng tôi muốn nhấn mạnh rằng tài liệunày chỉ hỗ trợ các bạn, chứ không thay thế bài giảng vì các vấn đề đợc trìnhbày một cách tóm tắt, còn nhiều điều cha đợc giải thích đầy đủ, nếu chỉ

đọc mà không nghe giảng thì rất khó hiểu Ví dụ khi trình bày cú pháp cáclệnh thì dấu [ ] hàm ý là những gì nằm giữa hai dấu này là không bắtbuộc, còn những gì nằm giữa 2 dấu < > lại là bắt buộc phải có Tuy nhiêndấu [] lại đợc dùng để bao các chỉ số trong một mảng Ví dụ a[i][j] là phần

tử ở hàng i, cột j của một mảng a 2 chiều… Trong quá trình giảng dạy chúngtôi sẽ dựa vào sự tiếp thu của các bạn để đa ra cách giải thích và các ví dụminh họa phù hợp

Chúng tôi luôn sẵn sàng lắng nghe các ý kiến đóng góp của các bạn về tàiliệu cũng nh bài giảng, để sự hợp tác giữa giáo viên và học viên ngày cànghiệu quả hơn

Hà nội, tháng 01/2004

`

TS Phan Đăng Cầu

Trang 3

Mục lục

Chơng 1 Tổng quan về C và C++ 1

1.1 Ngôn ngữ lập trình và thuật toán 1

1.1.1 Ngôn ngữ lập trình 1

1.1.2 Thuật toán (Algorithm) 2

1.1.3 Sự ra đơi và phát triển của ngôn ngữ C 2

1.2 Các phần tử cơ bản trong ngôn ngữ C 3

1.2.1 Bộ ký tự (character set) 3

1.2.2 Các từ khóa (key words, reserved words) 3

1.2.3 Tên và cách đặt tên (identifier) 3

1.2.4 Lời giải thích (comment) 3

1.2.5 Một vài chơng trình C đơn giản 3

1.3 Cấu trúc chơng trình trong C 4

1.3.1 Các thành phần của một chơng trình C 4

1.3.2 Soạn thảo và chạy một chơng trình C 4

Chơng 2 Hằng, biến và mảng 7

2.1 Các kiểu dữ liệu cơ sở 7

2.2 Hằng 8

2.3 Kiểu enum 9

2.4 Biến 9

2.5 Mảng và chuỗi 11

2.6 Định nghĩa kiểu bằng typedef 11

2.7 Khối lệnh 12

2.8 Vài nét về hàm và chơng trình 12

2.9 Biến, mảng tự động 12

2.10 Biến, mảng ngoài 12

2.11 Toán tử sizeof 14

2.12 Biến tĩnh, mảng tĩnh 14

Chơng 3 Biểu thức 15

3.1 Khái niệm biểu thức(expression) 15

3.2 Phép toán số học 15

3.3 Các phép thao tác bit 15

3.4 Các phép toán quan hệ và logic 15

3.5 Phép chuyển đổi kiểu giá trị 15

3.6 Phép toán tăng giảm 15

3.7 Câu lệnh gán và biểu thức 15

3.8 Biểu thức điều kiện 15

3.9 Thứ tự u tiên các phép toán 16

Chơng 4 Vào ra 17

4.1 Hàm printf 17

4.2 Hàm scanf 18

4.3 Đa ra máy in- hàm fprintf 19

4.4 Dòng vào stdin và các hàm nhập dữ liệu 19

4.5 Nhập /xuất số liệu cho chuỗi và ký tự 21

4.6 Một số hàm xử lý chuỗi 21

4.7 Sự khác biệt giữa mảng và chuỗi 21

4.8 Các hàm vào ra và dịch chuyển vị trí trên màn hình 23

4.9 Các luồng nhập xuất cin,cout 23

Chơng 5 Các toán tử điều khiển 24

5.1 Nhắc lại khái niệm câu lệnh và khối lệnh 24

Trang 4

5.2 Toán tử if 24

5.3 else if 24

5.4 Toán tử switch 24

5.5 Toán tử goto và nhãn 24

5.6 Toán tử for 24

5.6 Toán tử while 25

5.7 do while 25

5.8 Lệnh break và lệnh continue 25

Chơng 6 Hàm và cấu trúc chơng trình 27

6.1 Khai báo và định nghĩa hàm 27

6.2 Các hàm void 28

6.3 Lời gọi hàm 29

6.4 Sử dụng hàm assert() để kiểm tra điều kiện trớc 29

6.5 Các đối số mặc định 29

6.6 Truyền tham số cho hàm 30

6.7 Hàm chồng(Overloaded function) 33

6.8 Các mẫu (template) 33

6.9 Hàm với các tham số là mảng 34

Chơng 7 Con trỏ, cấp phát động và hàm 36

7.1 Con trỏ và địa chỉ 36

7.2 Con trỏ và mảng một chiều 38

7.3 Con trỏ tới hàm 39

7.4 Khả năng đệ quy của hàm 40

7.5 Hàm main có đối (tham khảo tài liệu [2], trang 198) 40

Chơng 8 Cấu trúc 41

8.1 Kiểu cấu trúc 41

8.2 Truy nhập đến thành phần cấu trúc 42

8.3 Phép gán cấu trúc 42

8.4 Cấu trúc trong C++ 42

8.5 Thành phần kiểu fields 43

8.6 Union 43

Chơng 9 Thao tác trên tệp 44

Chơng 10 Quản lý màn hình văn bản 49

10.1 Chọn kiểu màn hình văn bản 49

10.3 Sự khác biệt giữa các hàm nhập xuất dữ liệu 50

10.4 Một số hàm thao tác màn hình khác 50

10.5 Ví dụ ứng dụng: Tạo thực đơn trên cửa sổ 50

Chơng 11 Đồ họa 54

11.1 Khái niệm về đồ họa 54

11.2 Độ phân giải màn hình đồ họa 55

11.3 Vẽ hình trong màn hình đồ họa 56

11.4 Đặt màu nền, màu vẽ, màu tô 56

11.5 Vẽ một số đờng và hình cơ bản 57

11.6 Cửa sổ (viewport) 59

11.7 Xử lý văn bản trên màn hình đồ họa 61

11.8 Tạo hình ảnh chuyển động 64

Chơng 12 Âm thanh, âm nhạc 66

Chơng 13 Tính đóng gói, thừa kế và đa hình 68

13.1 Mở đầu 68

Câu hỏi và bài tập ôn tập chuẩn bị cho thi hết môn 72

Phụ lục Các chơng trình mẫu 80

2

Trang 5

01 Tìm ớc số chung lớn nhất của 2 số nguyên 85

02 Chuyển đổi một số thập phân sang dạng nhị phân 85

03 Chuyển đổi một số thập phân sang số có cơ số bất kỳ 85

04 Chuyển đổi một số thập phân sang số có cơ số 11 86

05 Nhập và sắp xếp danh sách các số thực 87

06 Đảo lại một chuỗi ký tự 88

07 Một số chong trình đệ quy: tính giai thừa của một số nguyên không âm, tính số Fibonacci, tìm ớc số chung lớn nhất của hai số nguyên không âm, bài toán tháp Hà nội 88

08 Sàng Erastothen liệt kê các số nguyên tố không vợt quá một số tự nhiên n cho trớc 89

09 Tìm số lớn nhất trong dãy các số thực 90

10 Tìm xem một số thực x có xuất hiện trong dãy số thực hay không 91

11 Tính giá trị đa thức bậc n theo phơng pháp Horner 92

12 Tìm tổ hợp của các loại giấy bạc 92

13 Loại trừ các dấu cách thừa trong chuỗi tên (chỉ để lại một dấu cách) 93

14 Đếm số chữ trong chuỗi ký tự 93

15 Tính số theo công thức: 94

16 Nhập và in danh sách sinh viên (phiên bản 1) 96

17 Nhập và in danh sách sinh viên (phiên bản 2) 98

18 Nhập, sắp xếp và in danh sách sinh viên (phiên bản 3) 117

19 Nhập, sắp xếp, tìm kiếm và in danh sách sinh viên (phiên bản 4) 122

20 Nhập, sắp xếp, tìm kiếm và in danh sách sinh viên (phiên bản 5) 131

21 Nhập, sắp xếp, tìm kiếm và in danh sách sinh viên (phiên bản 6) 143

22 Danh sách cài đặt bằng danh sách liên kết (phiên bản 1) 145

23 Danh sách cài đặt bằng danh sách liên kết (phiên bản 2) 148

24 Danh sách cài đặt trên tệp (phiên bản 1) 151

25 Danh sách cài đặt trên tệp (phiên bản 2) 154

Tài liệu tham khảo 158

3

Trang 6

Chơng 1 Tổng quan về C và C++

1.1 Ngôn ngữ lập trình và thuật toán

1.1.1 Ngôn ngữ lập trình

Trong phần “Nhập môn tin học” chúng ta đã tìm hiểu Winword và Excel,

là các phần mềm ứng dụng trong công việc soạn thảo văn bản và làm các bảngtính toán đợc Đặc điểm của các phần mềm ứng dụng là luôn định rõ phạm

vi ứng dụng và cung cấp càng nhiều càng tốt các công cụ để hoàn thành chứcnăng đó Tuy nhiên ngời sử dụng cũng hầu nh bị bó buộc trong phạm vi quy

định của chơng trình Chẳng hạn ta khó có thể dùng Excel để giải một bàitoán gồm nhiều bớc tính toán nh tính nghiệm gần đúng một phơng trình viphân hay giải một hệ phơng trình tuyến tính Mặc dầu các phần mềm ứngdụng ngày càng nhiều và thuộc đủ các lĩnh vực nh xây dựng, thiết kế, hộihọa, âm nhạc nhng không thể bao trùm hết các vấn đề nẩy sinh trong thực

tế vô cùng phong phú Rõ ràng không chỉ những chuyên gia tin học mà ngaycả những ngời sử dụng, nhất là các cán bộ kỹ thuật, rất cần đến những phầnmềm uyển chuyển và mềm dẻo hơn, có khả năng thực hiện đợc nhiều hơncác chỉ thị của ngời sử dụng để giúp họ giải quyết những công việc đadạng bằng máy tính Phần mềm có tính chất nh thế đợc gọi là ngôn ngữ lập

trình Chính xác hơn ngôn ngữ lập trình là một ngôn ngữ nhân tạo bao

gồm một tập các từ vựng (mà ta sẽ gọi là từ khóa để phân biệt với ngôn

ngữ thông thờng) và một tập các quy tắc (gọi là Syntax - cú pháp) mà ta có

thể sử dụng để biên soạn các lệnh cho máy tính thực hiện

Nh ta đã biết, các ô nhớ của máy tính chỉ có thể biểu diễn các số 0 và 1 Vìvậy ngôn ngữ mà máy có thể hiểu trực tiếp là ngôn ngữ trong đó các lệnh làcác dãy số nhị phân và do đó đợc gọi là ngôn ngữ máy (machine language) Mọi ngôn ngữ khác đều phải thông dịch hoặc biên dịch sang ngôn ngữ máy(Interpreter - thông dịch và cho chạy từng lệnh Compiler - biên dịch thành 1chơng trình ngôn ngữ máy hoàn chỉnh, do vậy chạy nhanh hơn thông dịch)

Có nhiều loại ngôn ngữ lập trình, và hầu hết các nhà khoa học về máy tính

đều cho rằng không có một ngôn ngữ độc nhất nào có đủ khả năng phục vụcho các yêu cầu của tất cả các lập trình viên Theo truyền thống, các ngônngữ lập trình đợc phân làm 2 loại: các ngôn ngữ bậc thấp và ngôn ngữ bậccao

Ngôn ngữ lập trình bậc thấp (low-level programming language):

Ngôn ngữ máy, hợp ngữ (asembler: chơng trình dịch hợp ngữ, assemblylanguage: ngôn ngữ hợp ngữ) Hợp ngữ là ngôn ngữ một bậc từ ngôn ngữ máy

Nó chỉ khác với ngôn ngữ máy trong việc sử dụng các mã biểu thị các chứcnăng chính mà máy thực hiện

Lập trình bằng hợp ngữ rất phiền toái: có đến vài tá dòng mã cần thiết chỉ

để thực hiện phép cộng 2 con số Các chơng trình hợp ngữ rất khó viết;chúng không có cấu trúc hoặc modun hóa rõ ràng Chơng trình hợp ngữ cũngkhông dễ chuyển từ loại máy tính này sang loại máy tính khác Các chơngtrình này đợc viết theo các tập lệnh đặc thù của loại bộ vi xử lý nhất định.Lập trình bằng hợp ngữ thì mã gọn và chạy nhanh Do đó hầu hết các chơngtrình điều hành hệ thống đều đợc viết bằng hợp ngữ Tuy nhiên do sự phứctạp của công việc lập trình nên các hãng sản xuất phần mềm chuyên dụng

Trang 7

thích viết chơng trình bằng ngôn ngữ C (do Bell Laboratories của hãng AT&Txây dựng) là loại ngôn ngữ kết hợp đợc cấu trúc của ngôn ngữ bậc cao hiện

đại với tốc độ và tính hiệu quả của hợp ngữ bằng cách cho phép nhúng cáclệnh hợp ngữ vào chơng trình

Ngôn ngữ lập trình bậc cao:

Các ngôn ngữ lập trình bậc cao nh Basic, Pascal, C, C++ cho phép các lậptrình viên có thể diễn đạt chơng trình bằng các từ khóa và các câu lệnh gầngiống với ngôn ngữ tự nhiên Các ngôn ngữ này dợc gọi là “bậc cao” vì chúnggiải phóng các lập trình viên khỏi những quan tâm về từng lệnh sẽ đợc máytính tiến hành nh thế nào, bộ phận thông dịch hoặc biên dịch của chơngtrình sẽ giải quyết các chi tiết này khi mã nguồn đợc biến đổi thành ngônngữ máy Một câu lệnh trong ngôn ngữ bậc cao tơng ứng với một số lệnhngôn ngữ máy, cho nên bạn có thể thảo chơng theo ngôn ngữ bậc cao nhanhhơn so với bậc thấp Tuy nhiên bạn cũng phải trả giá cho việc này Chơng trìnhngôn ngữ máy đợc dịch ra từ mã nguồn đợc viết bằng ngôn ngữ bậc cao chứarất nhiều chi tiết thừa, do đó tốc độ chạy sẽ chậm hơn nhiều so với chơngtrình viết bằng hợp ngữ Thông thờng một trình biên dịch đặc trng thờngsinh ra số lệnh mã máy gấp 2 lần hay nhiều hơn số lệnh cần thiết nếu viếtbằng mã máy

Ngôn ngữ khai báo: Ngôn ngữ sẽ định nghĩa một loạt các yếu tố và các quan

hệ, đồng thời cho phép bạn có thể tiến hành xếp hàng đối với những kết quảxác định Thí dụ: Prolog, SQL (Structured Query Language)

Điều then chốt trong việc lập trình chuyên dụng là môdun hóa ngôn ngữ - đó

là sự phát triển sao cho nhiệm vụ lập trình có thể phân phối đợc cho cácthành viên của một nhóm lập trình, và kết quả đạt đợc là các bộ phận khácnhau sẽ hoạt động phù hợp với nhau khi nhiệm vụ của từng ngời hoàn thành.Ngôn ngữ lập trình môdun, nh Module-2 hoặc ngôn ngữ hớng đối tợng nh C++, sẽ cho phép từng lập trình viên có thể tập trung vào việc lập mã, biên dịch

và gỡ rối các module chơng trình riêng biệt, đồng thời có thể cho chạy (kiểmtra thử) riêng từng module của mình Khi từng module riêng đã chạy tốt chúng

sẽ đợc liên kết với nhau mà không gây trục trặc nào

1.1.2 Thuật toán (Algorithm)

Thuật ngữ Algorithm đợc dịch ra tiếng Việt là thuật toán, thuật giải hoặc giảithuật ở đây chúng tôi dùng từ thuật toán là cách gọi quen thuộc với nhiều ng-ời

Thuật toán là một dãy hữu hạn các bớc, mỗi bớc mô tả chính xác các phép toán hoặc hành động cần thực hiện, để giải quyết một vấn đề.

Để hiểu đầy đủ ý nghĩa của khái niệm thuật toán, chúng ta nêu ra 6 đặc

tr-ng sau đây của thuật toán:

1 Input Mỗi thuật toán thờng có một số dữ liệu vào

2 Ouput Mỗi thuật toán thờng có một số dữ liệu ra.

Trang 8

3 Tính xác định (Definiteness) Mỗi bớc đợc mô tả chính xác, chỉ có một

cách hiểu duy nhất và đủ đơn giản để có thể thực hiện đợc

4 Tính dừng (Finiteness) Thuật toán phải dừng sau một số hữu hạn bớc thực hiện

5 Tính hiệu quả (Effectiveness) Các phép toán trong các bớc phải đủ đơn

giản để có thể thực hiện đợc

6 Tính tổng quát (Generalness) Thuật toán phải có tính tổng quát, có thể

áp dụng cho một lớp đối tợng

Ngợc lại (r>0) m:=n; n:=r và quay lại bớc 1

1.1.3 Sự ra đơi và phát triển của ngôn ngữ C

Năm 1970 Ken Thompson sáng tạo ra ngôn ngữ B dùng trong môi trờng hệ

điều hành UNIX trên máy điện toán DEC PD-7 B là ký tự đầu của cụm chữviết tắt BCPL (Basic Combined Programming Language) do Martin Richardsviết Năm 1972 Dennis Ritchie của hãng Bell Laboratories (và Ken Thompson)sáng tạo nên ngôn ngữ C nhằm tăng hiệu quả cho ngôn ngữ B Lúc đầu ngônngữ C không đợc mọi ngời a dùng Nhng sau khi D.Ritchie cho xuất bản cuốn

"The C Programming Language" thì ngôn ngữ C đợc chú ý và đợc sửdụng rộng rãi Ngời ta đã dùng C để viết hệ điều hành đa nhiệm UNIX, O/S

2 và ngôn ngữ Dbase C đã đợc cải tiến qua nhiều phiên bản: trình biêndịch Turbo C từ phiên bản 1 đến phiên bản 5, Microsoft C từ phiên bản 1

đến phiên bản 6 Hiện nay, C lại đợc phát triển để thành C++ với 3 trìnhbiên dịch: Borland C++ (dùng trong DOS và trong Windows), Visual C++(dùng trong DOS và trong Windows) và Turbo C++ (dùng trong DOS) Có thểnói rằng hiện nay hầu hết các phần mềm ứng dụng đều đợc viết trực tiếphoặc gián tiếp bằng C hoặc C++

Trong tài liệu này chúng tôi sẽ giới thiệu C và một số lệnh của C++

1.2 Các phần tử cơ bản trong ngôn ngữ C

1.2.1 Bộ ký tự (character set)

1.2.2 Các từ khóa (key words, reserved words)

Các từ khóa thông dụng trong C

continue extern int sizeof union volatile

1.2.3 Tên và cách đặt tên (identifier)

Đối với C, mọi tên cần phải khai báo trớc khi sử dụng Tên ta dãy các ký tự liềnnhau, bắt đầu bằng ký tự hoặc dấu gạch dới, tiếp theo là các ký tự, các số

Trang 9

hoặc dấu gạch dới

Chú ý: Tên không chứa dấu cách C phân biệt chữ hoa và chữ thờng

1.2.4 Lời giải thích (comment)

Lời giải thích từ một vi trí đến cuối dòng: //

Lời giải thích trên một hoặc nhiều dòng: /* */

Hiện câu chào

//002CHAO1.cpp Hien cau chao tren man hinh

Thông thờng một chơng trình C đầy đủ có các phần sau:

 Chỉ dẫn tiền xử lý (preprocessor directive)

- Các bao hàm (#include)

- Các vĩ lệnh (#define)

 Khai báo toàn cục

- Khai báo các nguyên mẫu cho hàm (function prototype)

- Khai báo các biến toàn cục

Trang 10

 Hàm main()

 Định nghĩa chi tiết các hàm do ngời sử dụng vừa khai báo trên

Phần "Định nghĩa chi tiết các hàm " có thể đặt ở ngay sau phần khai báotoàn cục

iomanip.h setw,setprecision, (cout<<oct<<a<<hex<<b;)

1.3.2 Soạn thảo và chạy một chơng trình C

a Soạn thảo chơng trình

Mỗi câu lệnh của C có thể viết trên một dòng hay nhiều dòng nhng phải kết

thúc bằng dấu ; Tuy nhiên khi nhập một chuỗi ký tự mà muốn chuyển sang dòng khác ta phải thêm dấu \ trớc khi xuống dòng

b Dịch và chạy chơng trình

Khi nhấn F9 thì đầu tiên chơng trình đợc dịch sang tệp có đuôi là *.obj,sau đó liên kết các tệp và dịch sang tệp có đuôi *.exe có thể chạy đợctrong môi trờng DOS

Khi dịch chơng trình có thể xuất hiện 3 loại lỗi sau đây:

Lỗi đ ợc thông báo bởi từ khóa error (lỗi cú pháp) :

Lỗi này thờng xảy ra do khi ta soạn thảo chơng trình không tuân theo đúngnhững quy tắc của C, thí dụ int thì ta gõ thành Int; hay ta gõ thiếu ngoặc

đơn, ngoặc kép chẳng hạn

Sau đây là một số thông báo lỗi thờng gặp loại này

Unknown preprocessor directive

Chỉ thị tiền xử lý không đúng Trong trờng hợp này bạn phải xem lại các lệnh

#include xem bạn có viết sai không

Declaration terminated incorrectly

Khai báo kết thúc không đúng Ví dụ bạn đánh dấu ; sau hàm main nh sau:

void main();

chẳng hạn Nên lu ý là sau tên hàm không đợc đánh dấu ; nh trên đây Sau

tên hàm phải là dấu { và kết thúc hàm là dấu }.

Unexpected }

Trang 11

Thừa dấu } Mỗi lần đánh dấu { thì bạn nên đánh dấu } rồi sau đó gõ các lệnh vào đoạn giữa, nh vậy tránh đợc tình trạng thừa thiếu dấu { hoặc }.

Compound statement missing }

Thiếu dấu }.

Declaration syntax error

Khai báo sai Ví dụ bạn viết

int a,b

printf("Chao");

thì máy báo lỗi ở dòng thứ 2 Sở dĩ nh vậy là vì khi đọc qua dòng thứ nhấtkhông có dấu ; máy cho rằng lệnh cha kết thúc và còn chuyển tiếp sang dòngthứ 2 Tuy nhiên sang dòng thứ 2 thì máy lại thấy lệnh không phù hợp nên báolỗi ở dòng này Cách viết trên đây tơng đơng với cách viết:

int a,b printf("Chao");

Và máy thấy rằng đây là một lệnh không đúng Còn nếu ta sử lại các lệnhtrên là

int a,b

;printf("Chao");

thì máy không còn báo lỗi nữa vì nó chuyển xuống dòng thứ 2 gặp dấu ;

và biết là lệnh int a,b; đợc khai báo đúng.

Undefined symbol

Bạn đã sử dụng một biến nào đó mà cha khai báo Ví dụ bạn cha khai báo biến

n nhng lại sử dụng trong lệnh:

printf("%d",n);

chẳng hạn thì máy báo là Undefined symbol 'n'

Function should have a prototype

Ví dụ trong lệnh trên bạn viết sai là

prinf("%d",n);

thì máy báo là Function 'prinf' should have a prototype Nghĩa của câu nàylà: hàm prinf cần phải có nguyên mẫu

Lỗi đ ợc thông báo bởi từ khóa Warning (lỗi cảnh báo) :

Lỗi này thờng xảy ra do khi ta khai báo biến nhng không sử dụng tới

Ví dụ

is assigned a value that is never used

Khai báo và đã gán giá trị cho biến nhng không sử dụng

Ví dụ bạn viết các lệnh

int n; n=10;

nhng trong các phần tiếp theo không sử dụng n (để hiện ra màn hìnhchẳng hạn, hay dùng để tính giá trị của biến khác ) thì máy báo là

'n' is assigned a value that is never used

tuy nhiên đây chỉ là thông báo (warning) Khi bạn nhấn F9 để dịch chơngtrình thì máy vẫn báo là success

Hai loại lỗi trên đây đợc thông báo ngay khi dịch chơng trình thành file *.obj

Loại lỗi thứ 3 có thể xảy ra trong quá trình liên kết:

Lỗi này thờng xảy thí dụ khi có lời gọi hàm nhng hàm chỉ mới có nguyên mẫu

Trang 12

mµ cha cã khai b¸o chi tiÕt.

Trang 13

Chơng 2 Hằng, biến và mảng

2.1 Các kiểu dữ liệu cơ sở

C có một số kiểu dữ liệu cơ sở nh sau:

Mã ASCII 0 1 127 128 129 254 255

Giá trị biến kiểu char 0 1 127 -128 -127 -2 -1

Giá trị biến kiểu

Phân loại ký tự:

Các ký tự có thể phân làm 3 nhóm: 0-31,32-126, 127-254; trong đó các ký tự

từ 0 đến 32 là các ký tự điều khiển, không thể nhìn thấy trên màn hình

Chú ý:Trong chơng trình một ký tự phải đợc bao trong dấu nháy đơn Thí dụchar ch='A'; ch='1' sẽ cho ta ch=49, còn ch=1 lại cho ta ch biểu diễn ký tự coamã ASCII là 1

Trang 14

3 Kiểu dấu phẩy động

float chiếm 4 byte, double chiếm 8 byte

Chú ý Khi hiện một số nguyên dới dạng bát phân bằng lệnh printf() ta dùng

khuôn dạng % và chữ 0, còn với dạng thập lục phân thì dùng % và ký tự x(in thờng hoặc in hoa) Ví dụ

printf("%o",9) hoặc printf("%x",17) cho kết quả trên màn hình là 11

printf("%o",011) hoặc printf("%x",0x11) cho kết quả trên màn hình là 11

3 float và double (số thực và số thực có độ chính xác gấp đôi)

Là một dãy ký tự bất kỳ đặt trong 2 dấu "", thí dụ "Ha noi"

Chú ý: 'a' là hằng ký tự gồm một byte, còn "a" là hằng xâu ký tự gồm 2 byte,

1 byte chứa ký tự a, byte cuối cùng chứa ký tự '\0' là ký tự báo kết thúc

xâu.

Chú ý:

Khi ta dùng hàm strlen(st) để xác định độ dài của chuỗi ký tự thì ký tự '\0'

Trang 15

không đợc tính vào độ dài này Thí dụ 3 biến st1,st2,st3 sau đây đều có

Giả sử ta khai báo:

#define str "Ha Noi"

const float a=10.123;

const char str2[]="Hai Phong";

const char *str3="Tay Ho";

Không nên dùng const char str2[5]= "Hai Phong" chẳng hạn, vì có thể độ dàicủa hằng vợt quá độ dài định nghĩa

Chú ý: Hằng có thể là các biến chiếm dụng bộ nhớ thí dụ int m =10; nhng cũng

có thể là những giá trị tạm thời, không đợc phân phối bộ nhớ thí dụ M_PI, M_E,printf("\n%s","Ha Noi");

Trang 16

Tuy nhiên theo cách này thì các con số 2, 3, không cho ta ý nghĩa gợi nhớ

đó là các ngày trong tuần C cho ta ta định nghĩa biến kiểu liệt kê phục vụcho mục đích này Ta có thể làm nh sau

enum ngay_tt {hai, ba, tu, nam, sau, bay, chunhat};

ngay_tt i;

for(i=hai;i<=chunhat;i++) {các lệnh}

Giả sử các lệnh là printf("%d ",i); thì ta có kết quả là 0 1 2 3 4 5 6

Vì biến enum thực chất là biến nguyên, do đó các dòng lệnh trên có thể viết

đơn giản hơn nh sau:

enum {hai, ba, tu, nam, sau, bay, chunhat};

int i;

for(i=hai;i<=chunhat;i++) [lệnh]

Ta có thể khởi gán các giá trị cho biến enum Ví dụ nếu ta viết:

enum {hai=2, ba, tu, nam, sau, bay, chunhat};

thì khi đó ta sẽ có hai=2,ba=3,

2.4 Biến

Mọi biến phải đợc khai báo trớc khi sử dụng Việc khai báo đợc thực hiện theomẫu sau:

<Kiểu biến> <tên biến 1>,<tên biến 2>, ,<tên biến n>;

Có thể khai báo ngay khi sử dụng, thí dụ

for(int i=0;i<n;i++) [các lệnh]

1 Vị trí của các khai báo

Trong C++ thì biến có thể khai báo tại vị trí bất kỳ trong chơng trình

2 Khởi đầu cho các biến

float a=10.123;

char str2[]="Hai Phong";

char *str3="Tay Ho";

int x[] = {1,2,3};

float y[4] = {1.2, 3.2, 4.3, 6.5};

Nhng không thể viết:

float *py = {1.2, 3.2, 4.3, 6.5};//Viết nh thế này là sai.

Nhng với chuỗi thì lại đợc:

char st1[]="123";

char st2[7]="123";

char *st="123";

3 Lấy địa chỉ của biến

Mỗi biến đợc cấp phát một vùng nhớ gồm một số byte liên tiếp Địa chỉ củabyte đầu tiên là địa chỉ của biến Địa chỉ của biến có thể nhận đợc bằngphép toán

Trang 17

p=&(k+1);//Dòng lệnh này sai

Ta chỉ có thể gán một con trỏ bằng địa chỉ của một biến cùng kiểu với nó Ví

dụ phép gán sau là sai:

int *p;

const int m=10;

p=&m;//Dòng lệnh này sai

Phải sửa lại là

Để có thể lu trữ và thực hiện các phép toán trên các giá trị địa chỉ, C địnhnghĩa một kiểu biến nguyên đặc biệt mà giá trị của chúng là địa chỉ củacác biến và gọi biến này là con trỏ Khi định nghĩa con trỏ ta phải chỉ rõ đó

là con trỏ của biến loại gì Thí dụ để khai báo một con trỏ kiểu nguyên taviết

int *p;

Và khi đó ta có thể gán p = &x; trong đó x là biến nguyên nào đó

4 Lấy giá trị của một biến thông qua địa chỉ

Giả sử ta p là một con trỏ Khi đó *p sẽ là giá trị đợc chứa trong vùng bộ nhớ

mà p trỏ tới

Nh vậy với biến x bất kỳ thì ta có *&x chính là giá trị x

Trang 18

2.5 Mảng và chuỗi

Trong phần trên ta hiểu biến là một vùng bộ nhớ đợc đặt tên và có thể lu trữmột kiểu giá trị nào đó Để biểu diễn nhiều giá trị ta phải dùng nhiều biến.Tuy nhiên nhiều khi số biến lại phụ thuộc một tham số nào đó Thí dụ sốthành phần của một vectơ phụ thuộc vào một số n, còn số các phần tử củamột ma trận lại phụ thuộc số hàng và số cột Trong những trờng hợp này ngời tadùng một kiểu dữ liệu có cấu trúc là mảng để biểu diễn số liệu Mảng là mộttập hợp nhiều phần tử có cùng một kiểu giá trị và có chung một tên Về mặtnào đó có thể coi mảng cũng là biến, nhng là biến có cấu trúc phức tạp hơn

Định nghĩa mảng

Khai báo int a[10] sẽ dành 10 vị trí liên tiếp trong bộ nhớ, mỗi vị trí gồm 2byte có thể lu trữ đợc một số nguyên và các vị trí này tơng ứng là a[0],a[1], , a[9]

Khai báo int a[8][10] sẽ dành 80 vị trí liên tiếp trong bộ nhớ, mỗi vị trí gồm

2 byte có thể lu trữ đợc một số nguyên và các vị trí này tơng ứng là a[0][0],a[0][1], , a[0][9], a[1][0], a[1][1], , a[1][9], , a[7][0], a[7][1], , a[7][9]

Chú ý: Khi ta khai báo một mảng có kích cỡ định trớc, thí dụ

int a[10]; thì a là một hằng địa chỉ, do đó ta không thể gán a = <địachỉ> Tuy nhiên nếu ta định nghĩa một biến con trỏ, thí dụ int *pn; thì ta

có thể dùng phép gán cho pn Với một chuỗi

char *s="123"; chẳng hạn, ta có s là địa chỉ của biến đầu tiên của chuỗi,tức là s[0], do đó *s chính là giá trị của s[0], còn *(s+1) là giá trị củas[1],

2.6 Định nghĩa kiểu bằng typedef

Các khối lệnh lồng nhau, phạm vi hoạt động của các biến:

Khối lệnh là tập hợp các lệnh đợc bao trong hai dấu { } Khối lệnh có thể

Trang 19

gồm nhiều khối lệnh khác Một biến đợc khai báo trong khối lệnh thì miền tácdụng của nó là khối lệnh trong cùng chứa khai báo của biến đó Nếu có cácbiến cùng tên thì biến đợc khai báo sau cùng sẽ là biến tích cực, tức là thực sựtham gia trong mọi phép toán có tên biến chung

2 Phạm vi hoạt động và thời gian tồn tại

Biến tự động chỉ tồn tại trong khối lệnh mà nó đợc định nghĩa

3.Khởi đầu cho biến và mảng tự động

Biến ngoài (toàn cục) khi khai báo thì đợc tự động gán bằng 0 hoặc rỗng.Nhng với biến tự động khi khai báo xong mà không gán giá trị khởi đầu hoặcgán giá trị thì giá trị không xác định, là một giá trị vô nghĩa nào đó

Khác với C, trong C++ có thể khởi đầu cho mảng hoặc biến, thí dụ

Trang 20

2 Phạm vi hoạt động và thời gian tồn tại

Biến ngoài tồn tại từ vị trí đợc khai báo cho đến hết chơng trình

đó thì biến luôn đợc hiểu là biến địa phơng

Ví dụ sau minh họa cho điều này:

Trang 21

3 Khởi đầu cho biến và mảng ngoài

Biến ngoài (toàn cục) khi khai báo thì đợc tự động gán bằng 0 hoặc rỗng.Quy tắc khai báo và khởi đầu cũng giống nh biến tự động Tuy nhiên với biến

tự động thì sau khi khai báo biến có thể nhận một giá trị vu vơ nào đó

Trang 22

Chơng 3 Biểu thức

3.1 Khái niệm biểu thức(expression)

Biểu thức là một giá trị đợc tạo nên do sự kết hợp các phép toán với các hằng,biến, phần tử mảng, hàm Nh vậy bản thân các hằng, biến, phần tử mảng,hàm cũng là các biểu thức

| : Phép tuyển các bit, ví dụ 3 | 5 =7

^ : Phép tuyển có loại trừ, ví dụ 3 ^ 5 = 6

<< :Phép dịch trái (dịch dãy bit k vị trí về phía trái dấu phẩy, tức là nhân

số dịch chuyển với 2k ), ví dụ 11 << 2 = 44 (1011 -> 101100)

m<<k = m* 2k

>> :Phép dịch phải (dịch dãy bit k vị trí về phía phải dấu phẩy, tức là chia

số dịch chuyển cho 2k), ví dụ 11 >> 2 = 2 (1011 -> 10)

m>>k = m/ 2k

~ : Phép lấy phần bù (trong chuỗi bit 0 -> 1 và ngợc lại)

3.4 Các phép toán quan hệ và logic

Trang 23

3.8 BiÓu thøc ®iÒu kiÖn

Trang 24

Chơng 4 Vào ra

4.1 Hàm printf

int printf(const char *dk, [danh sách các đối]);

Đối dk là con trỏ kiểu char chứa địa chỉ của chuỗi điều khiển

1 Chuỗi điều khiển gồm 3 loại ký tự:

- Các ký tự điều khiển nh: \n Xuống dòng, \t Dấu tab

- Các đặc tả chuyển dạng và tạo khuôn (gọi tắt là đặc tả)

- Các ký tự để hiển thị ra màn hình Đối với một số ký tự đặc biệt nh dấu ', '',

b Dấu trừ (-): Nếu có dấu - thì dồn trái, không có thì dồn phải

c pp chỉ nên dùng cho số thực pp là số chữ số sau dấu chấm thập phân,nếu không có thì đợc hiểu là pp=6

d Ký tự chuyển dạng: quy định dạng in ra của đối tợng, thí dụ d là sốnguyên, f là số thực, o là số bát phân, x là số thập lục phân

Bảng các ký tự chuyển dạng

Ký tự chuyển

Trang 25

Trong đó giá trị 19.25 là giá trị của biến thực ns, ta viết:

printf("\nNang suat tang %5.2f%",ns);

Giả sử ta cần in ra

Năng suất tăng 19.25% trong năm 2000

Trong đó giá trị 19.25 là giá trị của biến thực ns, 2000 là giá trị của biếnnguyên nam có thể thay đổi tuỳ thuộc từng trờng hợp, nếu ta viết:

printf("\nNang suat tang %5.2f% trong nam %4d",ns,nam);

thì về mặt cú pháp là đúng nhng lệnh không in ra điều ta mong muốn.Trong trờng hợp này ta nên tách làm 2 lệnh:

printf("\nNang suat tang %5.2f%",ns);

printf(" trong nam %4d",nam);

2 Danh sách các đối

Các đối cần đợc phân cách nhau bởi dấu phẩy Đối có thể là hằng, biến, hàmhay là kết hợp của chúng bằng các phép toán Vậy các đối chính là các biểuthức Nói chung có bao nhiêu đặc tả thì có bấy nhiêu đối Nếu số đối nhiềuhơn số đặc tả thì các đối không có đặc tả tơng ứng sẽ bị bỏ qua Còn nếu

số đối ít hơn số đặc tả thì máy sẽ bị rối và có thể dẫn đến những kết quảsai

4.2 Hàm scanf

int scanf(const char *dk, [danh sách các đối]);

1 Danh sách các đối

Các đối cần đợc phân cách nhau bởi dấu phẩy Đối phải là một con trỏ chứa

địa chỉ của một biến nào đó Vì tên của chuỗi ký tự là địa chỉ nên khôngcần dấu lấy địa chỉ đứng trớc tên chuỗi

2 Chuỗi điều khiển

Gồm các ký tự đặc tả chuyển dạng Mỗi đặc tả thờng có một đối tơng ứng

phần đặc tả có dạng tổng quát nh sau:

Trang 26

Nói chung đặc tả chỉ gồm ký tự % và đặc tả chuyển dạng đợc thống kêtrong bảng sau:

Bảng các ký tự chuyển dạng

Ký tự chuyển

f hoặc e float Số dấu phẩy động

lf hoặc le double Số dấu phẩy động

g (Không có) Không có dạng này

Chú ý: Ký tự chuyển dạng của số nguyên không âm hệ 8 là chữ o, số nguyên không âm hệ 16 là ox; nhng biểu diễn số nguyên không âm hệ 8 bắt đầu bằng số 0, còn số hệ 16 thì bắt đầu bằng số 0 và chữ x.

Các dòng nghiêng và đậm chính là sự khác biệt giữa hàm scanf và printf

Ta có thể nhập các trờng vào liên tiếp nhau, sao cho mỗi trờng cách nhau ítnhất một khoảng trắng Trong đó khoảtng trắng đợc hiểu là dấu cách, dấutab hoặc dấu xuống dòng Nh vậy giữa các trờng vào có thể chứa một sốkhoảng trắng tuỳ ý Nh vậy ta không thể nhập một chuỗi ký tự có chứakhoảng trắng

Ví dụ về hàm scanf:

Trang 27

int n;float a;double b;char st[5]

scanf("%d%f%lf%s",&n,&a,&b,st);

Nh vậy có thể thấy sự khác biệt của chuỗi điều khiển trong hàm printf và hàm scanf là: chuỗi điều khiển trong hàm printf có thể coá 3 thành phần: các ký tự điều khiển, các ký tự đặc tả và các ký tự hiện trên màn hình; còn trong lệnh scanf thì chỉ có các ký tự đặc tả.

4.3 Đa ra máy in- hàm fprintf

int fprintf(stdprn,const char *dk, [danh sách các đối]);

Tất cả những điều đã nói ở lệnh printf đều đúng Chỉ có một điểm khácbiệt: trong lệnh printf thiết bị ra là màn hình còn với lệnh fprintf thì thiết bị

ra là máy in

4.4 Dòng vào stdin và các hàm nhập dữ liệu

Trớc hết ta hãy chạy thử đoạn chơng trình đơn giản sau:

Nếu ta gõ a  thì lệnh scanf thứ 2 bị bỏ qua

Lệnh printf tiếp theo chỉ hiện lên màn hình ký tự

Predefined streams automatically opened when the program is started.

Name Meaning stdin

stdout stderr stdaux stdprn

Standard input device Standard output device Standard error output device Standard auxiliary device Standard printer

Khi gặp một lệnh nhập số liệu và ta bắt đầu gõ từ bàn phím thì các ký tự

đợc gửi vào stdin Chơng trình sẽ chờ cho đến khi ta gõ phím  báo hiệukết thúc lệnh nhập số liệu thì chơng trình bắt đầu đọc các ký tự từ stdin

để gán cho các trờng nhập Nếu số liệu trong stdin cha đủ thì chơng trìnhlại dừng để ta nhập tiếp Còn nếu số liệu có nhiều hơn thì chơng trình chỉlấy vừa đủ để gán cho các trờng vào, phần còn lại vẫn còn lại trong stdin Khigặp lệnh nhập số liệu tiếp theo thì trớc hết chơng trình xem trong stdin có

Trang 28

số liệu không, nếu có đủ số liệu thì chơng trình lấy ngay các số liệu đó đểgán cho trờng vào mới và lệnh nhập số liệu đó bị bỏ qua Ta có cảm giác làlệnh không đợc thực hiện nhng thực ra đã đợc thực hiện nhng có thể không

nh ý ta muốn

Trở lại đoạn chơng trình trên đây Khi nhập số liệu cho ca ta đã gõ a vànhấn  thì cả ký tự a và ký tự  (\n, LF có mã là 10) đều đợc đa vàostdin Lệnh scanf đọc ký tự a từ stdin nhng không loại ký tự \n ra khỏi stdin

Do vậy khi tới lệnh scanf tiếp theo thì chơng trình lấy ngay giá trị \n để gáncho cb mà không cần chờ ngời sử dụng nhập số liệu mới Khi hiện ra mànhình thì ký tự \n không nhìn thấy do đó ta chỉ thấy chữa a mà thôi Nếubây giờ ta sửa lại lệnh printf thành

ta nhập tiếp dữ liệu cho lệnh scanf tiếp theo

Trang 29

int getc(FILE *stream);

int putc(int c, FILE *stream);

int getch(void);//Nhận ký tự trực tiếp từ bàn phím, ký tự không hiện trên màn hình

int getche(void); //Nhận ký tự trực tiếp từ bàn phím, ký tự hiện trên màn hình

int putch(int ch); //Màu tuỳ thuộc vào lệnh textcolor

int getchar(void);//Nhận ký tự từ stdin

int putchar(int c); //Luôn hiện màu đen trắng

char *gets(char *s);

int puts(const char *s);

Các hàm scanf, cin chỉ nhập đợc chuỗi không có dấu cách.

Hàm gets nhập đợc chuỗi chứa dấu cách: Nhận dãy ký tự từ stdin cho đến

khi gặp ký tự '\n' Ký tự '\n' bị loại khỏi stdin nhng không đợc đặt vào cuối chuỗi Chuỗi đợc bổ sung ký tự kết thúc '\0'

Các hàm printf, cout và puts có thể hiện đợc các chuỗi có chứa dấu cách

4.6 Một số hàm xử lý chuỗi

strcmp(st1,st2)>0 nghĩa là st1>st2, phân biệt chữ hoa chữ thờng

strcmpi(st1,st2)>0 nghĩa là st1>st2, không phân biệt chữ hoa chữ thờngstrcat(st1,st2) ghép st2 vào st1

char* strchr(char *s, int kt);

Tìm lần xuất hiện đầu tiên của kt trong s Nếu tìm thấy trả về địa chỉ của

ký tự tìm đợc, nếu không trả về NULL

strcpy(st1,st2); thục chất là gán st1=st2;

strlen(st); cho độ dài chuỗi st.strlwr(st) chuyển thành chữ thờng (giốngtolower(ch) đối với ký tự)

strupr(st);

4.7 Sự khác biệt giữa mảng và chuỗi

 Trớc hết ta chạy thử đoạn chơng trình sau đây

Trang 30

Đây là điểm khác biệt giữa chuỗi và mảng Nếu với mảng ta chỉ có thểnhập số liệu và cho hiện từng phần tử của mảng thì nếu ta cũng đòi hỏi

nh vậy với chuỗi thì sẽ làm cho công việc lập trình rất rắc rối Chuỗi có thểxem nh mảng, nhng đồng thời phải đợc truy xuất nh một phần tử Khôngthể thao tác với tên ngời, tên địa danh mà coi nh hợp thành của nhiều phần

tử, mỗi phần tử là một ký tự đợc Chính vì vậy các nhà sáng tạo ngôn ngữ

C đã chọn một trong 2 ký hiệu &b và b một ký hiệu dùng để thao táctoàn bộ chuỗi Vì vậy khi dùng lệnh

scanf("%s",b); ta có thể nhập toàn bộ chuỗi

còn lệnh

printf("%s",b); sẽ in toàn bộ chuỗi

Nếu b là mảng thì các lệnh trên đây không thực hiện đợc và máy sẽ báolỗi

 Ta có thể khởi đầu các giá trị cho chuỗi ký tự nh ví dụ sau

Trang 31

4.8 Các hàm vào ra và dịch chuyển vị trí trên màn hình

Hàm gotoxy(cm,rn); sẽ đa con trỏ đến vị trí ở cột thứ cm và hàng thứ rntrên màn hình

Hàm kbhit() nhận giá trị 1 nếu có phím đợc bấm

4.9 Các luồng nhập xuất cin,cout

C++ cung cấp các dòng (stream đợc chứa trong iostream.h) cin và cout đểnhập xuất số liệu Sau đây là vài ví dụ:

Trang 32

Ch¬ng 5 C¸c to¸n tö ®iÒu khiÓn

5.1 Nh¾c l¹i kh¸i niÖm c©u lÖnh vµ khèi lÖnh

Trang 33

1 Nếu có [các lệnh A] thì thực hiện các lệnh này Nếu phần này gồmnhiều lệnh thì các lệnh cách nhau bằng dấu , (chứ không phải là dấu ;), ví

dụ các lệnh A có thể là int i=1, int j=2; Sau khi thực hiện các lệnh A thìchuyển sang bớc thứ 2 sau đây

2 Xác định [biểu thức B], nếu biểu thức này sai thì kết thúc lệnh for

tức là chuyển sang bớc 4, nếu B đúng thì thực hiện [lệnh D] sau đóchuyển sang bớc 3 sau đây

3 Thực hiện các lệnh C, (thông thờng các lệnh này làm thay đổi giá trị biểuthức B), trở lại bớc 2 Ví dụ có thể là i++, hoặc i++, j++

4 Kết thúc lệnh for, tức là chuyển sang thực hiện [lệnh E] ngay sau lệnh for

Nh vậy nếu [biểu thức B] luôn luôn đúng thì vòng lặp sẽ vô hạn Trong trờnghợp [biểu thức B] vắng mặt chẳng hạn, thì đợc hiểu là biểu thức B luônluôn đúng Trong phần B có thể không phải là một biểu thức duy nhất, mà cóthể có các biểu thức cách nhau bằng dấu , ví dụ i<10, j<20 Lúc này biểuthức B đợc hiểu là i<10 && j<20

Trang 35

Chơng 6 Hàm và cấu trúc chơng trình 6.1 Khai báo và định nghĩa hàm

Tơng tự nh một biến, một hàm phải khai báo trớc khi nó đợc gọi Một khai báohàm có 3 phần: Kiểu cho ra, tên và danh sách tham số

Hàm có vai trò ngang nhau, C++ không cho phép xây dựng một hàm bên trong hàm khác

Ví dụ: Khai báo hàm:

double power(double x, int n);

Trong đó double là kiểu cho ra, power là tên của hàm và (double x,int n) làdanh sách các tham số Hàm này có 2 tham số là x và n Các tham số này còn

đợc gọi là các tham số hình thức Danh sách các tham số có thể trỗng, nhngcác dấu ngoặc đơn vẫn cần thiết Một khai báo hàm còn đợc gọi là cácnguyên mẫu hàm (prototype) Phần này chứa các thông tin tối thiểu mà bộ biêndịch cần để biên dịch các lệnh gọi đến hàm Vì vậy trong phần khai báo cóthể bỏ bớt tên các tham số chẳng hạn nh:

double max(double,double);

Tuy nhiên nếu biến là mảng thì không thể bỏ tên biến đợc Ta chỉ có thểviết một cách đơn giản hơn, ví dụ

int x[],float y[][10]

chẳng hạn Lu ý là với mảng 2 chiều phải có thông tin về số cột

Phần khai báo phải ở vị trí trớc lời gọi hàm trong chơng trình Tuy nhiên

nh ta có thể thấy, phần khai báo cha đủ để xác định một hàm Hàm còn cóphần định nghĩa nằm ở vị trí bất kỳ trong chơng trình (tất nhiên là khôngphải bên trong một hàm khác)

 Nếu định nghĩa hàm nằm trớc lời gọi nó thì không cần khai báo mẫu nữa

 Trong thân hàm có thể khai báo các biến cục bộ Các biến này không đợc

trùng tên với các tham số Trong thân hàm ta có thể sử dụng các tham số mà

không khai báo lại Nếu ta khai báo lại thì chơng trình sẽ báo lỗi

 Trong phần định nghĩa hàm không đợc bỏ tên các tham số nh trong phầnkhai báo

 Nếu hàm có kiểu cho ra thì cuối thân hàm phải có lệnh return <biểuthức>; trong đó <biểu thức> có cùng kiểu giá trị với hàm Trong thân hàm

có thể có một hoặc nhiều lệnh return <biểu thức>; Khi chơng trình gặp

Lập trình C và C++ - Chơng 5 Các toán tử điều khiển

Trang 36

lệnh này thì giá trị hàm đợc trả về và chơng trình thoát khỏi hàm.

 Tên hàm cũng là một identifier, do đó không đợc đặt tên hàm trùng với tênbiến hoặc ngợc lại

 Khi ta khai báo tham số là mảng một chiều hay con trỏ thì khi gọi có thểgọi tham số thực là con trỏ hoặc mảng Thí dụ khai báo char st[]; vàchar *st; là hoàn toàn tơng đơng Tuy nhiên với mảng 2 chiều thì không

còn đúng nữa Thí dụ đoạn chơng trình sau đây là không hợp lệ:

ng lệnh này nếu có thì chỉ có ở dạng đơn giản là return; khi chơng trìnhgặp lệnh này thì chơng trình thoát khỏi hàm Nếu không có lệnh returnthì chơng trình chạy đến hết thân hàm rồi mới thoát khỏi hàm

Ví dụ:

Trang 37

Bây giờ ta xét một ví dụ là in ra ngày trong tuần từ thứ 2 đến thứ 7 bằngtiếng Anh khi cho ngày bằng số, thí dụ 2 là thứ 2, 3 là thứ 3, và viết hàmbằng 2 cách: có kiểu cho ra và kiểu cho ra là void.

Cách 1:

char* weekday(int n)

{switch(n)

{case 2: return "Monday";

case 3: return "Tuesday";

case 4: return "Wednesday";

case 5: return "Thursday";

case 6: return "Friday";

case 7: return "Saturday";

case 3: printf("\n%s","Tuesday"); break;

case 4: printf("\n%s","Wednesday"); break;

case 5: printf("\n%s","Thursday"); break;

case 6: printf("\n%s","Friday"); break;

case 7: printf("\n%s","Saturday"); break;

t=max(a,b);

6.4 Sử dụng hàm assert() để kiểm tra điều kiện trớc

Hầu hết các hàm không thực thi tốt trên tất cả các giá trị của các tham số Thí

dụ hàm double power(double x,int n) mà chúng ta sẽ xét tới sau đây chỉ cónghĩa với x>0 Đối với các hàm có trả về giá trị khác với kiểu void thì đôi khirất khó để tìm một kiểu ra tơng ứng với các trờng hợp không thích hợp Trongcác trờng hợp này ta có thể dùng hàm assert() đợc định nghĩa trong assert.h

để kiểm tra trớc các điều kiện Khi điều kiện đó không thỏa mãn thì chơngtrình dừng thực hiện hàm và kèm lời thông báo

Trang 38

Ví dụ:

double power(double x,int n)

{assert(x>0);

double y=1.0;int m=abs(n);//Nếu là double thì dùng fabs()

for(int i=0;i<m;i++) y*=x;

if(n<0) y=1/y;

return y;

}

6.5 Các đối số mặc định

Nếu ta sửa lại hàm nh sau

double power(double x=1.0,int n=2)

{assert(x>0);

double y=1.0;int m=abs(n);//Nếu là double thì dùng fabs()

for(int i=0;i<m;i++) y*=x;

6.6 Truyền tham số cho hàm

1 Truyền bằng tham trị (value parameter)

(Chú ý rằng tên mảng là con trỏ do đó hàm có tham số là mảng luôn đợc tự

động truyền theo địa chỉ Thậm chí nếu ta viết void vv(double &a[2][3])chẳng hạn thì máy sẽ báo lỗi Tuy nhiên nếu ta đã định nghĩa trớc typedefdouble kmatran[2][3]; thì lại có thể viết

void vv(kmtran &a);)

Trang 39

x lại đợc hiểu là biến trớc khi gọi hàm.

Truyền bằng tham trị hằng (const value parameter):

Nếu hàm f1 đợc sửa lại nh sau:

void f1(const int x)

Nghĩa là sau khi ra khỏi chơng trình thì x lấy giá trị đã thay đổi trong

ch-ơng trình con Đây là cách truyền tham số theo địa chỉ Qua cách truyềnnày thì chơng trình con làm việc trực tiếp với giá trị mà tham số địa chỉtrỏ tới, tức là giá trị thực sự của biến Do vậy nếu trong hàm giá trị biến bịthay đổi thì khi thoát khỏi hàm những sự thay đổi đó vẫn đợc giữ lại Khitruyền tham số theo địa chỉ ta cần chú ý tới những điểm sau:

 Mảng chỉ có thể truyền cho hàm qua địa chỉ, do đó đối với dữ liệu kiểu

Trang 40

mảng thì mọi sự thay đổi trong hàm vẫn còn tác dụng khi ra khỏi hàm.

 Có thể dùng 2 cách khai báo biến <kiểu dữ liệu>* <tên biến con trỏ>hoặc <kiểu dữ liệu> *<tên biến con trỏ> (thí dụ int* pi hoặc int *pi,trong đó pi là con trỏ kiểu int) Cả 2 cách này hoàn toàn tơng đơng Cáchthứ nhất thờng đợc dùng khi khai báo nguyên mẫu hàm, vì khi đó ta chỉkhai báo kiểu của biến, cha cần khai náo tên

 Con trỏ không cần phải khởi tạo khi khai báo nhng phải khởi tạo trớc khi sửdụng

 Không đợc gán giá trị khác kiểu cho con trỏ Thí dụ trong hàm trên đây takhông thể gọi f1(2); hoặc f1(&(x+1));

3 Truyền bằng tham chiếu (reference parameter):

Trong C++ ngời ta còn đa thêm khái niệm biến tham chiếu Có thể xem biếntham chiếu là một bớc tiến của con trỏ Ta hãy xét đoạn chơng trình sau:

nh biến i Do đó mọi sự thay đổi của i đều tơng đơng với thay đổi trên j

và ngợc lại Vậy ta có thể hình dung một biến tham chiếu giống nh bí danhcủa biến khác Ta có mấy điều chú ý sau đây về biến tham chiếu:

 Biến tham chiếu cũng chứa địa chỉ của một hực thể nh các biến khác

 Biến tham chiếu cần phải đợc khởi tạo khi khai báo Thí dụ nếu ta khai báoint& i; thì máy sẽ báo lỗi Điều này cũng dễ hiễu, vì biến tham chiếu làbiến "ăn theo", do đó phải đợc khởi tạo khi khai báo Tốt nhất là ta khởi tạobiến tham chiếu theo một biến khác đã có Còn nếu ta khởi tạo bằng mộthằng, thí dụ int &m=2; thì máy không báo lỗi nhng có dòng cảnh báoTemporary used to initialize 'm'

 Không cấp phát bộ nhớ động cho biến tham chiếu

 Không dùng các phép toán nh tăng hoặc giảm địa chỉ đối với biến thamchiếu

Mặc dù bản chất của biến tham chiếu là con trỏ, nhng ta có thể sử dụng tênbiến tham chiếu để truy nhập đến giá trị của nó Đây là điểm khác biệtgiữa biến thuộc kiểu tham chiếu và biến kiểu con trỏ Nếu trong đoạn chơngtrình trên đay ta sửa lại là

const int i=10;

int& j=i;

j=20;

printf("\n%d",i);

Ngày đăng: 14/06/2014, 00:48

HÌNH ẢNH LIÊN QUAN

Bảng các ký tự chuyển dạng - Giáo trình Lập Trình C
Bảng c ác ký tự chuyển dạng (Trang 24)
Bảng các ký tự chuyển dạng - Giáo trình Lập Trình C
Bảng c ác ký tự chuyển dạng (Trang 26)
Bảng mã các màu nền và màu chữ: - Giáo trình Lập Trình C
Bảng m ã các màu nền và màu chữ: (Trang 58)

TỪ KHÓA LIÊN QUAN

w