cslt 1 chuong 2

Màu nền
Font chữ
Font size
Chiều cao dòng

Chương 2: Lập trình căn bản trên C

2.1. Làm quen với Turbo C

2.1.1. Khởi động và thoát khỏi

a. Giới thiệu sơ lược về ngôn ngữ C

Ngôn ngữ C do Dennish Ritchie đề xuất năm 1972 tại phòng thí nghiệm Bell Telephone thuộc công ty viễn thông AT&T của Mỹ với mục đích ban đầu là tạo ra ngôn ngữ bậc cao để viết hệ điều hành UNIX. C được tạo ra trên cơ sở ngôn ngữ BCPL (do Martin Richards đưa ra năm 1967) và ngôn ngữ B (do Ken Thompson đưa ra năm 1970).

Đến năm 1978, giáo trình “The C programming language” do chính tác giả viết được xuất bản, rồi được viện tiêu chuẩn hoá của Mỹ (American National Standard Institute) làm thành tiêu chuẩn năm 1983 với tên gọi “ANSI C”.

Cho đến nay, C đã trở thành một ngôn ngữ quốc tế và được sử dụng rộng rãi cho giới lập trình chuyên nghiệp, trong việc dạy lập trình ở các trường  đại học, cao đẳng và trung học nhờ các ưu điểm sau:

- Là ngôn ngữ lập trình cấp cao nhưng rất mạnh và mềm dẻo, có những khả năng thực hiện những thao tác như của Assembler để viết các hệ điều hành, các trình điều khiển, soạn thảo văn bản, bảng tính điện tử, cơ sở dữ liệu ... thậm chí cả chương trình dịch cho các ngôn ngữ khác. Người ta ước tính rằng, chương trình C khi đã dịch, có thể đạt tới 80% tính năng của chương trình viết bằng ngôn ngữ máy.

- C được xây dựng trên những thành tựu mới nhất của Tin học, nó có một thư viện chương trình con hàm khổng lồ làm giảm đáng kể công sức lập trình; Bên cạnh đó, có khá nhiều chương trình dịch và và các thư viện tiện ích khác mà C có thể khai thác được.

- C là ngôn ngữ có thể chuyển dịch nên rất dễ thích nghi. Một chương trình C viết cho loại máy này có thể chuyển sang loại máy khác chỉ cần cho dịch lại là có thể chạy được ngay hoặc nếu có phải thay đổi thì đó chỉ là các hiệu chỉnh không đáng kể.

- C là ngôn ngữ lập trình có cấu trúc mạch lạc nhờ sử dụng các hàm, rất dễ học, dễ phát hiện lỗi chương trình. Nó được dùng rất tốt cho các bài toán kĩ thuật cũng như các cơ sở dữ liệu lớn vì tính cấu trúc chặt chẽ.

Vì C là ngôn ngữ rất được quan tâm của giới nhà nghề nên rất nhiều hãng đã phát triển C dựa trên C chuẩn (ANSI C) trong đó chương trình dịch Turbo C là sản phẩm nổi tiếng của hãng Borland International (Mỹ) đang được sử dụng thịnh hành nhất. Giáo trình này sẽ giới thiệu C trên cơ sở Turbo C với phiên bản 2.01 cho DOS (Cũng có thể thực hành Turbo C trên Turbo C++ 3.0 cho DOS hoặc Turbo C++ 4.5 cho WINDOWS). Việc mới tiếp xúc với C sẽ gây nhiều bỡ ngỡ cho người học vì C có một số kí hiệu mang nhiều nghĩa được hiểu tuỳ theo ngữ cảnh, tự do truy nhập vào các vùng dữ liệu, các kiểu dữ liệu được xử lí pha trộn bằng các loại toán tử khác nhau, ... Nhưng đó chỉ là bước đầu, phải chấp nhận để có được những điểm mạnh của C.

b. Khởi động Turbo C

- Về bộ chương trình: Trên DOS, cài đặt Turbo C (TC) bằng cách chạy chương trình INSTALL.EXE trong bộ cài của Turbo C. Tệp chương trình chính để khởi động TC là TC.EXE đã chứa sẵn trình soạn thảo và trình dịch TC. Ngoài ra còn nhiều tệp khác để hoàn chỉnh khả năng của TC (xem phụ lục 2).

- Bản chất việc khởi động TC là cho chạy tệp chương trình chính TC.EXE, nó được gọi để thực hiện giống như gọi các tệp ngoại trú, lời gọi có dạng:

[Đường dẫn]TC[.EXE]

Trong đó: đường dẫn để xác định địa chỉ của tệp TC.EXE

Ví dụ: Giả sử tệp TC.EXE để khởi động TC nằm ở thư mục TC trên gốc C:, từ dấu mời DOS có dạng C:\> ta gõ lần lượt các lệnh:

C:\> CD TC

C:\TC> TC

Nếu từ màn hình giao tiếp của WINDOWS, có thể tạo một Shortcut để tham chiếu tới tệp TC.EXE hoặc chạy tệp này trực tiếp từ Start >>Run : C:\TC\TC.EXE

Sau khi khởi động xong sẽ xuất hiện màn hình làm việc của TC

c. Thoát khỏi Turbo C

Bản chất là ngắt thực hiện tệp TC.EXE để trở về hệ điều hành, bằng cách:

·    Dùng bàn phím, ấn: ALT - X

·    Dùng thực đơn: File >> Quit   (Alt - F >> Q)

Khi thoát khỏi  TC mà chương trình chưa được ghi lại những sửa đổi, TC sẽ hỏi có ghi lại không thông qua hộp thoại có dạng:

Trả lời:    Y (yes) nếu muốn ghi lại. Khi đó, phải đưa vào tên tệp với phần mở rộng ngầm định là C kèm theo đường dẫn (nếu cần);

 N (no) nếu không ghi.

2.1.2. Môi trường làm việc của Turbo C

a. Màn hình làm việc của Turbo C

Là màn hình xuất hiện ngay sau khi khởi động C và được mô phỏng trong hình dưới đây. Màn hình làm việc của C gồm các thành phần:

·  Thanh thực đơn: chứa hệ thống thực đơn để thao tác với chương trình. Thao tác với thực đơn tương tự như trong Pascal: ấn F10 để kích hoạt rồi dùng các phím Left, Right, Up, Down di chuyển đến mục cần chọn và ấn Enter. Cũng có thể giữ phím ALT và nhấn kí tự đại diện (có màu đỏ) để kích hoạt và chọn.

              Ví dụ: ấn ALT - F rồi ấn Q để thoát khỏi TC.

·  Dòng trạng thái: chỉ ra một số trạng thái khi làm việc.

·  Vùng văn bản: chứa nội dung văn bản chương trình.

·  Vùng thông báo (Message): chứa các lời nhắc của máy cho bạn.

·  Thanh trợ giúp: Để nhắc nhở một số phím chức năng thường dùng nhất.

Để tiện lợi trong quá trình thực hành, sinh viên có thể làm quen với màn hình làm việc của C++  dưới đây với cách thức giao tiếp hoàn toàn tương tự như C vì C++ là version sau của C.

Sự khác nhau căn bản trong giao diện của C và C++ là ở chỗ: C không sử dụng chuột còn C++ thì được phép sử dụng chuột nên tiện lợi hơn.

Chú ý: Trong phần này chỉ cần nhớ một số thao tác chính sau:

Ø    ALT - E  để bắt đầu soạn chương trình;

Ø    ALT - F  và N để soạn một chương trình mới;

Ø    F2         để ghi chương trình lên đĩa thành tệp với phần mở rộng ngầm định là .C, nếu ghi lần đầu thì phải đặt tên tệp;

Ø    F3           để đọc tệp từ đĩa vào RAM;

Ø    CTRL - F9   để biên dịch và chạy chương trình;

Ø    ALT - F5     để xem kết quả chạy chương trình;

Ø    ALT - F9  để dịch chương trình thành tệp cùng tên với phần mở rộng là .EXE (Chỉ dịch sau khi đã ghi chương trình).

b. Soạn thảo trong Turbo C

Để bước vào soạn thảo thường chọn thực đơn Edit. Nếu đang soạn một chương trình, muốn soạn tệp mới thì chọn thực đơn File >> New.

Khi soạn thảo trong C, thường sử dụng các lệnh sau đây:

- Các lệnh di chuyển con trỏ: Left, Right, Up, Down; Home, End; PgUp, PgDn; Ctrl_PgUp, Ctrl_PgDn.

- Các lệnh xoá:

            Del              : Xoá kí tự tại con trỏ.

            Back Space  : Xoá kí tự trước trỏ.

            Ctrl_Y         : Xoá dòng hiện tại.

            Ctrl_Q Y     : Xoá phần cuối dòng kể từ vị trí con trỏ.

            Ctrl_K Y     : Xoá khối đã đánh dấu.

- Các lệnh xử lí khối:

            Đánh dấu khối: Ctrl_K B để đánh dấu đầu khối, Ctrl_K K để đánh dấu cuối khối.

            Ctrl_K C      : Sao khối đến vị trí con trỏ.

            Ctrl_K V      : Chuyển khối đến vị trí con trỏ.

            Ctrl_K Y      : Xoá khối.

            Ctrl_K W    : Ghi khối vào tệp trên đĩa, nếu tên tệp là PRN thì khối được in ra máy in.

            Ctrl_K R      : Đọc tệp từ đĩa vào văn bản đang soạn, đặt tại con trỏ.

            Ctrl_K P       : In khối.

            Ctrl_K H      : ẩn/hiện khối.

- Các lệnh tìm kiếm và thay thế

            Ctrl_Q F       : Tìm một cụm từ.

            Ctrl_Q A      :  Tìm và thay thế. Phải xác định:

Find: tìm gì

Replace: thay bằng gì

Option : tuỳ chọn khi tìm, nếu là:

U: không phân biệt chữ in và thường;

B: tìm từ trỏ về phía đầu tệp;

W: tìm các từ độc lập;

G: tìm và thay thế từ đầu tệp;

N: tìm và thay thế không cần hỏi lại;

m: m là số nguyên dương chỉ số lần gặp để dừng lại.

2.2. Các yếu tố cơ bản trong turbo c

2.2.1. Bảng chữ cái (Character set)

Bảng kí tự gốc của C là bảng mã ASCII, được chia thành ba nhóm sau:

-     Bộ chữ cái: Gồm 26 chữ cái Latinh viết in (A,B,C,...,Z) và viết thường (a,b,c,...,z). C là ngôn ngữ có sự phân biệt rõ ràng giữa chữ in và chữ thường nên phải lưu ý khi viết các từ khoá và sử dụng tên.

-     Bộ chữ số: Gồm 10 chữ số ả rập 0,1,2,3,...,9.

-        Các kí hiệu đặc biệt: Là các kí hiệu không phải chữ cái hoặc chữ số, chẳng hạn như: +, -, *, /, [, ], (, ), =, <, >, .... Khoảng trống (còn gọi là dấu cách) cũng được coi là một kí tự đặc biệt.

Mỗi kí hiệu thuộc một trong ba loại trên, gọi chung là một kí tự. Một dãy kí tự gọi là một xâu. Số kí tự trong xâu gọi là độ dài xâu. Xâu không gồm kí tự nào gọi là xâu rỗng.

2.2.2. Từ khoá (Keywords)    

Từ khoá trong C là những từ được dùng riêng, với cách viết và ý nghĩa cố định, không được dùng từ có nghĩa tương đương để thay thế và cũng không được dùng trong bất kì trường hợp nào khác (định nghĩa lại, dùng đặt tên). Sau đây là danh sách từ khoá thường dùng của C.

ams

auto

break

case

cdecl

char

const

continue

default

do

double

else

enum

extern

far

float

for

huge

If

long

near

pascal

return

short

sizero

static

struct

signed

switch

typedef

union

unsigned

voi

volatile

while

Chú ý: Các từ khoá phải viết thường. Ví dụ: Phải viết là if, không được viết If hay IF như trong nhiều ngôn ngữ khác.

2.2.3. Tên (Identifier)

Tên trong C là một dãy kí tự do người dùng đặt để định danh cho chương trình, cho biến, cho hàm, cho mảng, cho hằng, ... Muốn chỉ đến các đối tượng đã được định danh, người ta xác định nó qua tên. Mọi tên đều phải được khai báo trước khi sử dụng.

Trong C, tên do người sử dụng tuỳ ý đặt nhưng phải thoả mãn ba quy định:

-        Gồm không quá 32 kí tự thuộc loại chữ cái, chữ số, dấu gạch dưới nhưng bắt đầu phải không là chữ số;

-        Không trùng với từ khoá;

-        Có phân biệt chữ in và chữ thường.

Ví dụ: Delta, pi, Pi, dien_tich, _bien_trung_gian là các tên khác nhau đặt đúng. Các tên sau đây là sai:

Số1       : Có kí tự đặc biệt.

chu vi  :  Chứa khoảng trống.

return :  Trùng với từ khoá.

2x        :  Bắt đầu là chữ số.

Chú ý: Tên có thể dài quá 32 kí tự, bình thường (ngầm định) C chỉ phân biệt 32 kí tự đầu tiên, phần còn lại không xét; tuy vậy, có thể đặt lại giá trị cực đại này một giá trị nhận từ 1 đến 32 trong thực đơn: Option >> Compiler >> Source >> Indentifier length.

2.2.4. Chú thích (Comment)

Nhiều khi, ở chỗ nào đó trong chương trình, ta muốn đặt lời thuyết minh cho những ý tưởng của mình chỉ để kiểm soát chương trình sao cho thuận lợi hay người khác đọc sẽ dễ hiểu hơn. C cho phép viết lời thuyết minh đó trong cặp dấu /* và */. Một văn bản bất kì không chứa /* và */ viết giữa cặp /* và */ gọi là chú thích và bị chương trình dịch bỏ qua khi dịch chương trình ra ngôn ngữ máy.

Các chú thích có thể viết trên một phần của dòng lệnh hay trên nhiều dòng khác nhau nhưng bắt buộc phải bắt đầu bằng /* và kết thúc bằng */.

Ví dụ:

#include <stdio.h>   /*Gọi tệp xử lí vào ra */

main()

{

    /* Các câu lệnh của chương trình C

         ghi ở đây   */

return(0);         /* Không bắt buộc viết */

}

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

          Dữ liệu là nguyên liệu xử lí của máy tính. Mọi dữ liệu cho máy tính đều phải có một kiểu xác định. Mỗi kiểu dữ liệu sẽ quy định một cách thức lưu trữ và xử lí khác nhau đối với máy. Người sử dụng máy phải hiểu được các quy tắc đó để kiểm soát quá trình hoạt động của máy.

2.2.5.1. Dữ liệu kiểu số nguyên

Dữ liệu kiểu số nguyên là dữ liệu biểu diễn các số nguyên trong máy tính, bao gồm các kiểu số nguyên cụ thể được liệt kê ở bảng dưới đây:

Kiểu dữ liệu

Miền giá trị

Bộ nhớ lưu trữ

-32.768 - 32.767

2 bytes

short

-32.768 - 32.767

2

long

-2.147.483.648  -  2.147.483. 647

4

unsigned int

0 - 65.535

2

unsigned short

0 - 65.535

2

unsigned long

0 – 4.294.967.295

4

Chú ý:

 - Hai kiểu shortunsigned  short không cần sử dụng vì khi tính toán, hai kiểu này được trình biên dịch tự động hiệu chỉnh tương ứng thành kiểu int và unsigned int.

           - Hai kiểu char  và unsigned char thực chất là dữ liệu kiểu kí tự (lưu trữ ở 1 byte) nhưng có thể dùng nó như số nguyên. Khi tính toán trong biểu thức số thì hai kiểu trên được sử dụng là số nguyên kiểu int!

           -  Khi thực hiện các phép toán trên số nguyên, phải chú ý xem kết quả có vượt quá miền giá trị hay không, nếu vượt quá sẽ gây tràn số và sai kết quả. Trong trường hợp đó, phải nghiên cứu cách thay đổi lại kiểu dữ liệu cho phù hợp. Ví dụ, ta thực hiện phép toán trên số kiểu int:

          32766 + 2 - 100 , kết quả 32766 + 2 vượt quá giá trị 32767 nên sẽ sai gây ra kết quả cuối cùng của phép tính trên sẽ sai mặc dù giá trị của cả biểu thức vẫn nằm trong phạm vi biểu diễn của số kiểu int.

2.2.5.2. Dữ liệu kiểu số thực

Dữ liệu kiểu số thực là dữ liệu biểu diễn các số thực trong máy tính, bao gồm các kiểu số thực cụ thể được liệt kê ở bảng dưới đây:

Kiểu dữ liệu

Phạm vi biểu diễn

Độ chính xác

Bộ nhớ lưu trữ

float

1.2E-38 – 3.4E+38

7 chữ số

4 bytes

double

2.2E-308 – 1.8E+308

15 chữ số

8

long double

3.4E-4932 – 3.4E+4932

19 chữ số

10

Chú ý: Giá trị của các số thực sẽ có trị tuyệt đối nằm trong phạm vi biểu diễn ở bảng trên, nếu nhỏ hơn coi bằng không, lớn hơn không biểu diễn được.  

2.2.5.3. Dữ liệu kiểu char

Dữ liệu kiểu char là dữ liệu biểu diễn một kí tự thông qua bảng mã ASCII. Mã của kí tự là số thứ tự của kí tự đó trong bảng mã. Có tất cả 256 kí tự đánh số tự 0 đến 255, trong đó các mã từ 0 đến 31 dùng để điều khiển quá trình vào - ra của thiết bị ngoại vi, không in ra được.

Dữ liệu kiểu char được lưu trữ ở 1 byte trong bộ nhớ.

2.2.5.4. Dữ liệu kiểu xâu

Dữ liệu kiểu xâu (xâu kí tự) là dữ liệu thể hiện một dãy kí tự bất kì. Trong C, xâu gồm không quá 255 kí tự bất kì  đặt trong một cặp dấu nháy kép.

Ví dụ:   “HOC VIEN TAI CHINH”

Hoặc, trong lệnh: printf(“Hoc de ngay mai lap nghiep”);

Trong bộ nhớ của C, xâu được lưu trữ trong một mảng ô nhớ liền nhau, mỗi kí tự một byte, ngoài ra còn sử dụng thêm một ô nhớ cuối cùng để lưu mã số 0 (kí tự null – kí tự đầu tiên của bảng mã ASCII, kí hiệu là \0).

H

O

C

V

I

EN

T

A

I

C

H

I

N

H

\0

Chẳng hạn:

Ta sẽ nghiên cứu kĩ kiểu này trong phần mảng.

2.2.5.5. Dữ liệu kiểu logic

Dữ liệu kiểu logic là dữ liệu thể hiện một trong hai giá trị đúng hoặc sai của một mệnh đề logic mà ta đã làm quen trong phần tin học đại cương.

Trong C, hai giá trị sai hoặc đúng được thể hiện bằng một số nguyên kiểu int, có giá trị bằng 0 (sai) và khác 0 (đúng). Tuy vậy, trong các kết quả tính toán thì đúng luôn có giá trị là 1.

Ví dụ: Lệnh printf(“%d”, 3 > 5); sẽ hiển thị giá trị 0

 Chương trình:

main()

{ int i;

   i = 8>2;

   printf(“%d”, i);

              }

sẽ hiển thị giá trị 1

Một điều khá đặc biệt trong C là: Các giá trị logic 0 hoặc 1 có thể tham gia vào các phép toán trong các biểu thức trong khi ở các ngôn ngữ khác, chúng chỉ là các giá trị lựa chọn.

2.2.6. Các đại lượng

2.2.6.1.  Hằng

Hằng là một đại lượng xác định, có giá trị không thay đổi trong suốt quá trình thực hiện chương trình. Có bao nhiêu kiểu dữ liệu thì có bấy nhiêu kiểu hằng với cách viết được quy định trong C như sau:

§  Hằng nguyên được viết dưới dạng: ±n với n là một số nguyên hệ 10 nằm trong miền giá trị, có thể có dấu + hoặc - trước chữ số đầu tiên.

Ví dụ:  Các số -32768, 12345, +32767 có thể là hằng kiểu int.

Ngoài ra, có thể viết số nguyên dạng số hệ 16 với quy định viết bắt đầu là 0x hoặc 0X. Ví dụ: số 65 hệ 10 có thể viết là 0x41 hay 0X41, số 10 hệ 10 có thể viết là 0xA.

Trong C còn cho phép viết định kiểu trước cho hằng nguyên để đảm bảo độ chính xác, bằng cách ghi thêm một kí tự định kiểu vào cuối dãy số: L là kiểu long, U là kiểu unsigned int, UL là kiểu unsigned long. Ví dụ: 65535U, 123456789UL, -2147483648L.

§  Hằng thực có hai cách viết:

Cách 1: Viết dạng dấu chấm tĩnh theo mẫu: ±n.m với n, m là dãy các chữ số hệ 10. Trong cách viết số thực dạng dấu chấm tĩnh, phải có dấu chấm ngăn cách phần nguyên và phân nhưng các chữ số 0 vô nghĩa đều có thể bỏ qua. Ví dụ: Viết các số thực  -123.45,  5.,  .456,  0.123  là đúng; Viết 789 là sai (thiếu dấu chấm).

Cách 2: Viết dạng dấu chấm động. Trong cách viết này, số thực được tách thành hai phần là phần định trị và phần bậc, với dạng tổng quát là: ±n.mE±s  hoặc  ±n.me±s .

Trong đó: n, m, s là các chữ số hệ 10, E±s với nghĩa là nhân với 10±s , phần định trị và phần bậc có thể có dấu ± đi kèm và viết liền nhau không chứa khoảng trống, các dấu + và dấu chấm có thể không viết.

Ví dụ, Viết các hằng thực -123.45E+6, 2E8, .456e-2 là đúng; Viết 5 (thiếu  dấu .), 2E 3 (có khoảng trống trước số 3) là sai.

Tương tự như với số nguyên, có thể viết định kiểu trước cho hằng thực bằng cách thêm một kí tự định kiểu vào cuối dãy số: F là kiểu float, L là kiểu long double. Ví dụ, có thể viết 12.E-5F , .1234E-123L  .

§  Hằng kí tự được viết bằng cách đặt một kí tự trong cặp dấu nháy đơn (‘).

Ví dụ: ‘A’, ‘a’, ...

Có một số kí tự đặc biệt không nhìn thấy hoặc không được viết trong một số trường hợp, dùng để điều khiển, được mã hoá bằng cách viết thêm ở trước dấu \ (kí tự escape) như bảng sau:

Kí tự

Mã kí tự

Mã ASCII (hệ 10)

Đổ chuông

\a

7

Xoá lùi

\b

8

Nhảy một Tab

\t

9

Nhảy cách đứng

\v

11

Xuống dòng

10

Xuống dưới  (LF)

\f

12

Về đầu dòng (CR)

\r

13

Dấu nháy kép “

\”

34

Dấu nháy đơn ‘

\’

39

Dấu chấm hỏi ?

\?

63

Dấu \

\\

92

Null (số không)

\0

0

Khi đó, hằng dấu nháy đơn có thể viết trong C là ‘ \’ ’ , dấu \ viết là ‘\\’.

§  Hằng xâu kí tự có cách viết: Đặt xâu kí tự bất kì (kể cả các kí tự đặc biệt viết sau dấu \) trong cặp dấu nháy kép (“).

Ví dụ: “Thanh pho Ha noi”

           “ \”Toi\” và \”Chung ta\”.”

Chú ý rằng, nếu viết A (kiểu char) thì nó lưu trữ ở 1 byte và tham gia được vào các phép toán số học nhưng viết A (kiểu xâu) thì sẽ lưu trữ trong hai bytes và không tham gia được vào các phép toán số học.

Trong chương trình C, hằng có thể thể hiện qua giá trị cho trực tiếp như đã viết ở trên, cũng có thể thể hiện qua tên hằng. Nếu hằng thể hiện qua tên thì trước khi sử dụng hằng, phải khai báo tên hằng ở phần khai báo các hằng của chương trình. Có hai cách khai báo hằng như sau:

Cách 1: Khai báo ở bắt đầu một hàm, bắt đầu một khối lệnh, theo mẫu:

const  <kiểu dữ liệu> <tên hằng>=<giá trị (hoặc biểu thức) của hằng>;

Ví dụ:

    main()

    { const int i=3;

       const float x=123.45;

        /* các lệnh tiếp theo */

     }

Cách 2:   Khai báo ở đầu chương trình, theo mẫu:

#define <tên hằng>  <giá trị hằng>

Ví dụ:  

#include <stdio.h>

#define MAX 1000

Khi đã khai báo hằng thì về sau, bất kì chỗ nào trong chương trình viết tên đó, trình biên dịch sẽ thay bằng giá trị đã xác định. Chẳng hạn, viết MAX thì được thay bằng 1000.

Bạn nào có thói quen dùng khối lệnh Begin ...End; của PASCAL, có thể định nghĩa lại trong C

#define Begin {

#define End  }

và từ đó có thể đặt khối lệnh trong cặp Begin và End.

2.2.6.2.  Biến (Variable)

Biến là một đại lượng có giá trị thể thay đổi trong quá trình thực hiện chương trình. Trong mọi ngôn ngữ lập trình, kể cả C, các biến của chương trình đều được thể hiện qua tên biến (trong C, biến còn có thể được truy nhập qua địa chỉ và qua con trỏ – điều này sẽ được xét ở phần sau). Tên biến được đặt theo quy tắc đặt tên nói chung được giới thiệu ở phần 2.2.3. Mỗi tên biến là một địa chỉ tượng trưng của một vùng nhớ trong RAM để lưu trữ dữ liệu. Biến cũng nhận các kiểu dữ liệu như đã giới thiệu ở trên nhưng phải nhớ rằng: Trong một chương trình C, một biến chỉ gắn với một kiểu dữ liệu và chỉ một mà thôi và phải khai báo biến trước khi sử dụng.

a. Khai báo biến

Mọi biến, trước khi dùng, phải được khai báo trước để trình biên dịch xác định được kích thước,vị trí và ghi nhận sự có mặt của biến. Dạng khai báo như sau:

<Kiểu dữ liệu >  <Danh sách biến>;

Trong đó:

<Danh sách biến> là tên các biến cần khai báo đặt cách nhau dấu phẩy;

<Kiểu dữ liệu > là một trong các kiểu đã giới thiệu ở phần trước (int, long, float, char, ...)

Ví dụ:

int  i,n; char  kt;

float S;  double Y;

Khai báo này thường được đặt ở đầu chương trình (ngoài tất cả các hàm), bắt đầu một hàm hoặc bắt đầu khối lệnh. Nếu khai báo biến ở đầu chương trình thì các biến này là biến toàn cục, có tác động tới toàn bộ chương trình; Nếu khai báo biến ở đầu một hàm hay khối lệnh thì phải đặt nó ngay sau dấu { đầu tiên của thân hàm và trước tất cả mọi câu lệnh khác, trường hợp này, người ta gọi nó là biến địa phương, chỉ có tác dụng trong hàm hay khối lệnh đó.

Khi khai báo, máy sẽ cấp phát cho các biến trong danh sách một trường nhớ có độ dài do kiểu dữ liệu của biến quy định. Địa chỉ byte đầu của trường đó gọi là địa chỉ của biến. Để truy nhập đến địa chỉ của biến, ta viết dấu & trước tên biến đó. Ví dụ &i là địa chỉ của biến i (có thể in ra địa chỉ này dạng số hệ 16).

b. Gán giá trị ban đầu cho biến

Mỗi biến đều có một kiểu dữ liệu xác định, nếu không gán giá trị ban đầu cho biến thì biến đó sẽ mang một giá trị bất kì (không xác định được) trong miền của kiểu đã được khai báo. Để cho biến nhận một giá trị xác định ban đầu, phải gán cho biến một giá trị bằng một trong hai cách sau:

-        Dùng lệnh gán, có dạng: <Tên biến> = <biểu thức>;

Ví dụ:

main()

 {  int i,k;

     float a,s;

     char kt;

         i = 1;  k =-1;

         s = 5.0; a = 2.1E+2;

         kt = ‘A’;

         . . . . . .

  }

-        Vừa khai báo vừa gán giá trị.

Ví dụ:

main()

{

          int a,b = 10, c = 1;

          float d = 12.3 d,e = 5E-6;

          char kt = ‘A’;

          . . . . .

  }

2.2.6.3.  Hàm mẫu

Để giúp cho việc lập trình được thuận tiện và có hiệu quả hơn, trong Turbo C, người ta đã xây dựng sẵn một số chương trình mẫu để tính giá trị của các hàm thông dụng, gọi là hàm mẫu (hay hàm xây dựng sẵn). Các hàm này được ghi trong các tệp tiêu đề (header) của Turbo C thuộc thư viện chương trình mẫu của ngôn ngữ. Khi cần dùng, đầu chương trình phải khai báo đọc tệp chứa hàm mẫu thì trong thân chương trình sẽ được gọi hàm thông qua tên hàm kèm theo giá trị của đối cụ thể (nếu có) theo đúng quy định của C.

Ví dụ: Hàm fabs(x) trả về giá trị là trị tuyệt đối của số thực x

Sau đây sẽ giới thiệu một số hàm mẫu thông dụng nhất.

a. Một số hàm số:

Các hàm số nhận đối là số (số thực hoặc số nguyên) và giá trị của hàm cũng là số. Các hàm này nằm trong tệp math.h nên muốn sử dụng, đầu chương trình phải có khai báo  #include <math.h>

Hàm

Kiểu giá trị

ý nghĩa

abs(i)

Trả lại trị tuyệt đối của số nguyên i

fabs(d)

double

Trả lại trị tuyệt đối của số thực d

sin(d)

double

Trả lại giá trị hàm sin

cos(d)

double

Trả lại giá trị hàm cos

tan(d)

double

Trả lại giá trị hàm tang

exp(d)

double

Trả lại giá trị hàm ex

log(d)

double

Trả lại giá trị hàm lnd

pow(d1,d2)

double

Trả lại giá trị là d1 mũ d2

floor(d)

double

Cho số nguyên lớn nhất nhỏ hơn d

ceil(d)

double

Cho số nguyên nhỏ nhất lớn hơn d

fmod(d1,d2)

double

Hàm phần dư của d1/d2

sqrt(d)

double

Căn bậc hai của số thực d

b. Một số hàm đối với xâu và kí tự

Các hàm xâu sau đây nằm trong tệp ctype.h. Khi muốn sử dụng, đầu chương trình phải có khai báo #include <ctype.h>. Trong các dạng hàm, s để chỉ một xâu, c để chỉ một kí tự.

- Hàm atoi(s) : Chuyển xâu kí tự s (string) thành một số nguyên kiểu int.

Ví dụ: Hàm atoi(“32767”) cho giá trị là số nguyên (int) là 32767;

           Hàm atoi(“32768”)  cho giá trị là -32768;

           Hàm atoi(“12A4h”) cho giá trị là 12;

           Hàm atoi(“abc”) cho giá trị là 0.

- Hàm atol(s): Chuyển xâu kí tự s thành một số nguyên kiểu long.

- Hàm atof(s): Chuyển xâu kí tự s thành một số thực kiểu double.

- Hàm toupper(c): Chuyển kí tự c thành chữ in (tương ứng với một số nguyên kiểu int).

Ví dụ: Hàm toupper(‘a’) cho giá trị là kí tự A. Khi hiển thị, nếu định dạng ra là kí tự thì đưa ra chữ A, nếu định dạng là số nguyên thì đưa ra số 65.

- Hàm tolower(c) : Chuyển kí tự c thành chữ thường (tương ứng với một số nguyên kiểu int).

Ví dụ: Hàm tolower(‘A’) cho giá trị là kí tự a.

- Hàm toascii(c) :Cho giá trị là một số nguyên kiểu int bằng mã ASCII của kí tự c.

Ví dụ: Hàm toascii(‘B’) cho giá trị là số 66.

- Hàm isalpha(c):  Cho giá trị đúng (số kiểu int có giá trị khác 0) nếu c là một chữ cái, ngược lại cho giá trị sai (=0).

- Hàm islower(c): Cho giá trị đúng nếu c là chữ thường

- Hàm isupper(c): Cho giá trị đúng nếu c là chữ in

- Hàm isdigit(c): Cho giá trị đúng nếu c là chữ số

- Hàm iscntrl(c): Cho giá trị đúng nếu c là kí tự điều khiển (mã ascii từ 0 -31)

- Hàm isspace(c): Cho giá trị đúng nếu c là dấu cách, dấu

(xuống dòng mới), \r (về đầu dòng), \t (Tab), \v (nhảy đứng)

2.2.7. Biểu thức

Biểu thức là một tập hợp các đại lượng liên kết với nhau bởi các dấu phép toán và các dấu hiệu thể hiện trình tự ưu tiên. Trong hầu hết các ngôn ngữ lập trình, dấu hiệu thể hiện trình tự ưu tiên là cặp dấu ( ). Trong biểu thức, các đại lượng còn gọi là các toán hạng, các dấu phép toán còn gọi là toán tử, biểu thức chỉ có một toán hạng gọi là phép toán một ngôi, ví dụ như –a hoặc !a (phủ định của a). Mỗi kiểu dữ liệu có thể tham gia vào một số phép toán nhất định, căn cứ vào giá trị của biểu thức, ta chia biểu thức thành các loại sau:

2.2.7.1. Biểu thức số

Một tập hợp các đại lượng (hằng, biến, hàm) có cùng kiểu số (nguyên hay thực) được liên kết với nhau bởi  các dấu phép toán số học, các dấu mở ngoặc, đóng ngoặc một cách có ý nghĩa tạo thành biểu thức số học. Biểu thức số học đơn giản nhất chỉ gồm duy nhất một hằng, một biến hoặc một hàm  có kiểu số.

Đặc biệt, trong C, một biểu thức số có thể chứa các toán hạng là đại lượng kiểu char. Mỗi đại lượng kiểu char tham gia trong biểu thức số đều được coi là một số nguyên không dấu với giá trị bằng mã ASCII của kí tự đó. Ví dụ: ‘A’ là số 65, ‘1’ là số 49, ... Có thể viết ‘9’ - ‘1’ sẽ cho kết quả như 57-49  hoặc ‘a’ -‘A’ cho kết quả của phép toán 97 - 65.

Các dấu phép toán số học bao gồm:

Phép toán

Dấu phép toán

Thực hiện trên loại dữ liệu

Cộng

Trừ

Nhân

Chia

Lấy phần dư

+

-

*

%

Số nguyên và thực

Số nguyên và thực

Số nguyên và thực

Số nguyên và thực

Chỉ thực hiện trên số nguyên

Thứ tự ưu tiên thực hiện của các phép toán được xếp từ cao đến thấp, như sau:

-        Các phép toán trong ()

-        Phép tính hàm

-        Phép toán một ngôi ( như -a hay +a)

-        Phép nhân, chia, lấy phần dư

-        Phép cộng, trừ

Nếu trong biểu thức có nhiều phép toán cùng một mức độ ưu tiên thì thực hiện từ trái sang phải, riêng phép toán một ngôi thì thực hiện từ phải sang trái.

Ví dụ:

Biểu thức

Viết trong Turbo C

     -x

-------  +1

           2y2

-x/(2*y*y) + 1

  -b +

  ----------

      2a

(-b + sqrt(d))/(2*a)

     xn

pow( x,n) hoặc exp(n*log(x))

123 – 65

123 - 65  hoặc 123 - ‘A’

Chú ý: Giá trị của biểu thức số là một số. Khi trong biểu thức số có nhiều đại lượng không cùng kiểu dữ liệu tham gia thì giá trị biểu thức sẽ có kiểu của đại lượng có độ chính xác cao nhất (chuyển kiểu tự động). Cụ thể cho như ở bảng:

TH Thứ 2

Thứ 1

long

unsigned int

unsigned long

float

double

long double

I

L

I

I

F

D

LD

long

L

L

L

L

F

D

LD

unsigned int

I

L

UI

UL

F

D

LD

unsigned long

I

L

UL

UL

F

D

LD

float

F

F

F

F

F

D

LD

double

D

D

D

D

D

D

LD

long double

LD

LD

LD

LD

LD

LD

LD

Trong nhiều trường hợp, người ta muốn chuyển kiểu dữ liệu khi thực hiện các phép toán, C cho phép làm điều đó bằng phép ép kiểu (chuyển kiểu bắt buộc), có dạng:

(kiểu) <biểu thức>  

Trong đó: Kiểu là kiểu mà biểu thức cần chuyển sang.

Ví dụ: i và j là hai biến có kiểu int,  biểu thức (float) i/j sẽ có kiểu float.

2.2.7.2. Biểu thức quan hệ

a. Khái niệm: Tập hợp các biểu thức liên kết với nhau bởi các dấu phép toán quan hệ và dấu (, ) thì tạo thành một biểu thức quan hệ.

Các dấu phép toán quan hệ gồm:

Dấu phép toán

ý nghĩa

Độ ưu tiên

Lớn hơn

1

Nhỏ hơn

1

>=

Lớn hơn hoặc bằng

1

<=

Nhỏ hơn hoặc bằng

1

==

Bằng

2

!=

Khác

2

b. Tính giá trị của biểu thức quan hệ: Trong biểu thức quan hệ, nếu có cả các phép toán số học thì trật tự ưu tiên khi thực hiện các phép toán được xếp từ cao xuống thấp như sau:

-  Các phép toán số học

-  Các phép toán trong ngoặc

-  Các phép toán ưu tiên mức 1 ( >, <, >=, <=)

-  Các phép toán ưu tiên mức 2  ( = = ,  != )

Nếu cùng mức độ ưu tiên sẽ thực hiện từ trái qua phải. ở mỗi phép so sánh, nếu thoả mãn dấu phép toán thì biểu thức quan hệ nhận giá trị 1, ngược lại nhận giá trị 0. Các giá trị này là một số nguyên kiểu int, có thể tham gia vào các phép toán số học.

c.Ví dụ:

Biểu thức :  1>2 nhận giá trị 0

Biểu thức :  ‘A’+1 < 100  nhận giá trị 1

Biểu thức:   1>(2>3)==5>1 nhận giá trị  1

 (Thứ tự tính: 2>3 nhận 0;  1>0 nhận 1; 5>1 nhận 1; 1==1 nhận 1).

Biểu thức:   12.3+(1>(2>3)==5>1) nhận giá trị  13.3 nhưng nếu viết: 12.3+1>(2>3)==5>1 thì sẽ nhận 1.

2.2.7.3. Biểu thức logic

a. Khái niệm: Một tập hợp các biểu thức liên kết với nhau bởi các dấu phép toán logic, các dấu (,) một cách hợp lí sẽ tạo thành một biểu thức logic (Boon).

Các dấu phép toán logic gồm:

!            Dấu phép toán phủ định

&&      Dấu phép toán và (giao)

||           Dấu phép toán hoặc (tuyển)

Cách thực hiện các phép toán được thể hiện ở bảng chân trị sau đây:

X

Y

! X

X || Y

X && Y

Khác 0

Khác 0

0

1

1

Khác 0

0

1

0

0

Khác 0

1

1

0

0

0

0

0

b. Tính giá trị của biểu thức logic: Trong biểu thức logic, nếu có cả các phép toán số học và các phép toán quan hệ thì trật tự ưu tiên xếp từ cao xuống thấp như sau:

- Các phép toán trong ngoặc

- Phép toán phủ định !

- Các phép toán số học

- các phép toán quan hệ

- Phép toán và &&

- Phép toán hoặc ||

Nếu cùng mức độ ưu tiên sẽ thực hiện từ trái qua phải, riêng phép phủ định thì từ phải sang trái.

Cuối cùng, một biểu thức logic nhận một giá trị 0 hoặc 1 - một số nguyên kiểu int và có thể tham gia vào các phép toán khác. Biểu thức quan hệ thực chất chỉ là một biểu thức logic đơn giản nhất.

c.Ví dụ:

10+1>10 || 4 > ! “A” <100      có giá trị là 1

Chú ý: Trong C, phủ định hai lần cho kết quả chưa chắc bằng giá trị ban đầu! Ví dụ: với x=2772,  !!x=1.

2.2.7.4. Biểu thức điều kiện

a. Khái niệm: Là biểu thức khá đặc biệt trong C, nó gồm 3 toán hạng, mỗi toán hạng là một biểu thức với cách viết được quy định bắt buộc có dạng như sau:

e1 ? e2 : e3  

Trong đó: e1, e2, e3 là các biểu thức bất kì.

b. Tính giá trị của biểu thức điều kiện:

Trước tiên, tính giá trị của biểu thức e1. Nếu e1 có giá trị khác 0 (coi là giá trị logic đúng), biểu thức điều kiện sẽ nhận giá trị bằng e2,  ngược lại (e1 có giá trị bằng 0) thì biểu thức điều kiện nhận giá trị bằng e3.

Kiểu giá trị của biểu thức điều kiện sẽ là kiểu có độ chính xác cao nhất trong hai kiểu của e2 và e3.  Ví dụ: e2 có kiểu int, e3 có kiểu float thì biểu thức điều kiện sẽ có kiểu là float.

c. Ví dụ:

(a >b) ? a : b  là một biểu thức điều kiện. Biểu thức cho giá trị là số lớn hơn trong hai số a và b đã cho.

(n1<n2) ? (min = n1, max=n2) : (min = n2, max = n1)  là một biểu thức điều kiện. Biểu thức gán giá trị cho biến số min và max tương ứng là số nhỏ và số lớn trong hai số đã cho n1, n2.

Trong biểu thức điều kiện thứ 2 này, các biểu thức e2 và e3 được viết khá đặc biệt, gọi là dãy phép gán mà ta sẽ nghiên cứu sau)

2.3. Cấu trúc của một chương trình C

2.3.1. Làm quen với chương trình C

a. Ví dụ 1: Hiển thị xâu kí tự.

/* Chương trình C đầu tiên*/

#include  <stdio.h>

void main()

{

printf(“

Turbo C xin chao cac ban.”);

printf(“

Chuc cac ban thanh cong!”);

}

Chương trình này sẽ hiển thị trên màn hình hai dòng:

                     Turbo C xin chao cac ban.

                     Chuc cac ban thanh cong!

Trong chương trình, hàm printf là hàm đưa ra màn hình dãy kí tự nằm trong cặp dấu “ ...”. Dấu

là kí tự điều khiển xuống đầu dòng mới, không được in ra.

b. Ví dụ 2: Tính căn bậc hai của một số nguyên dương cho trước.

/* Chuong trinh C tinh can bac 2 cua so nguyen */

#include <stdio.h>

#include <conio.h>

#include <math.h>

main()                       /* có thể viết thêm void trước main() */

{  int n;

float  can;

printf(“Vao mot so nguyen duong:”); scanf(“%d”,&n);

can = sqrt(n);

printf(“Can bac 2 cua %d la %f

”,n,can);

getch();

 }

Ba dòng đầu của chương trình khai báo cho chương trình dịch đọc ba tệp:

Tệp stdio.h  - định nghĩa và nội dung hàm printf.

Tệp conio.h - chứa hàm vào ra getch.

Tệp math.h - chứa các hàm toán học.

Phần thân chương trình bắt đầu bằng hàm main() không có tham số và đặt trong cặp {...}.

Phần khai báo gồm hai dòng:

                int n;          để khai báo biến n có kiểu int (integer)

                float can;   để khai báo biến can có kiểu thực float.

Các lệnh tiếp theo sẽ hiển thị lên màn hình lời nhắc “Vao mot so nguyen duong” rồi dừng lại chờ vào dữ liệu cho biến n; tính căn bậc 2 của n rồi gán cho biến can; hiển thị tiếp dãy kết quả có dạng “Can bac 2 của .n.. là .can..” và dừng chờ xem kết quả (lệnh getch()) cho đến khi ấn Enter. Chú ý rằng, %d, %f là quy cách hiển thị số nguyên và số thực; &n chỉ địa chỉ của biến n.

c. Ví dụ 3: Tính chu vi và diện tích hình tròn biết bán kính là r.

#include <stdio.h>

#define  pi 3.1416

main()

{ float r, chu_vi, dien_tich;

    clrscr();     /*xoá màn hình*/

printf(“Ban kinh r=”);

scanf(“%f”, &r);

chu_vi = 2*pi*r;

dien_tich = pi*r*r;

printf(“Chu vi duong tron = %f

”, chu_vi);

printf(“Dien tich hinh tron = %f

”,dien_tich);

getch();

return(0);

 }

Trong C, mọi chương trình đều thể hiện qua các hàm. Bản thân main() cũng là một hàm. Về nguyên tắc, các hàm đều phải có return(...) để trả lại giá trị cho tên hàm. Tuy vậy, main() là hàm không phải trả giá trị cho hàm nào (chương trình chính) nên có thể không viết return.

2.3.2. Cấu trúc chung của một chương trình C

Một chương trình C thường có cấu trúc sau:

/* Gọi các tệp tiền xử lí và định nghĩa */

#include  <...>

#define       ...

/* Hàm chính - không có đối */

main()

{

   /*các lệnh của hàm main */

   return(0);  /*trả giá trị cho chương trình gọi hàm */

 }

/* Khai báo hàm người dùng */

<Kiểu dữ liệu>    <tên hàm>(danh sách tham số);

{

   /*Các lệnh của hàm */

  return(...);   /* trả giá trị cho tên hàm */

 }

Nói chung, chương trình C bao gồm nhiều hàm, trong đó, main() là hàm chính vì chỉ nó gọi hàm khác chứ không hàm nào gọi nó. Hàm main() luôn phải có trong mọi chương trình C. Tuy nhiên, hàm main() không phải trả kết quả cho tên hàm nên có thể viết void main() như trong ví dụ 1 phần 2.3.1.

Phần gọi các tệp tiền xử lí và định nghĩa, phần khai báo hàm người dùng có thể có hoặc không, tuỳ theo nhu cầu.

Các lệnh của hàm gồm các câu lệnh C để xử lí dữ liệu và được viết cách nhau dấu chấm phảy (;), nó có thể là các câu lệnh đơn (chỉ có một lệnh) hoặc khối lệnh (xét ở phần 2.4.). Mỗi dòng có thể viết nhiều lệnh, tuy vậy, trong C, một dòng lệnh phải có độ dài không quá 248 kí tự kể cả khoảng trống.

2.4. Khối lệnh

 Mỗi lệnh sẽ thực hiện một tác vụ và khi viết trong chương trình, nó được kết thúc bằng dấu chấm phảy (;). Có nhiều tác vụ không thể thực hiện bằng một lệnh đơn giản mà phải nhờ một tập hợp nhiều lệnh, ví dụ: ta viết “Nếu thoả mãn điều kiện a thì thực hiện tập hợp lệnh x, lệnh y và lệnh z”; tập hợp lệnh đó gọi là một khối lệnh. Trong chương trình C, khối lệnh là một dãy các lệnh đặt trong cặp dấu { và }. Mỗi khối lệnh có thể coi như một lệnh riêng lẻ, ở đâu đặt được một lệnh thì cũng có thể đặt được một khối lệnh. Những câu lệnh của một hàm, của cấu trúc phải đặt trong cấu trúc khối lệnh.

Trong mỗi chương trình C có thể có nhiều khối lệnh, trong khối lệnh này có thể chứa vô hạn khối lệnh khác nhưng các khối lệnh phải lồng nhau (không cắt nhau). Có thể minh hoạ trong sơ đồ sau:

Khi sử dụng cấu trúc khối lệnh lồng nhau, phải chú ý đến sự tương tác giữa các biến (biến đơn, biến mảng) trong và ngoài khối lệnh, cụ thể:

Ø  Nếu khai báo một biến ở ngoài khối lệnh không trùng tên với biến nằm trong khối lệnh thì khối lệnh nằm trong được phép sử dụng biến ngoài khối lệnh đó. Đây là trường hợp biến dùng chung (public) mà ta đã nói đến trong phần 1.3.2.(a).

Ø  Nếu trong và ngoài khối lệnh đều có khai báo một biến (trùng tên) thì biến ở khối lệnh nằm trong là biến địa phương, chỉ của khối lệnh đó, không ảnh hưởng đến khối lệnh nằm ngoài.

            Có thể minh hoạ điều đó trong sơ đồ sau:

2.5. Các lệnh cơ bản của C

2.5.1. Các phép gán, vào/ra dữ liệu

Chương trình có cấu trúc tuần tự

2.5.1.1. Lệnh gán, các phép toán tăng và giảm 1

a. Lệnh gán:

·    Tác dụng: Tính giá trị của biểu thức rồi gán cho các biến.

·    Cú pháp: <Biến>=<Biểu thức>;

Trong đó: Biến là một biến bất kì đã được khai báo, cần gán giá trị;

                 Biểu thức là một biểu thức bất kì.

·      Tác động: Máy sẽ tính giá trị của biểu thức rồi gán giá trị đó cho biến. Nếu sau khai báo, biến chưa được gán giá trị ban đầu thì lệnh này sẽ gán giá trị ban đầu cho biến. Nếu biến đã được gán giá trị thì giá trị cũ sẽ bị mất đi và nhận giá trị mới là giá trị của biểu thức.

·      Ví dụ:

main()

{

   int i, j , k;   float a ; char  c;

   i = 1;                     /* i=1 */

   j = i + 1;                /* j=2 */

   k = 3<4 ;               /* k=1 */

   a = 12.345;            /* a=12,345 */

   c = ‘A’;                  /* c nhận kí tự A */

   i = 10;                   /* i=10 */

 /* Các lệnh tiếp theo */

 }

·      Một số chú ý:

- Nếu biến và biểu thức không cùng kiểu, máy sẽ tự động đổi kiểu biểu thức cho phù hợp với biến rồi thực hiện phép gán. Phải chú ý, nếu không sẽ ảnh hưởng đến độ chính xác của kết quả.

Ví dụ:

main()

{

  int i;   float f;   char c;

  i = 1.6;                  /* i=1 */

  f = 2;                     /* f=2.0*/

  c = 65;                   /* c=’A’ */

  .................

 }

- Trong C cho phép gán kép cho nhiều biến, có dạng:

<biến1> [= biến2] [= ... biến n] = <biểu thức>;

Ví dụ:

 a = b = c =  d = 10; tương đương với a=(b=(c=(d=10)));

 z = (y = 2) + ( x = 4);  sẽ đồng thời gán y=2, x=4 và z=6.

- Trong C còn cho phép gán phức hợp (còn gọi là phép gán mở rộng), có dạng:

<biến pt> = < biểu thức>;

Trong đó:

Vế trái chỉ là một biến duy nhất;

pt có thể là một trong các phép toán hai ngôi (có hai toán hạng tham gia như: +, -, *, /, %, >, <, ...).

Ví dụ:

a + = b;                       /* a = a + b */

x * = y;                       /* x = x * y */

- Có thể sử dụng toán tử phẩy trong phép gán. Đây là một toán tử đặc biệt kí hiệu là dấu phẩy “,” bao gồm hai biểu thức cách nhau dấu phẩy và được tính toán từ biểu thức bên trái rồi đến biểu thức bên phải. Kết quả của biểu thức phẩy là kết quả của biểu thức bên phải.

     Ví dụ:

S = (i = 2, h = i * i + 1);   /* sẽ cho i=2, h=5 và S=5 */

-  Trong các biểu thức có tính giao hoán, C không xác định trật tự tính toán xác định, ví dụ như, nếu viết:  x = a + b; thì chưa xác định được lấy a cộng với b hay lấy b cộng với a.Trong biểu thức này, kết quả vẫn như nhau. Song, có nhiều biểu thức có tính giao hoán, việc lấy đại lượng nào trước đại lượng nào sau lại ảnh hưởng tới kết quả. Ví dụ, có hai hàm function1() và hàm function2(), viết: 

x = function1() + function2();

Khi đó, hàm function1() hay function2() tính trước có thể làm cho x có giá trị khác nhau. Trường hợp hàm này làm thay đổi biến dùng chung mà hàm kia dùng tới sẽ ảnh hưởng tới giá trị của biến x khi hàm nào tính trước. Hiện tượng này gọi là hiệu ứng lề (ngoài lề), gây ra tình trạng rất khó kiểm soát. Để khắc phục hiệu ứng lề, người lập trình nên tự xác định trật tự tính toán nhờ kĩ thuật lập trình, ví dụ, ta dùng một biến Trung_gian để bắt hàm function1() tính trước, viết như sau:

Trung_gian = function1();

x =  Trung_gian + function2();

b. Phép toán tăng và  giảm 1:

Trong C cung cấp hai phép toán một ngôi để làm tăng và giảm giá trị của một biến có kiểu bất kì đi 1, đó là phép toán ++ và -- . Các phép toán này có có hai dạng:

1. ++ biến     hoặc - -biến

2.  biến++  hoặc biến - -

Trong đó:

Các dấu ++ và -- phải viết liền nhau;

ở dạng 1, biến được tăng (với phép toán ++) hoặc giảm (với phép toán -- ) đi 1 trước khi sử dụng biến; Dạng 2, biến được sử dụng rồi mới tăng hoặc giảm đi 1.

Ví dụ:

Dùng phép tăng giảm

Tương tự như

Kết quả

int  i=19, j=5;

float a,b,c;

a = (float) ++i/j--;

b = a-- +  i--/j;      

c = a + i;              

i=i+1; a=(float)i/j; j=j-1;

b=a+i/j; a=a-1; i=i-1;

/* a=4.0 , i=20, j=4 */

/* b= 9.0 , a=3.0, i=19 */

 /* c=22.0 */    

Chú ý:

- Toán hạng trong phép toán này phải là một biến để xác định được địa chỉ cụ thể của trường nhớ cần tăng/giảm 1, không được là biểu thức tổng quát.

- Các phép toán tăng và giảm sẽ được máy thực hiện nhanh hơn phép gán vì rất gần với ngôn ngữ máy.

2.5.1.2. Xuất thông tin

a. Lệnh printf:

· Lệnh này sẽ gọi hàm printf nằm trong tệp tiêu đề stdio.h. Muốn gọi hàm, phần đầu chương trình phải có khai báo #include <stdio.h> để trình biên dịch chèn tệp tiêu đề stdio.h vào đầu chương trình.

· Công dụng: Hiển thị giá trị các biểu thức lên màn hình.

· Cú pháp:  printf(“Xâu điều khiển” [,Danh sách biểu thức]);

Trong đó:

- Xâu điều khiển là một xâu, chứa 3 thành phần:

+ Những kí tự mang tính thông báo kết quả cho người đọc. Thành phần này có thể có hoặc không;

+ Các kí tự điều khiển để điểu khiển quá trình đưa ra, bao gồm các kí tự:

, \r, \t, ... Thành phần này có thể có hoặc không;

+ Các mã định dạng (format code) để định dạng dãy thông tin được hiển thị; Thành phần này bắt buộc phải có nếu có ít nhất một biểu thức trong danh sách biểu thức, gồm các mã cho ở bảng sau:

Mã định dạng

Kiểu dữ liệu

ý nghĩa

%c

char, int, short

Hiển thị một kí tự

%d

int, char

Hiển thị một số nguyên kiểu int

%u

unsigned int,

unsigned short

Hiển thị một số nguyên không dấu kiểu unsigned int

%x, %X

Số nguyên

Hiển thị một số nguyên dạng hệ 16 (hexa)

%o

Số nguyên

Hiển thị một số nguyên dạng hệ 8 (octal)

%f

float, double

Hiển thị một số thực dạng dấu chấm tĩnh

%e, %E

Số thực

Hiển thị một số thực dấu chấm động với 5 chữ số phần phân ở phần định trị

%g, %G

Số thực

Hiển thị kiểu %f hay %e tuỳ dạng nào ngắn hơn

%s

Xâu

Hiển thị một xâu kí tự

Chú ý: - Thêm l hoặc L vào ngay sau dấu % ở mã định dạng các kiểu d, o, x để chuyển sang kiểu long; ở các mã e, E, g, G, f để chuyển sang kiểu double;

            - các mã %c, %d,%u, %x, %o có thể viết thêm số nguyên không dấu n ngay sau dấu % để định dạng tường minh cho số nguyên được hiển thị trên n cột;

-     Với mã %f (ngầm định) có thể viết dạng %n.mf hoặc %nf (tự động cho m=6) để định dạng một cách tường minh cho số thực dấu chấm tĩnh được đưa ra với chiều dài là n và m chữ số thập phân.

- Danh sách biểu thức gồm tập hợp các biểu thức cần hiển thị giá trị, viết cách nhau dấu phảy. Nhớ rằng, mỗi biểu thức phải có tương ứng (theo thứ tự) một mã định dạng; Mã định dạng phải phù hợp với kiểu của biểu thức tương ứng.

·  Tác động:

Máy sẽ hiển thị lên màn hình các kí tự thông báo (nếu có) kèm theo giá trị các biểu thức trong danh sách biểu thức. Giá trị mỗi biểu thức được đưa ra sẽ rơi vào đúng vị trí của mã định dạng tương ứng nằm trong xâu điều khiển. Cách đưa ra cụ thể như sau:

- Theo định dạng ngầm định, số nguyên khi đưa ra, được dành số cột đúng bằng số chữ số của nó và dấu (nếu có); Số thực đưa ra dạng dấu chấm tĩnh có độ dài bằng độ dài phần nguyên, dấu chấm và 6 chữ số thập phân (nhiều hơn 6 chữ số thập phân sẽ làm tròn, ít hơn sẽ bổ sung số 0 vô nghĩa); Số thực đưa ra dạng dấu chấm động, ở phần định trị có 1 chữ số phần nguyên, 5 chữ số phần phân; Kiểu char được đưa ra trên 1 cột; Kiểu xâu sử dụng số cột đúng bằng số kí tự trong xâu.

- Theo định dạng tường minh, số cột dành để  đưa ra các biểu thức đã được xác định trước theo ý đồ của người lập trình, nếu thừa thì chèn thêm kí tự khoảng trống phía trước, nếu thiếu sẽ tự động bổ sung để đủ chỗ đưa ra như trường hợp ngầm định.

·  Ví dụ: Có một chương trình C:

#include <sdtio.h>

#include <conio.h>

main()

{

    char c = ‘A’;     

    int i,j=10;

    float a = 123.45;

    i = j*j+5;

    clrscr()    /* Lệnh xoá màn hình trong tệp conio.h */

    printf(“Kết quả đưa ra màn hình

”);                 /* Lệnh 1 */

    printf(“i=%d, j=%d

Kí tự=%c, a=%f

”, i,j,c,a);            /* Lệnh 2*/

    printf(“i=%2d, j=%4d

Kí tự=%d, a=%9.2f

”, i,j,c,a);   /* Lệnh 3 */

    printf(“Dấu chấm động, a=%e

”, a);                                 /* Lệnh 4 */

    printf(“Số %d hệ 10 =  %x hoặc %X hệ 16

”,90, 90,90);   /* Lệnh 5 */

    printf(“%s”, “Kết thúc.”);                                                     /* Lệnh 6 */

}

Khi thực hiện, màn hình sẽ hiển thị như sau:

Lệnh 1: Kết quả đưa ra màn hình      (từ dòng 1 cột 1)

Lệnh 2:  i=105,    j=10                                      (từ dòng 2 cột 1)

              Kí tự=A,    a=123.449997                   (từ dòng 3 cột 1)

Lệnh 3:  i=105,   j=       10

              Kí tự=65,    a=          123.45

Lệnh 4:  Dấu chấm động, a=1.23450e+02

Lệnh 5:  Số 90 hệ 10 = 5a hoặc 5A hệ 16

Lệnh 6:  Kết thúc.

·  Một số chú ý:

- Một số trường hợp mã định dạng và biểu thức không phù hợp kiểu, trình biên dịch sẽ tự động chuyển kiểu biểu thức theo mã định dạng để đưa ra. Nếu cùng độ dài trường nhớ, ví dụ %u cho số int hay %d cho số unsigned int, đều định dạng cho số ở 2 byte nhưng cách truy nhập khác nhau nên giá trị khác nhau. Nếu độ dài trường nhớ khác nhau, máy sẽ lấy trường tiếp theo để bù. Điều này cũng gây sai kết quả được hiển thị.

Ví dụ:  Mã định dạng         Biểu thức               Giá trị hiển thị             

                   %d                       ‘A’                              65

                   %c                        65                              ‘A’

                   %c                   4*256+65                       ‘A’

                   %d                     65535                            -1 (sai!)

- Khi số lượng mã định dạng không bằng số lượng biểu thức, máy sẽ căn cứ vào số mã định dạng để đưa ra, mỗi mã định dạng đưa ra một giá trị. Nếu thừa biểu thức nào thì không đưa ra giá trị biểu thức đó, ngược lại, nếu thiếu biểu thức sẽ đưa ra một số ngẫu nhiên.

Ví dụ:

printf(“%d”,123,456);               /* Lệnh 1 */

printf(“%d  %d”,123);               /* Lệnh 2 */

Lệnh 1 chỉ đưa ra số 123, số 456 không có mã định dạng để đưa ra.

Lệnh 2 đưa ra số 123 và một số ngẫu nhiên nào đó!

- Khi đưa ra số thực dấu chấm tĩnh dùng mã định dạng %m.nf, có thể viết m và n bằng kí tự thay thế là dấu *. Khi đó, dấu * được gán giá trị thực bằng cách đọc một cách tương ứng (theo thứ tự) trong xâu điều khiển của lệnh printf.

Ví dụ:

main()

{

  int n,m;

  n=9;

m=2;

printf(“%d, %*.*f”, 987, n, m, 123.456);

}

Chương trình sẽ đưa ra màn hình như sau:

987,          123.46

b. Lệnh putchar

·    putchar là một macro viết trong tệp stdio.h

·    Công dụng: Hiển thị một kí tự ra màn hình.

·    Cú pháp:  putchar(c); 

Trong đó: c là một đại lượng kiểu char.

·      Tác động: Lệnh sẽ hiển thị lên màn hình kí tự c.

·      Ví dụ:

char c;

c = ‘A’;

  putchar(c);  /* hiển thị chữ A */

Dễ thấy lệnh putchar(c); tương đương với printf(“%c”, c);

c. Lệnh puts

·    puts là một hàm trong tệp stdio.h

·    Công dụng: Hiển thị một xâu kí tự lên màn hình.

·    Cú pháp:  puts(s)   với s là một đại lượng kiểu xâu.

·    Tác động: Lệnh hiển thị xâu kí tự s lên màn hình.

·    Ví dụ: puts(“Con thuyền không bến”);

d. Lệnh fprintf

·        fprintf là một hàm trong tệp stdio.h

·       Công dụng: In ra máy in giá trị của các biểu thức.

·       Cú pháp: fprintf(stdprn, <xâu điều khiển> [,danh sách biểu thức]);

·       Tác động: Tương tự như lệnh printf nhưng kết quả sẽ hiển thị ở máy in.

·       Ví dụ: fprintf(stdprn, “In ra số %d”, 100);

sẽ in ra máy in dòng: In ra số 100

·         Chú ý: Trong C, dữ liệu ở bộ nhớ trong có thể trao đổi với nhiều bộ phận khác nhau. Mỗi hệ thống trao đổi ấy, người ta gọi là một luồng. Những luồng dữ liệu thường gặp nhất gồm:

stdin               Bàn phím

stdout             Màn hình

stderr              Màn hình

stdprn             Máy in

stdaux            Cổng nối tiếp

fprintf() là hàm tổng quát để đưa dữ liệu ra các luồng khác nhau. Lệnh printf() thực chất là lệnh fprintf(stdout, ...) với stdout là một luồng dữ liệu chuẩn.

2.5.1.3. Nhập dữ liệu từ bàn phím

a. Lệnh scanf

·  scanf là một hàm trong tệp stdio.h

·  Công dụng: Đọc dữ liệu vào từ bàn phím và lưu trữ nó trong các biến (trường nhớ) ở bộ nhớ trong.

·  Cú pháp:

scanf(“Xâu điều khiển”, <danh sách địa chỉ biến>);

Trong đó:

- Xâu điều khiển chỉ chứa các mã định dạng để điều khiển quá trình đọc vào các biến trong bộ nhớ. Giữa các mã định dạng có thể có khoảng trống hoặc không. Các mã định dạng đọc dữ liệu cho scanf được liệt kê ở bảng dưới đây:

Mã định dạng

Kiểu dữ liệu

ý nghĩa

%c

char

Đọc một kí tự

%d

Đọc một số nguyên kiểu int

%u

unsigned int

Đọc một số nguyên không dấu kiểu unsigned int

%hd

short int

Đọc một số nguyên kiểu short int

%hu

unsigned int

Đọc một số nguyên kiểu unsigned int

%ld

long int

Đọc một số nguyên kiểu long in

%lu

unsigned long

Đọc một số nguyên kiểu unsigned long

%x

Số nguyên

Đọc một số nguyên dạng hệ 16 (hexa)

%o

Số nguyên

Đọc một số nguyên dạng hệ 8 (octal)

%f

float

Đọc một số thực kiểu float dạng dấu chấm tĩnh hoặc chấm động

%lf

double

Đọc một số thực kiểu double

%e

float

Giống %f

%s

Xâu

Đọc một xâu kí tự không chứa khoảng trống

Chú ý: -  ở các mã %c,  %d, %u, %x, %o, %s có thể viết thêm số nguyên không dấu n ngay sau dấu % để định dạng tường minh cho việc đọc n kí tự từ bàn phím;

-     Với mã %f (ngầm định) có thể viết dạng %n.mf hoặc %nf hoặc %.mf  để định dạng một cách tường minh cho số thực dấu chấm tĩnh được đọc vào với chiều dài là n và m chữ số thập phân.

-     Khi đưa ra, một mã có thể dùng cho nhiều kiểu số nhưng khi đọc vào bằng  scanf, mỗi mã chỉ ứng với một kiểu số vì nó liên quan trực tiếp đến việc lưu trữ ở bộ nhớ trong.

- Danh sách địa chỉ biến gồm các địa chỉ biến cần nhập giá trị vào, viết cách nhau dấu phảy. Trong C, muốn viết địa chỉ một biến, ta viết thêm dấu & trước tên biến đó (chẳng hạn, địa chỉ biến  x được viết là &x).

Khác với quá trình đưa ra, khi đọc vào, số mã định dạng và số địa chỉ biến phải bằng nhau.

·  Tác động: Khi gặp lệnh scanf, máy sẽ dừng lại chờ người sử dụng vào dữ liệu từ bàn phím. Khi đó, người sử dụng phải đưa dữ liệu vào.

Dữ liệu đưa vào là một xâu kí tự do người sử dụng gõ vào từ bàn phím, kết thúc là phím Enter (tương ứng với kí tự xuống dòng (

). Để tiện kiểm soát khi nhập liệu, người ta thường đặt thêm các dấu ngăn (gồm: khoảng trống, Enter, Tab) giữa các đơn vị dữ liệu; Tuy nhiên, trong trường hợp này, giữa các mã định dạng thường phải có khoảng trống.

Tất cả các kí tự được gõ vào, theo thứ tự, sẽ được lưu tạm thời trong vùng nhớ đệm bàn phím (buffer - bộ đệm). Sau khi ấn Enter, máy sẽ tiến hành đọc dữ liệu từ bộ đệm vào các biến trong danh sách một cách tuần tự theo sự điều khiển của mã định dạng. Cách thức đọc cụ thể như sau:

- Cách đọc số: Xét tuần tự nội dung bộ nhớ đệm, bỏ qua các dấu ngăn dữ liệu (khoảng trống, Tab, Enter) đến khi gặp chữ số đầu tiên thì bắt đầu đọc, đến khi gặp kí tự đầu tiên không phải là chữ số hoặc đã đủ số chữ số được chỉ định theo mã định dạng tường minh thì dừng lại. Dãy chữ số vừa đọc sẽ được chuyển thành số và ghi vào biến.

- Cách đọc kí tự: Chỉ đọc một kí tự và ghi vào trường nhớ của biến kiểu char.

- Cách đọc xâu: Đọc các kí tự cho đến khi gặp khoảng trống hoặc đủ số kí tự yêu cầu trong định dạng tường minh rồi ghi vào mảng (sẽ nghiên cứu ở phần sau).

·  Ví dụ:

Ví dụ 1: Lệnh nhập số nguyên vào hai biến i và j có kiểu int:

              scanf(“%d%d”,  &i, &j);

Ví dụ 2: Lệnh nhập số thực vào hai biến a và  b có kiểu  float:

              scanf(“%f%f”,  &a, &b);

Ví dụ 3: Lệnh nhập một số nguyên không quá 3 chữ số vào biến i kiểu int :

              scanf(“%3d”,  &i);

Ví dụ 4: Lệnh nhập một số thực vào biến a kiểu float có không quá 2 chữ số phần thập phân:

              scanf(“%.2f”,  &a);

Ví dụ 5: Lệnh nhập 1 kí tự vào biến c có kiểu char và 1 số nguyên vào biến i  có kiểu long int:

              scanf(“%c%ld”, &c, &i);

Ví dụ 6:

Lệnh:

int i, j;

scanf(“%3d  %d”, &i, &j);

Dữ liệu vào

Kết quả

   1234567   89

i=123; j=4567

12   32767ABC

i=12 ; j=32767

Ví dụ 7:

Lệnh:

char c;  int i;

scanf(“%d%c”, &i, &c);

Dữ liệu vào

Kết quả

   12345ABC

i=12345; c=’A’

12345   ABC

i=12345 ; c=’   ‘. Nếu xâu điều khiển là “%d   %c” thì c=’A’

·   Chú ý:

-  Bộ đệm là một trường nhớ ở bộ nhớ trong được tổ chức kiểu FIFO (vào trước ra trước) để lưu tạm thời các thông tin chờ xử lí. Khi nhập các kí tự vào, trước tiên, nó nằm trong bộ đệm. Lệnh scanf sẽ đọc từ bộ đệm (không đọc trực tiếp từ bàn phím) nhưng có thể chưa đọc hết các kí tự vào, điều đó sẽ ảnh hưởng tới lần đọc tiếp theo mà ta khó quản lí hết được. Chẳng hạn, trong ví dụ 7, trường hợp nhập vào 12345ABC, sau khi đọc xong, bộ đệm vẫn còn 3 kí tự là BC

. Lệnh đọc tiếp theo sẽ đọc tiếp phần này mà ta ít để ý đến.

Để khắc phục hiện tượng này, có thể dùng mã định dạng %*c để loại kí tự

(kí tự tương ứng khi bấm Enter, mã là 10) ra khỏi bộ đệm; Ngoài ra, cũng có thể dùng hàm fflush(stdin)  sau lệnh scanf để xoá tất cả những gì còn lại trong bộ đệm sau khi thực hiện xong lệnh scanf.

Ví dụ:

Để nhập một số nguyên và một kí tự từ bàn phím rồi hiển thị hai giá trị đó ra màn hình, ta viết chương trình sau:

# include  <stdio.h>

main()

{

  int i;  char c;

  printf(“Nhập số nguyên = ”); scanf(“%d”,&i);

  printf(“Nhập một kí tự : ”); scanf(“%c”,&c);

  printf(“Số nguyên =  %d, Kí tự = %c”, i , c);

}

Nếu nhập số nguyên là 123¿ thì lệnh scanf thứ hai đọc một kí tự sẽ bị trôi. Kết quả là: i = 123,  c =’

Nếu nhập 123ab¿ thì kết quả là: i = 123, c = a

Để khắc phục hiện tượng “trôi” , ta viết”

# include  <stdio.h>

main()

{

  int i;  char c;

  printf(“Nhập số nguyên = ”); scanf(“%d”,&i);

  fflush(stdin);

/* hoặc scanf(“%d%*c”,&i) nếu chỉ loại kí tự ¿*/

  printf(“Nhập một kí tự : ”); scanf(“%c”,&c);

  printf(“Số nguyên =  %d, Kí tự = %c”, i , c);

}

- Trường hợp giữa các mã định dạng, ta chèn thêm dấu khoảng trống, thì khi đọc từ bộ đệm, máy sẽ bỏ qua các dấu ngăn trong dãy dữ liệu đưa vào. Hãy xem trường hợp 2 của ví dụ 7!

b. Lệnh getchar

·  getchar là một macro trong tệp stdio.h bằng cách định nghĩa:

#define getchar() getc(stdin)

(có thể mở tệp stdio.h và xem lại!)

·  Công dụng: Đọc một kí tự từ bàn phím vào một biến kiểu char.

·  Cú pháp: <c> = getchar();

Với c là một biến kiểu char cần đọc vào một kí tự.

·  Tác động: Máy dừng chờ người sử dụng vào một kí tự, kết thúc ấn Enter, kí tự đó sẽ được gán cho biến.

·  Chú ý:

-        getchar() chính là hàm đọc kí tự getc() từ luồng vào chuẩn stdin có sử dụng bộ đệm bàn phím.

-        Hàm getch() sẽ đọc một kí tự từ bàn phím ngay say khi kí tự được gõ vào (không cần ấn enter). getch khác với getchar ở chỗ: kí tự gõ vào không hiển thị lên màn hình, không sử dụng bộ đệm.

-        Hàm getche() tương tự như hàm getch() nhưng kí tự gõ vào sẽ hiển thị lên màn hình.

c. Lệnh gets.

·  gets() là một hàm nằm trong tệp stdio.h

·  Công dụng: Đọc một xâu văn bản cho đến khi gặp kí tự

.

·  Cú pháp:

gets(s);  với s là một biến xâu (tên mảng) cần nhận giá trị từ bàn phím.

·  Tác động: Máy dừng lại chờ người sử dụng nhập một xâu từ bàn phím, kết thúc ấn Enter. Xâu này được đưa vào bộ đệm bàn phím, cả kí tự

rồi đọc vào biến xâu s. Sau khi đọc xong sẽ tự động loại kí tự

ra khỏi bộ nhớ đệm.

·  Ví dụ:

#include <stdio.h>

#include <conio.h>

main()

{

char hoten[40];

printf(“Nhập họ tên của bạn :”);

gets(hoten);

clrscr();

printf(“

Chào mừng bạn %s đến với Turbo C”, hoten);

getch();

}

Lưu ý: stdin là luồng vào chuẩn sử dụng một bộ nhớ đệm bàn phím. Các hàm: scanf, gets, getchar bao giờ cũng đọc dữ liệu từ stdin theo nguyên tắc:

- Nếu stdin có đủ dữ liệu thì chúng nhận một phần dữ liệu theo yêu cầu, phần còn lại vẫn giữ nguyên nên phải chú ý quán xuyến quá trình đọc này để không gây trục trặc vì trôi dữ liệu;

- Nếu stdin không đủ dữ liệu theo yêu cầu thì máy tạm dừng chờ người sử dụng đưa dữ liệu từ bàn phím lên stdin cho đến khi gặp

lại tiếp tục đọc và cứ như thế cho đến khi đọc đủ dữ liệu thì thôi;

- Sau khi đọc xong, xoá khỏi stdin phần dữ liệu đã đọc;

- Kí tự

chỉ được gets tự động xoá khỏi stdin sau khi đọc, còn với scanf và getchar thì không.

2.5.1.4. Chương trình có cấu trúc tuần tự.

Một chương trình C được gọi là cáo cấu trúc tuần tự (tuyến tính) khi các lệnh trong trong chương trình sẽ được thực hiện tuần tự, một lần theo thứ tự liệt kê từ trên xuống dưới. Cấu trúc này được quy định bởi cấu trúc của thuật toán.

Ví dụ: Chương trình tính chu và diện tích hình tam giác biết ba cạnh là a,b,c.

#include  <stdio.h>  /* Cho vào-ra chuẩn */

#include  <conio.h> /* Cho clrscr() */

#include  <math.h>  /* Cho hàm sqrt() */

main()

{

float a, b, c, p, chu_vi, dien_tich;

    clrscr();     /*xoá màn hình*/

printf(“Vào a, b, c cách nhau dấu cách: ”);

scanf(“%f %f %f ”, &a, &b, &c);

fflush(stdin);

chu_vi = a + b + c;

dien_tich = sqrt(p*(p-a)*(p-b)*(p-c));

printf(“Chu vi tam giac = %f

”, chu_vi);

printf(“Dien tich tam giac = %f

”,dien_tich);

getch();

return(0);

 }

2.5.2 Lệnh điều khiển rẽ nhánh

2.5.2.1. Lệnh if .. else

·  Công dụng: Tổ chức một cấu trúc điều kiện trong chương trình C.

·  Cú pháp:

   if  (biểu thức)  <nhóm lệnh 1>  [ else <nhóm lệnh 2>];

Trong đó:

- if,  else là hai từ khoá;

- Biểu thức là một biểu thức bất kì, thường là biểu thức logic. Khi viết, phải đặt biểu thức trong cặp dấu ngoặc tròn (...);

- Nhóm lệnh 1, 2 là tập hợp các lệnh C bất kì (lệnh đơn, khối lệnh, lệnh có cấu trúc), nếu có từ hai lệnh trở lên, phải đặt trong cấu trúc khối lệnh {...}.

·  Tác động:

Máy tính và kiểm tra giá trị của biểu thức:

- Nếu biểu thức nhận giá trị khác 0 (là giá trị logic đúng) sẽ thực hiện các lệnh trong <nhóm lệnh 1> rồi thực hiện lệnh tiếp theo đứng sau lệnh if này;

- Nếu biểu thức nhận giá trị bằng 0 (sai):

Ø      Trường hợp trong lệnh có mệnh đề else ... sẽ thực hiện các lệnh trong nhóm  lệnh 2 tương tự như nhóm lệnh 1;

Ø      Trường hợp trong lệnh không có mệnh đề else ... thì coi như đã thực hiện xong lệnh if này (không làm gì cả), tiếp tục thực hiện lệnh đứng ngay sau if.

Có thể mô tả quá trình thực hiện lệnh if qua sơ đồ khối sau:

·  Ví dụ:

- Ví dụ 1: Kiểm tra một số vào từ bàn phím là số bằng hay khác không.

#include   <stdio.h>

main( )

{

float number;

printf(“Vao mot so bat ki ? ”);

scanf(“%f”, &number);

if  (number)

{

  printf(“Số vừa vào khác không

”);

  printf(“Giá trị là %f”, number);

}

else

printf(“Số vừa vào bằng không

”);

getch( );

}

- Ví dụ 2: Tìm giá trị lớn nhất trong hai số bất kì nhập vào từ bàn phím.

#include   <stdio.h>

main( )

{

float a, b, max;

printf(“

Vao so thu nhat = ”);

scanf(“%f”, &a);

printf(“

Vao so thu hai = ”);

scanf(“%f”, &b);

max = a;

if  (max<b) max = b;

printf(“Gia trị lon nhat trong hai so la: %f

”, max );

getch( );

}

- Ví dụ 3: Giải phương trình bậc 2: ax2 + bx + c = 0

#include  <stdio.h>

#include  <math.h>

main( )

{

float a, b, c, d;

printf(“Bạn hãy nhập các hệ số của phương trình”);

printf(“

Hệ số a = ”); scanf(“%f”, &a);

printf(“

Hệ số b = ”); scanf(“%f”, &b);

printf(“

Hệ số c = ”); scanf(“%f”, &c);

if  (a == 0)    /* cảnh giác với điều kiện (a=0) */

printf(“

Không phải phương trình bậc hai; Vào lại số a!”);

else

{

d = b*b – 4*a*c;

if  (d < 0) 

printf(“

Phương trình đã cho vô nghiệm”);

else

if  (d = = 0)

   printf(“

Phương trình có nghiệm kép x = %f”, -b/(2*a);

else

   {

printf(

Phương trình có hai nghiệm:”;

printf(

x1 = %f ”, (-b – sqrt(d))/(2*a);

printf(

x2 = %f ”, (-b + sqrt(d))/(2*a);

}

}

getch( );

}

·  Chú ý:

-     Có thể thay thế lệnh if ... else ... bằng cách sử dụng biểu thức điều kiện.  Ví dụ, muốn xác định giá trị lớn nhất Max của hai số a và b, ta có thể viết:

Max = (a > b) ? a : b;

hoặc:  (a > b) ?  (Max = a) : (Max = b)

-     Khi nhóm lệnh 1 và nhóm lệnh 2 chứa lệnh có cấu trúc hay một khối lệnh thì lệnh có cấu trúc hay khối lệnh đó phải nằm trọn vẹn trong từng nhóm lệnh. Chẳng hạn, trong lệnh if này có một if khác như sau:

if (d= =0) if  (dx= =0 && dy= =0)  printf(“Hệ vô định”);

else printf(“Hệ vô nghiệm”);

Việc kiểm soát chương trình, nếu bất cẩn sẽ rất dễ nhầm lẫn, không xác định được mệnh else của lệnh if thứ nhất hay lệnh if thứ hai !

ở đây, ta phải theo nguyên tắc xác định của chương trình dịch, đó là: else sẽ đi với lệnh if cuối cùng nếu lệnh if đó chưa có else đi cùng. Trong ví dụ trên, else sẽ  của lệnh if thứ 2 và để dễ nhận biết, ta nên viết như sau:

if (d= =0)

if  (dx= =0 && dy= =0)

 printf(“Hệ vô định”;

else

printf(“Hệ vô nghiệm”);

2.5.2.2. Lệnh switch

·  Công dụng: Bản thân từ switch nghĩa là chuyển mạch. Lệnh switch trong C dùng để tổ chức một cấu trúc rẽ nhiều nhánh trong chương trình. Việc rẽ nhánh của chương trình có thể được tổ chức bằng lệnh if, tuy nhiên, mỗi lệnh if chỉ rẽ thành hai nhánh tương ứng với giá trị một biểu thức là 0 (sai) hay khác 0 (đúng). Có thể thấy, việc rẽ nhiều nhánh ở lệnh switch có thể thay thế bằng các lệnh if.

·  Cú pháp:

switch (biểu thức)

{

case n1 : [nhóm lệnh 1;]

case n2 : [nhóm lệnh 2;]

 . . .

case nk : [nhóm lệnh k;]

[default : nhóm lệnh k+1;]

}

Trong đó:

-     Biểu thức là một biểu thức bất kì nhưng phải có kết quả là một số nguyên (char, int, long, unsigned, ...);

-     ni  (i=1àk) là các hằng nguyên hoặc kiểu char (kiểu char sẽ được chuyển thành kiểu int) và bắt buộc phải có giá trị khác nhau;

-     Nhóm lệnh i (i=1àk+1) gồm tập hợp các lệnh bất kì của C, nếu có nhiều lệnh, không cần đặt trong cấu trúc khối lệnh;

-     Đoạn trình nằm trong cặp dấu { } gọi là thân switch. Khi nói thoát khỏi switch nghĩa là thoát ra khỏi dấu } cuối cùng của switch.

·  Tác động:

Bước 1: Máy tính giá trị của biểu thức. Biểu thức sẽ quyết định sự hoạt động của switch.

Bước 2: Duyệt lần lượt các giá trị ni (i=1àk), khi gặp ni nào thoả mãn điều kiện (biểu thức = ni) thì cho thực hiện nhóm lệnh i tương ứng. Trong trường hợp giá trị của biểu thức khác tất cả các giá trị ni thì sẽ phụ thuộc vào trong lệnh switch có  mặt default (thành phần tự chọn) hay không, cụ thể như sau:

-      Nếu có default thì: Thực hiện nhóm lệnh k+1 rồi thoát khỏi switch;

-      Nếu không có default thì: thoát khỏi switch.

·  Chú ý:

-      Các ni và default được coi như các nhãn nên sau khi thực hiện xong nhóm lệnh i của case ni đó, nó sẽ thực hiện luôn nhóm lệnh i+1 của case dưới nó mà không xét lại điều kiện (biểu thức = ni +1 ) có thoả mãn hay không. Trong trường hợp cần thiết phải thoát khỏi thân switch ngay sau khi thực hiện một nhóm lệnh nào đó, ở cuối nhóm lệnh đó người ta viết thêm lệnh break;

-      Việc thoát ra khỏi thân switch được thực hiện trong các trường hợp: Gặp lệnh break; hoặc dấu } cuối cùng của thân switch hoặc lệnh goto từ trong thân lệnh switch ra ngoài thân switch (sẽ xét sau). Trường hợp switch nằm trong một hàm, có thể thoát khỏi thân switch bằng return().

·  Ví dụ:

-        Ví dụ 1: Đọc một số nguyên có giá trị từ 1 đến 5 từ bàn phím rồi hiển thị bằng chữ giá trị số vừa nhập.

# include  <stdio.h>

# include  <conio.h>

main()

{

printf(“Vào một số nguyên từ 1 đến 5

”);

scanf(“%d”, &n);

clrscr();

switch (n)

{

case 1 : printf(“%d đọc là một

”, n);

             break;

case 2 : printf(“%d đọc là hai

”,n);

             break;

case 3 : printf(“%d đọc là ba

”,n);

             break;

case 4 : printf(“%d đọc là bốn

”,n);

             break;

case 5 : printf(“%d đọc là năm

”,n);

             break;

default : printf(“Nhập sai ”);

}

printf(“ các bạn ạ!”);

getch();

}

Nếu vào n=5, máy sẽ hiển thị:

5 đọc là năm

các bạn ạ!

Nếu vào n không phải là các số từ 1 đến 5, máy sẽ hiển thị:

Nhập sai các bạn ạ!

Để thấy rõ hiệu lực của các lệnh break; và cách thực hiện lệnh switch theo chú ý thứ nhất, ta thử bỏ break; trong một vài case và kiểm nghiệm lại. Ví dụ:

Ø  Bỏ lệnh break; trong case 4, khi n=4, máy sẽ hiển thị:

4 đọc là bốn

4 đọc là năm

các bạn ạ!

Ø  Bỏ lệnh break; trong case 4 và case 5, khi n=4, máy sẽ hiển thị:

4 đọc là bốn

4 đọc là năm

Nhập sai các bạn ạ!

-     Ví dụ 2: Dùng switch để xác định số lớn và số bé trong hai số a,b.

#include  <stdio.h>

#include  <conio.h>

main()

{

float a, b, min, max;

printf(“Nhập hai số cách nhau khoảng trống: ”);

scanf(“%f %f”, &a, &b);

switch (a<b)

{

case 0 : min = b; max = a; break;

case 1 : min = a; max = b; break;

}

printf(“số bé = %f, số lớn = %f”, min, max);

getch();

}

Lưu ý rằng, trong ví dụ này, nếu bỏ break ở case 0 thì khi a>=b kết quả sẽ sai!

-     Ví dụ 3: Dùng switch để xếp loại một sinh viên theo điểm thi (nguyên): Từ 0 đến 3 xếp loại kém, 4 là loại yếu, 6 đến 7 là loại trung bình, 8 là loại khá, 9 đến 10 là loại giỏi.

       /* Ví dụ có nhiều case chung một nhóm lệnh*/

#include  <stdio.h>

#include  <conio.h>

main()

{

char ho_ten[30];

int diem;

printf(“Vào họ tên: ”);    gets(&ho_ten);

printf(“Vào điểm thi: ”); scanf(“%d”, &diem);

clrscr();

switch (diem)

{

case 0:

case 1:

case 2:

case 3: printf(“

Thí sinh %s xếp loại kém”,ho_ten);

            break;

case 4: printf(“

Thí sinh %s xếp loại yếu”,ho_ten);

            break;

case 5:

case 6: printf(“

Thí sinh %s xếp loại trung bình”,ho_ten);

            break;

case 7:

case 8: printf(“

Thí sinh %s xếp loại khá”,ho_ten);

            break;

case 9:

case 10: printf(“

Thí sinh %s xếp loại giỏi”,ho_ten);

            break;

default : printf(“Bạn nhập sai điểm!”;

}

printf(“--------------------------------------”;

getch();

}

2.5.3. Lệnh chu trình

Chu trình (còn gọi là vòng lặp) là một đoạn chương trình được thực hiện lặp đi lặp lại nhiều lần. Số lần thực hiện chu trình gọi là số lần lặp. Nếu trước khi thực hiện chu trình, có thể xác định được số lần lặp thì chu trình đó được gọi là chu trình có số lần lặp biết trước; ngược lại (không thể xác định được số lần lặp trước khi thực hiện, chỉ xác định được sau khi đã thực hiện xong chu trình) thì gọi chu trình đó là chu trình có số lần lặp không biết trước.

Thông thường, một chu trình sẽ được thực hiện khi thoả mãn một điều kiện nào đó, khi không thoả mãn điều kiện đó nữa thì sẽ chuyển đến lệnh tiếp theo đứng sau chu trình đó, người ta gọi là thoát khỏi chu trình. Vì thế, để tránh tình trạng tạo thành một chu trình lẩn quẩn, trong thân chu trình thường có những yếu tố để làm thay đổi điều kiện thực hiện chu trình. Trong nhiều trường hợp, có thể xảy ra việc thoát khỏi chu trình ngay cả khi điều kiện thực hiện chu trình vẫn thoả mãn, gọi là thoát khỏi chu trình không bình thường.

Trong C, ba lệnh: for, while và do while được giới thiệu dưới đây dùng để tổ chức các chu trình.

2.5.3.1. Lệnh for

·  Công dụng: Để tổ chức một chu trình có số lần lặp biết trước trong trường hợp cần kiểm tra điều kiện trước rồi mới thực hiện chu trình.

·  Cú pháp:

for ( [biểu thức 1]; [biểu thức 2]; [biểu thức 3] )

       [Nhóm lệnh;]

Trong đó:

-      for là từ khoá

-      Các biểu thức 1, 2, 3 là các biểu thức bất kì và đều có thể có hoặc không có nhưng vẫn phải có dấu ngăn cách là ; , ví dụ: for (i=1 ; ++i<n ; ) và phải đặt trong cặp ( ).

 Thông thường: Biểu thức 1 là một phép gán (biểu thức gán) để tạo giá trị ban đầu cho biến điều khiển chu trình (biến chu trình); Biểu thức 2 là một biểu thức logic thể hiện điều kiện tiếp tục vòng lặp; Biểu thức 3 là một phép gán để thay đổi giá trị của biến chu trình. Trường hợp thường dùng, lệnh for có dạng:

for ([khởi tạo] ; [điều kiện] ; [thay đổi điều kiện] )

      [nhóm lệnh;]

-      Nhóm lệnh là thân chu trình, gồm các lệnh C bất kì, nếu có nhiều lệnh phải đặt trong cấu trúc khối lệnh. Nhóm lệnh có thể có hoặc không có (rỗng) nhưng thường là có.

·  Tác động:

Lệnh for thực hiện theo các bước sau đây:

-      Bước 1: Tính giá trị biểu thức 1 (nếu có)

-      Bước 2: Tính giá trị biểu thức 2 (nếu không có biểu thức 2 thì coi biểu thức 2 luôn nhận giá trị đúng)

-      Bước 3: Kiểm tra giá trị biểu thức 2

  Nếu biểu thức 2 khác 0 (đúng): thực hiện nhóm lệnh (thân chu trình) rồi sang bước 4.

  Nếu biểu thức 2 bằng 0 (sai): thoát khỏi chu trình.

-      Bước 4: Tính giá trị biểu thức 3 (nếu có) rồi quay lại bước 2 để tiếp tục lặp lại quá trình trên.

·  Một số chú ý khi sử dụng for:

Ø  Thân chu trình có thể chứa bất kì một lệnh nào của C, nếu nó chứa các lệnh có cấu trúc (khối lệnh, lệnh rẽ nhánh, lệnh chu trình) thì các lệnh này phải nằm trọn trong thân chu trình (lồng nhau, bao hàm nhau).

Ø  Nếu trong thân chu trình chứa lệnh break; thì khi gặp break;, sẽ thoát khỏi chu trình; Nếu có nhiều chu trình lồng nhau, break; sẽ thoát khỏi chu trình mức sâu nhất chứa nó.

Ø  Nếu trong thân chu trình chứa lệnh continue; thì khi gặp continue; sẽ bỏ qua các lệnh đứng sau continue; để chuyển sang bước 4.

Ø  Khi trong thân chu trình gặp các lệnh break;, goto hay return, sẽ thoát khỏi chu trình. Đây là trường hợp thoát không bình thường.

Ø  Lệnh goto có thể nhảy từ trong thân chu trình ra ngoài chu trình nhưng nhảy từ ngoài vào trong là sai.

Ø  Một trong ba biểu thức của for, có thể viết bằng một dãy biểu thức cách nhau dấu phảy (,). Khi tính toán giá trị biểu thức sẽ tiến hành tính từng biểu thức trong dãy, từ trái qua phải; Riêng biểu thức 2 sẽ nhận giá trị của biểu thức bên phải nhất của dãy.

Nhận xét: Lệnh for trong C không dựa trên nền là một bộ đếm như trong Pascal hay Foxpro, vì thế nó rất linh hoạt nhưng quy định hết sức chặt chẽ!

·  Ví dụ:

-      Ví dụ 1: Chương trình tính p = n!

Thuật toán:

+ Xác định số n

+ cho p ban đầu nhận giá trị 1

+ Nhân p với các số i với i chạy từ 1 tới n

+ Xác định kết quả.

Chương trình:

#include  <stdio.h>

#include  <conio.h>

main( )

{

int i, n;

float p;   /* p kiểu thực để nhận được số khá lớn */

clrscr();

printf(“

Vào số nguyên n = );

scanf(“%d”, &n);

p=1;

for  ( i = 1 ; i<=n ; ++i )  p = p*i;

printf(“

P = %d!  = %.0f”, n, f);

getch();

}

Lệnh for trên có thể thay bằng lệnh:

          for  ( i=1; i<=n; ) {p=p*i; i=i+1;}  /*hoặc */

          for ( p=1, i=1; i<=n; ++i ) p=p*i;

-     Ví dụ 2: Hiển thị lên màn hình hai dãy kí tự:

                        A B C ... X Y Z

                        Z Y X ... C B A

# include  <stdio.h>

# include  <conio.h>

main( )

{

clrscr();

for  ( i = 65 ; i  <= 90 ; i = i +1) printf(“%c ”, i);

printf(“

”);   /* để xuống dòng */

for  ( i = 90 ; i  >= 65 ; i = i -1) printf(“%c ”, i);

getch();

}

Chương trình trên có thể viết lại như sau:

# include  <stdio.h>

# include  <conio.h>

main( )

{

char i;

clrscr();

for  ( i = ‘A’ ; i  <= ‘Z’ ; i++) printf(“%c ”, i);

printf(“

”);   /* để xuống dòng */

for  ( i = ‘Z’; i  >= ‘A’ ; i --) printf(“%c ”, i);

getch();

}

-      Ví dụ 3: Tính trung bình cộng của dãy số a1, a2, ... a n.

Thuật toán:

+ Xác định số lượng phần tử của dãy ( n = ?)

+ Cho tổng ban đầu của dãy = 0

+ Nhập từng số hạng ai  (i=1à n) và cộng tích luỹ vào tổng

+ Tính giá trị trung bình

+ Xác định kết quả

Chương trình:

# include  <stdio.h>

# include  <conio.h>

main()

{

int n, i;

float a, tbc, tong=0;

printf(“Số phần tử của dãy n = ? ”;

scanf(“%d”, &n);

for (i=1; i<=n; ++i)

{

printf(“

Cho biết a%d = ”, i);

scanf(“%f ”, &a);

tong + = a;               /* thay cho viết tong=tong+a */

}

tbc = tong/n;

clrscr();

printf(“

TRUNG BINH CONG CUA DAY = %f”, tbc);

getch();

}

2.5.3.2. Các lệnh break , continue & goto

Ba lệnh break, continue và goto, mặc dù không thuộc nhóm các lệnh điều kiện, cũng không phải là lệnh chu trình nhưng nó lại làm mất tính tuyến tính của chương trình. Vì thế, ta có thể xếp các lệnh này thuộc vào các lệnh có cấu trúc để rẽ nhánh vô điều kiện.

a. Lệnh break

·  Công dụng: Lệnh break dùng để thoát khỏi chu trình của lệnh for, lệnh while, lệnh do while và cấu trúc switch ... case.

·  Cú pháp:   break;

·  Tác động:

break chỉ có thể có mặt trong các lệnh chu trình và lệnh switch. Khi thực hiện chương trình, lệnh break được thực hiện như sau:

- Nếu break nằm trong thân chu trình của các lệnh for, while, do while thì sẽ thoát khỏi chu trình đó. Nói cách khác là, break sẽ bỏ qua các lệnh sau nó trong thân chu trình để thoát khỏi chu trình, bất kể điều kiện thực hiện chu trình có thoả mãn hay không. Nếu có các chu trình lồng nhau, break sẽ thoát khỏi chu trình trong nhất chứa nó.

- Nếu break nằm trong các case của switch thì sẽ thoát khỏi lệnh switch đó, bỏ qua các lệnh sau nó trong mỗi case. Nếu có các switch lồng nhau, break sẽ thoát khỏi switch trong cùng chứa nó.

·  Ví dụ:

-        Ví dụ 1: Xem lại ví dụ 1 của lệnh swith trong phần 2.5.2.2. dùng break để thoát khỏi switch

-        Ví dụ 2: Xác định xem một số tự nhiên vào từ bàn phím có là số nguyên tố hay không?

   Thuật toán

      + Nhập n

      + Tổ chức một chu trình để kiểm tra: “ n có chia hết cho  các số i hay không” (i chạy từ 2 đến sqrt(n)). Nếu tồn tại một phép chia hết đầu tiên thì xác định n không phải là số nguyên tố và thoát ngay ra khỏi chu trình, ngược lại, nếu không tồn tại phép chia hết nào thì xác định n là số nguyên tố.

Chương trình:

# include  <stdio.h>

# include  <conio.h>

# include  <math.h>

main( )

{

long i, n;

char *ket_qua = “là số Nguyên tố”;

 /* tạm chấp nhận biến ket_qua là kiểu xâu */

clrscr();

printf(“Vào số tự nhiên n = ”; scanf(“%ld”, &n);

for (i=2; i<=sqrt(n); i++)

      if ( n%i == 0)

          {

          ket_qua = “không là số Nguyên tố”;

          break;

          }

printf(“

%ld %s”, n, ket_qua);

getch();

}

Nhận xét: Khi gặp phép chia hết đầu tiên của n/i (phần dư =0) thì break; sẽ thoát khỏi chu trình ngay trong khi i vẫn bé thua sqrt(n) - điều kiện thực hiện chu trình vẫn thoả mãn. Đây là trường hợp thoát khỏi chu trình không bình thường.

b- Lệnh continue

·  Công dụng: Lệnh continue chỉ có thể có mặt trong một chu trình, dùng để bỏ dở việc thực hiện thân chu trình và bắt đầu một vòng lặp mới chứa nó.

·  Cú pháp: 

                    continue;

·   Tác động: Khi gặp continue;, máy sẽ bỏ qua các lệnh còn tại trong thân chu trình, trở về đầu vòng lặp để tiếp tục thực hiện lệnh chu trình. Cụ thể như sau:

- Nếu continue; trong lệnh for, nó sẽ tính lại biểu thức 3 rồi kiểm tra biểu thức 2 để quyết định việc lặp.

- Nếu continue; nằm trong while hay do while, máy sẽ xác định lại giá trị biểu thức rồi kiểm tra điều kiện để kết thúc chu trình.

·   Ví dụ: Đưa ra các số nguyên tố nằm trong [1, 1000]

Thuật toán:

Bước 1: Cho n=1

Bước 2: Kiểm tra nếu n <=1000 thì sang bước 3, ngược lại thì kết thúc

Bước 3: Kiểm tra nếu n có giá trị từ 3 trở lên và là số chẵn thì sang bước 5

Bước 4: Kiểm tra n có là nguyên tố không, nếu có thì hiển thị rồi sang bước 5, nếu không thì  sang bước 5

Bước 5: Tăng n một đơn vị rồi trở về bước 2.

Chương trình:

# include  <stdio.h>

# include  <conio.h>

# include  <math.h>

main( )

{

int i, n, ra=1;

/* biến ra để quyết định có hiển thị n hay không?

    Nếu ra=1 thì hiển thị, nếu ra=0 thì không hiển thị n */

clrscr();

for  (n =1; n<=1000; ++n)

{

if  (n>2 && n%2= =0)

    continue;

/* Không cần kiểm tra các số chẵn lớn hơn 2

    có là số nguyên tố không! */

for (i=2; i<=sqrt(n); i++)

      if ( n%i == 0)

        {ra=0; break;}

               if (ra)  printf(“

%d ”, n);

               ra = 1;

               }

getch();

}

c- Lệnh goto

·    Công dụng: Lệnh goto dùng để chuyển vô điều kiện đến thực hiện một lệnh bất kì trong chương trình.

·    Cú pháp:

           goto <nhãn>;

Trong đó:

- goto là từ khoá;

- Nhãn là một tên hợp lệ do người lập trình đặt để làm mốc đánh dấu một lệnh cần chuyển đến của lệnh goto. Cách viết nhãn lệnh như sau:

nhãn: lệnh;

·      Tác động: Gặp lệnh goto, máy chuyển ngay đễn thực hiện lệnh được viết sau nhãn

·       Chú ý:

Ø  Đối với các lệnh chu trình và lệnh switch, chỉ có thể viết goto nhảy từ trong thân chu trình hay thân switch ra ngoài, việc chuyển ngược từ ngoài vào trong là sai nguyên tắc.

Ø  Có thể nhảy từ trong khối lệnh ra ngoài khối lệnh nhưng không được nhảy từ ngoài khối lệnh vào trong khối lệnh.

Ø  Nếu goto nằm trong hàm nào, nó chỉ có thể nhảy từ vị trí này tới vị trí khác trong hàm đó, không được nhảy từ hàm này sang hàm khác.

Ø  Có thể sử dụng lệnh goto kết hợp với lệnh if để tổ chức một chu trình. Tuy nhiên, không nên làm như vậy vì nó làm mất tính cấu trúc mạch lạc của chương trình.

·  Ví dụ: có thể viết chương trình tính tổng của n số (n>1) vào từ bàn phím như sau:

#include  <stdio.h>

#include  <conio.h>

main( )

{

int i, n;

float a, tong;

clrscr();

printf(“ Số phần tử n =); scanf(“ %d”, &n);

tong=0; i=1;

Lap: printf(“

a%d =”,i); scanf(“%f”, &a);

tong = tong +a;

++i;

if  (i<=n) goto Lap;

printf(“

Tổng %d số vừa nhập = %f”, n, tong);

getch();

}

2.5.3.3. Lệnh while

·  Công dụng: Lệnh while dùng để tổ chức một chu trình bất kì (cả chu trình có số lần lặp biết trước và không biết trước). Tuy nhiên, nếu chu trình có số lần lặp biết trước thì khi tổ chức viết chương trình, nên dùng lệnh for cho gọn. Cũng tương tự như for, lệnh while chỉ sử dụng trong trường hợp kiểm tra điều kiện trước rồi mới thực hiện chu trình.

·  Cú pháp:

while (biểu thức)

           [nhóm lệnh;]

Trong đó:

-   while là từ khoá;

-   Biểu thức là một biếu thức bất kì dặt trong cặp dấu ( ), thường là biểu thức logic, để thể hiện điều kiện thực hiện chu trình. Biểu thức có thể viết thành một dãy biểu thức cách nhau dấu phảy – Khi đó, giá trị biểu thức được xác định là giá trị của biểu thức viết sau cùng;

-   Nhóm lệnh gồm một tập hợp các lệnh C bất kì, nếu có nhiều lệnh thì bắt buộc phải viết trong cấu trúc khối lệnh. Nhóm lệnh tạo thành thân chu trình. Thân chu trình có thể rỗng (không chứa lệnh nào, tương tự như lệnh for).

·  Tác động:

Phỏng dịch, câu lệnh này có nghĩa là: Thực hiện lặp đi lặp lại nhóm lệnh chừng nào mà biểu thức còn nhận giá trị đúng. Cụ thể, lệnh while được thực hiện như sau:

Khi gặp while, máy sẽ tính giá trị biểu thức rồi kiểm tra giá trị biểu thức:

-  Nếu biểu thức khác 0 (đúng) thì thực hiện nhóm lệnh rồi lại trở về while để lặp lại quá trình trên.

- Nếu biểu = 0 (sai) thì thoát khỏi chu trình để thực hiện tiếp lệnh đứng ngay sau while

·  Chú ý: - Giống như các 1, 2, 3, 4, 5 của lệnh for.

        - Thân chu trình có thể không được thực hiện lần nào.

·  Ví dụ:

- Ví dụ 1: Tính p = n!

# include  <stdio.h>

main()

{

int i=1, n; long p =1;

printf(“Vào n= ”); scanf(“%ld ”, &n);

while  (i<=n)

  {p=p*i; i=i+1;}

printf(“%d! =%ld ”, p);

getch();

}

- Ví dụ 2: Hiển thị lên màn hình số chữ số có nghĩa của một số nguyên nhập từ bàn phím. Ví dụ: 1234567 là số có 7 chữ số.

chương trình:

# include  <stdio.h>

main()

{

long n; int i=0;

printf(“Vào một số nguyên”); scanf(“%ld”, &n);

if (n==0) i =1;

while (n!=0)

{

n = n/10;

i = i+1;

}

printf(“Số vừa nhập có %d chữ số”, i);

getch();

}

- Ví dụ 3: Số tự nhiên e được tính xấp xỉ theo công thức:

                            1       1                  

            e = 1 +  ---- + ---- + ...                                                                                                                    1!      2!                                                             

Tiêu chuẩn dừng là: 1/i! <0.000001

Chương trình:

# include  <stdio.h>

# include  <conio.h>

# include  <math.h>

main()

{

int i =1;

float e=1, mau=1;

while  ( 1/mau >= 0.000001)

{

mau=mau*i;

++i;

e = e +1/mau;

}

printf(“Số tự nhiên e = %10.6f”, e);

getch();

}

2.5.3.4. Lệnh do ..while

·  Công dụng: Lệnh do ... while dùng để tổ chức chu trình bất kì (cả số lần lặp biết trước và không biết trước) nhưng chỉ được sử dụng trong trường hợp thực hiện chu trình trước rồi mới kiểm tra điều kiện kết thúc chu trình.

·  cú pháp:

do

 [ nhóm lệnh ;]

while (biểu thức);

Trong đó:

-        do và  while là từ khoá;

-       Nhóm  lệnh nằm sau do đến trước while là một tập hợp các lệnh bất kì của C, có thể có hoặc không (rỗng), tạo thành thân chu trình; Nếu có nhiều lệnh hoặc rỗng phải đặt trong cấu trúc khối lệnh; Nếu chứa các lệnh có cấu trúc thì chúng phải nằm trọn trong thân chu trình.

-       Biểu thức là một biểu thức bất kì (thường là biểu thức logic) đặt trong cặp dấu ( ) để xác định điều kiện kết thúc chu trình.

·   Tác động: Khi gặp do ... while, máy tiến hành thực hiện nhóm lệnh, sau đó kiểm tra giá trị biểu thức. Nếu biểu thức khác 0 (đúng) thì quay trở lại thực hiện nhóm lệnh và lặp lại quá trình trên; Nếu biểu thức bằng 0 (sai) thì thoát khỏi chu trình.

·    Chú ý- Giống như các chú ý 1, 2, 3, 4, 5 trong lệnh for

- Thân chu trình sẽ được thực hiện ít nhất một lần.

- Có thể viết: while (biểu thức 1, biểu thức 2); . Khi đó, nó tương đương với: do <biểu thức 1> while (biểu thức 2);

·    Ví dụ: Để tính và in các phiếu thu tiền điện cho các hộ sử dụng điện, người ta nhập vào máy các thông tin: Họ tên khách hàng, mã khách hàng, địa chỉ, số công tơ đầu tháng, số công tơ cuối tháng. Các phiếu thu tiền điện có dạng:

   Phiếu thu tiền điện

 Họ tên khách hàng: ...

                 Mã khách hàng:   ....

                 Địa chỉ:  ....

                Số đầu tháng ...    Số cuối tháng ...

                Số điện sử dụng:  .... (kwh)

                Số tiền phải trả:   ....  (đồng)

Biết:  Số điện sử dụng = số cuối tháng – số đầu tháng

         Số tiền = Số điện sử dụng x Đơn giá.

         Đơn giá được tính: Từ 1 đến 100 số, tính đơn giá 500đồng, 50 số tiếp theo tính đơn giá 650 đồng, 50 số tiếp theo tính đơn giá 800 đồng, từ số thứ 201 trở đi tính đơn giá 1000 đồng.

Chương trình:

/* Gọi các tệp tiêu đề */

#include  <stdio.h>

#include  <conio.h>

#include  <ctype.h>

/* Thân chương trình */

main()

{

char  hoten[40], ma_kh[10], diachi[50], kiem_tra;

int  dau, cuoi, so_sd;

long   so_tien;

do

{

/* Phần nhập liệu */

clrscr( );

printf(“Họ tên: ”); gets(hoten);  /* có thể viết gets(&hoten); */

printf(“Mã số KH: ”); gets(ma_kh);

printf(“Địa chỉ: ”); gets(diachi);

printf(“Số đầu tháng: ”); scanf(“%d ”, &dau);

printf(“Số cuối tháng: ”); scanf(“%d ”, &cuoi);

 /* Phần tính toán */

so_sd = cuoi – dau;

if  (so_sd <=100)

   so_tien = so_sd *500;

if  (so_sd >100 && so_sd<=150)

   so_tien = 100 *500 + (so_sd – 100)*650;

if  (so_sd >150 && so_sd<=200)

   so_tien = 100 *500 + 50* 650 + (so_sd – 150)*800;

if  (so_sd >200)

   so_tien = 100 *500 + 50*650 + 50*800 + (so_sd – 200)*1000;

 /* Phần in ấn */

fprintf(stdprn, “     Phiếu thu tiền điện

”);

fprintf(stdprn, “ Họ tên KH: %s”, hoten

fprintf(stdprn, “ Mã  KH: %s”, ma_kh

fprintf(stdprn, “ Địa chỉ: %s”, diachi

fprintf(stdprn, “ Số đầu tháng: %d”, dau);

fprintf(stdprn, “ Số cuối tháng: %d

”, cuoi);

fprintf(stdprn, “ Số điện sử dụng: %d (kwh)

”, so_sd);

fprintf(stdprn, “ Số tiền phải trả: %ld (đồng)

”, so_tien);

fprintf(stdprn, “ --------------------------\”);

fprintf(stdprn, “ \n”);

 /* Phần quyết định thoát khỏi chu trình */

printf(“Có tiếp tục in không (C/K) ? ”; kiem_tra = getchar();

if  (toupper(kiem_tra) = ‘K’)

    {clrscr(); printf(“

Chào và hẹn gặp lại”); break;}

}

while (1);

getch();

}

bài tập và Câu hỏi ôn tập chương 2

1.Chỉ ra trình tự xây dựng một chương trình C?

2.Nêu cấu trúc tổng quát của một chương trình C?

3.Khái niệm khối lệnh, sự tương tác giữa các biến trong và ngoài khối lệnh?

4.Các kiểu dữ liệu cơ sở trong C: Cách lưu trữ và phạm vi biểu diễn?

5.Các đại lượng được sử dụng trong C như thế nào?

6.Nêu khái niệm và cách tính giá trị của các loại biểu thức trong C?

7.Cho các khia báo sau:

int  n=1, p=2;

long  q = 3;

float  x = 4.5;

Hãy xác định kiểu và giá trị các biểu thức:

a.       n + p

b.      n + p +1.

c.       ! ( n + p )

d.      n + x

e.       n % p + q

f.        n < p

g.      q + 3 * (n>p)

h.      q && n

i.        (q - 2) && (n-1)

j.        x * (q = =2);

k.      x * ( q = 5)

l.        n < p < q ! = x

8.    Cho khai báo:

int a, p;

double b, c;

Chọn phát biểu đúng:

a.       p = (int) b + (c*=2);

b.      p = a + (1, b = 1);

c.       p = c;

d.      a = “abc”;

9.    Cho khai báo:

char  a, p;

int  b, q;

Hãy chọn phát biểu sai:

a.      q <<=a;

b.     p->>b;

c.      a+=b - (double) 1;

d.     b = (char) a;

10.      Tại sao hàm gets() thích được sử dụng hơn scanf()?

11.      Viết chương trình nhập vào một số hệ 10 rồi hiển thị giá trị của số ở hệ 8 và hệ 16.

12.      Viết chương trình tìm số lớn nhất trong 3 số nhập từ bàn phím (cách 1 có sử dụng if và cách 2 sử dụng biểu thức điều kiện)

13.      Viết chương trình nhập một kí tự từ bàn phím rồi thông báo lên màn hình kí tự đó là số, chữ cái hay kí hiệu đặc biệt.

14.      Viết chương trình có một thực đơn chọn công việc để tính chu vi và diện tích một số hình sơ cấp:

a.     Hình vuông;

b.    Hình chữ nhật;

c.     Hình tam giác;

d.    Hình thang;

e.     Hình tròn.

15.      Viết chương trình giải phương trình bậc nhất   ax + b = 0

16.      Viết chương trình giải hệ phương trình bậc nhất: 

{

a1x + b1y = c1

a2x + b2y = c2

17.      Viết chương trình tìm các số nguyên tố trong khoảng [n1,n2] .

18.      Viết chương trình tìm ước số chung lớn nhất của hai số.

19.      Viết chương trình tìm bội số chung nhỏ nhất của hai số.

20.      Viết chương trình hiển thị n số của dãy số Fibonacy theo quy luật:

                    F1 = 1

                    F2 = 1

                    Fk = Fk-2 + Fk-1   nếu k>2

21.      Viết chương trình tính xấp xỉ COS(X) theo công thức Taylor:

                               cosx = 1 -  +  -  ...    + (-1)n

22.      Viết chương trình tính xấp xỉ ex theo công thức

                               ex = 1 +  + +   + ...  

            Quá trình lặp sẽ dừng khi kết quả giữa hai lần tính < ồ  cho trước.

23.      Viết chương trình tính và in ra 20 dòng tam giác PASCAL

24.      Viết chương trình tìm tất cả các số có ba chữ số mà tổng lập phương của từng chữ số có giá trị bằng chính số đó. Nghĩa là:

                    abc = 100a + 10b + c = a3 + b3 + c3

25.      Viết chương trình in ra bảng mã ASCII như phần phụ lục 1.

26.      Viết chương trình tính xấp xỉ căn bậc hai của số t dương theo công thức lặp:                 xn  =  ( t / xn-1 +xn-1 )/2

Giá trị xấp xỉ ban đầu là số dương x cho từ bàn phím. Tiêu chuẩn dừng của quá trình lặp là : | xn - xn-1 | < 10-6

27.      Một người gửi A đồng vào quỹ tiết kiệm loại không kì hạn với lãi suất 0,35% mỗi tháng. Viết chương trình xác định khoảng thời gian gửi (số tháng) để có tổng cộng là B đồng.

Bạn đang đọc truyện trên: Truyen2U.Pro