Giáo trình Lập trình cơ bản C - Bài 6: Nhập và xuất trong C

Bài 6  
Nhập Xuất trong C  
Mục tiêu:  
Kết thúc bài học này, bạn thể:  
Hiểu các hàm nhập xuất định dạng scanf() và printf()  
Sử dụng các hàm nhập xuất tự getchar() và putchar().  
Giới thiệu  
Trong bất kỳ ngôn ngữ lập trình nào, việc nhập giá trị cho các biến và in chúng ra sau khi xử lý có thể  
được làm theo hai cách:  
1. Thông qua phương tiện nhập/xuất chuẩn (I / O).  
2. Thông qua những tập tin.  
Trong phần này ta sẽ nói về chức năng nhập xuất cơ bản. Nhập xuất (I/O) luôn là các thành phần  
quan trọng của bất kỳ chương trình nào. Ðể tạo tính hữu ích, chương trình của bạn cần khả năng  
nhập dữ liệu vào và hiển thị lại những kết quả của nó.  
Trong C, thư viện chuẩn cung cấp những thủ tục cho việc nhập xuất. Thư viện chuẩn những hàm  
quản lý các thao tác nhập/xuất cũng như các thao tác trên ký tự chuỗi. Trong bài học này, tất cả  
những hàm nhập dùng để đọc dữ liệu vào từ thiết bị nhập chuẩn tất cả những hàm xuất dùng để viết  
kết quả ra thiết bị xuất chuẩn. Thiết bị nhập chuẩn thông thường là bàn phím. Thiết bị xuất chuẩn  
thông thường là màn hình (console). Nhập xuất ra có thể được định hướng đến tập tin hay từ tập tin  
thay vì thiết bị chuẩn. Những tập tin có thể được lưu trên đĩa hay trên bất cứ thiết bị lưu trữ nào khác.  
Dữ liệu đầu ra cũng thể được gửi đến máy in.  
6.1 Tập tin tiêu đề <stdio.h>  
Trong các ví dụ trước, ta đã từng viết dòng mã sau:  
#include <stdio.h>  
Ðây là lệnh tiền xử lý (preprocessor command). Trong C chuẩn, hiệu # nên đặt tại cột đầu  
tiên. stdio.h một tập tin và được gọi tập tin tiêu đề (header). chứa các macro cho nhiều  
hàm nhập xuất được dùng trong C. Hàm printf(), scanf(), putchar() getchar() được thiết kế theo  
cách gọi các macro trong tập tin stdio.h để thực thi các công việc tương ứng.  
6.2 Nhập xuất trong C (Input and Output)  
Thư viện chuẩn trong C cung cấp hai hàm để thực hiện các yêu cầu nhập xuất định dạng. Chúng  
là:  
printf() Hàm xuất định dạng.  
scanf() Hàm nhập định dạng.  
Những hàm này gọi những hàm được định dạng vì chúng có thể đọc và in dữ liệu ra theo các định  
dạng khác nhau được điều khiển bởi người dùng. Bộ định dạng qui định dạng thức mà theo đó giá  
trị của biến sẽ được nhập vào và in ra.  
Nhập Xuất trong C  
71  
6.2.1 printf()  
Chúng ta đã quen thuộc với hàm này qua các phần trước. Ở đây, chúng ta sẽ xem chúng chi tiết hơn.  
Hàm printf() được dùng để hiển thị dữ liệu trên thiết bị xuất chuẩn – console (màn hình). Dạng mẫu  
chung của hàm này như sau:  
printf(“control string”, argument list);  
Danh sách tham số (argument list) bao gồm các hằng, biến, biểu thức hay hàm và được phân cách bởi  
dấu phẩy. Cần phải một lệnh định dạng nằm trong chuỗi điều khiển (control string) cho mỗi  
tham số trong danh sách. Những lệnh định dạng phải tương ứng với danh sách các tham số về số  
lượng, kiểu dữ liệu thứ tự. Chuỗi điều khiển phải luôn được đặt bên trong cặp dấu nháy kép“”, đây  
dấu phân cách (delimiters). Chuỗi điều khiển chứa một hay nhiều hơn ba thành phần dưới đây :  
tự văn bản (Text characters) – Bao gồm các ký tự thể in ra được sẽ được in giống như  
ta nhìn thấy. Các khoảng trắng thường được dùng trong việc phân chia các trường (field) được  
xuất ra.  
Lệnh định dạng - Định nghĩa cách thức các mục dữ liệu trong danh sách tham số sẽ được hiển  
thị. Một lệnh định dạng bắt đầu với một hiệu % và theo sau một định dạng tương ứng cho  
mục dữ liệu. Dấu % được dùng trong hàm printf() để chỉ ra các đặc tả chuyển đổi. Các lệnh định  
dạng và các mục dữ liệu tương thích nhau theo thứ tự kiểu từ trái sang phải. Một định dạng  
thì cần thiết cho mọi mục dữ liệu cần in ra.  
Các ký tự không in được – Bao gồm phím tab, dấu khoảng trắng dấu xuống dòng.  
Mỗi lệnh định dạng gồm một hay nhiều định dạng. Một định dạng bao gồm hiệu % một  
bộ định kiểu. Bảng 6.1 liệt kê các mã định dạng khác nhau được hỗ trợ bởi câu lệnh printf():  
Ðịnh dạng  
printf() scanf()  
tự đơn (Single Character)  
Chuỗi (String)  
Số nguyên có dấu (Signed decimal integer)  
Số thập phân có dấu chấm động (Floating point)  
Số thập phân có dấu chấm động - Biểu diễn phần thập phân  
Số thập phân có dấu chấm động - Biểu diễn dạng số mũ  
Số thập phân có dấu chấm động (%f hoặc %e, con số nào ít hơn)  
Số nguyên không dấu (Unsigned decimal integer)  
Số thập lục phân không dấu (Dùng “ABCDEF”)  
(Unsigned hexadecimal integer)  
%c  
%s  
%d  
%f  
%lf  
%e  
%g  
%u  
%x  
%c  
%s  
%d  
%f hoặc %e  
%lf  
%f hoặc %e  
%u  
%x  
Số bát phân không dấu (Unsigned octal integer)  
%o  
%o  
Bảng 6.1: Mã định dạng trong printf ()  
Trong bảng trên, c, d, f, lf, e, g, u, s, o x bộ định kiểu.  
Các quy ước in cho các mã định dạng khác nhau được tổng kết trong Bảng 6.2:  
định dạng  
Quy ước in ấn  
%d  
Các con số trong số nguyên.  
72  
Lập trình cơ bản C  
%f  
%e  
Phần số nguyên của số sẽ được in nguyên dạng. Phần thập phân sẽ chứa 6  
con số. Nếu phần thập phân của con số ít hơn 6 số, sẽ được thêm các số  
không (0) bên phải hay gọi là làm tròn phía bên phải.  
Một con số bên trái dấu chấm thập phân và 6 con số bên phải giống như %f.  
Bảng 6.2: Quy ước in  
Bởi vì các ký hiệu %,\ và được dùng đặc biệt trong chuỗi điều khiển, nếu chúng ta cần in các ký hiệu  
này lên màn hình, chúng phải được dùng như trong Bảng 6.3:  
\\  
In ký tự \  
\ “  
%%  
In ký tự “  
In ký tự %  
Bảng 6.3: Các ký tự đặc biệt trong chuỗi điều khiển  
Bảng dưới đây đưa ra vài ví dụ sử dụng chuỗi điều khiển và mã định dạng khác nhau.  
Chuỗi  
điều  
khiển  
Nội dung mà  
chuỗi điều khiển  
chứa đựng  
Chỉ chứa lệnh 300  
định dạng  
Chỉ chứa lệnh 10 + 5  
định dạng  
Chỉ là các ký tự Không có Không có  
Danh  
sách  
tham số  
Giải thích  
danh sách  
tham số  
Hiển thị trên  
màn hình  
Số  
1.  
Câu lệnh  
printf(“%d”, 300);  
printf(“%d”, 10+5);  
printf(“Good  
%d  
Hằng số  
300  
2.  
%d  
Biểu thức  
15  
3.  
Good  
Good Morning  
Mr. Lee.  
Morning Mr. Lee.”); Morning văn bản  
(Nil)  
Mr. Lee.  
4.  
5.  
int count = 100;  
printf(“%d”, count);  
printf(“\nhello”);  
%d  
Chỉ chứa lệnh Count  
định dạng  
Chỉ là các ký tự Không có Không có  
văn bản và ký tự  
Biến  
100  
\nhello  
Hello  
(Trên dòng mới)  
không in được.  
6.  
7.  
#define str “Good %s  
Apple”  
……..  
Chỉ chứa lệnh Str  
định dạng  
Hằng chuỗi Good Apple  
printf(“%s”, str);  
……..  
%d %d  
Chỉ chứa lệnh count,  
định dạng và trình stud_num  
tự thoát ra  
Hai biến  
0, 100  
int count,stud_num;  
count = 0;  
stud_num = 100;  
printf(“%d  
%d\n”,  
count, stud_num);  
Bảng 6.4 : Chuỗi điều khiển và mã định dạng  
dụ 6.1 :  
Ðây là một chương trình đơn giản dùng minh họa cho một chuỗi thể được in theo lệnh định dạng.  
Chương trình này cũng hiển thị một tự đơn, số nguyên và số thực (a single character, integer, và  
float).  
#include <stdio.h>  
void main()  
Nhập Xuất trong C  
73  
{
int a = 10;  
float b = 24.67892345;  
char ch = ‘A’;  
printf(“\nInteger data = %d”, a);  
printf(“\nFloat Data = %f”, b);  
printf(“\nCharacter = %c”, ch);  
printf(“\nThis prints the string”);  
printf(“%s”, ”\nThis also prints a string”);  
}
Kết quả chương trình như sau:  
Integer data = 10  
Float Data = 24.678923  
Character = A  
This prints the string  
This also prints a string  
Bổ từ (Modifier) cho các lệnh định dạng trong printf()  
Các lệnh định dạng thể bổ từ (modifier), để thay đổi các đặc tả chuyển đổi gốc. Sau đây là các  
bổ từ được chấp nhận trong câu lệnh printf(). Nếu nhiều bổ từ được dùng thì chúng tuân theo trình  
tự sau :  
Bổ từ ‘-‘  
Dữ liệu sẽ được canh trái bên trong không gian dành cho nó, chúng sẽ được in bắt đầu từ vị trí ngoài  
cùng bên trái.  
Bổ từ xác định độ rộng  
Chúng có thể được dùng với kiểu: float, double hay char array (chuỗi-string). Bổ từ xác định độ rộng  
một số nguyên xác định độ rộng nhỏ nhất của trường dữ liệu. Các dữ liệu độ rộng nhỏ hơn sẽ cho  
kết quả canh phải trong trường dữ liệu. Các dữ liệu có kích thước lớn hơn sẽ được in bằng cách dùng  
thêm những vtrí cho đủ yêu cầu.Ví dụ, %10f lệnh định dạng cho các mục dữ liệu kiểu số thực với  
độ rộng trường dữ liệu thấp nhất là 10.  
Bổ từ xác định độ chính xác  
Chúng có thể được dùng với kiểu float, double hay mảng tự (char array, string). Bổ từ xác định độ  
rộng chính xác được viết dưới dạng .m với m một số nguyên. Nếu sử dụng với kiểu float double,  
chuỗi số chỉ ra số con số tối đa thể được in ra phía bên phải dấu chấm thập phân.  
Nếu phần phân số của các mục dữ liệu kiểu float hay double vượt quá độ rộng con số chỉ trong bổ  
từ, thì số đó sẽ được làm tròn. Nếu chiều dài chuỗi vượt quá chiều dài chỉ định thì chuỗi sẽ được cắt  
bỏ phần dư ra phía cuối. Một vài số không (0) sẽ được thêm vào nếu số con số thực sự trong một  
mục dữ liệu ít hơn được chỉ định trong bổ từ. Tương tự, các khoảng trắng sẽ được thêm vào cho chuỗi  
tự. dụ, %10.3f là lệnh định dạng cho mục dữ liệu kiểu float, với độ rộng tối thiểu cho trường dữ  
liệu là 10 và 3 vị trí sau phần thập phân.  
74  
Lập trình cơ bản C  
Bổ từ ‘0’  
Theo mặc định, việc thêm vào một trường được thực hiện với các khoảng trắng. Nếu người dùng  
muốn thêm vào trường với số không (0), bổ từ này phải được dùng.  
Bổ từ ‘l’  
Bổ từ này có thể được dùng để hiển thị số nguyên như: long int hay một tham số kiểu double. Mã định  
dạng tương ứng cho nó là %ld.  
Bổ từ ‘h’  
Bổ từ này được dùng để hiện thị kiểu short integer. Mã định dạng tương ứng cho nó là %hd.  
Bổ từ ‘*’  
Bổ từ này được dùng khi người dùng không muốn chỉ trước độ rộng của trường muốn chương  
trình xác định nó. Nhưng khi đi với bổ từ này, một tham số được yêu cầu phải chỉ ra độ rộng trường cụ  
thể.  
Chúng ta hãy xem những bổ từ này hoạt động thế nào. Ðầu tiên, chúng ta xem xét tác động của đối  
với những dữ liệu kiểu số nguyên.  
dụ 6.2:  
/* Chương trình này trình bày cách dùng bổ từ trong printf() */  
#include <stdio.h>  
void main()  
{
printf(“The number 555 in various forms:\n”);  
printf(“Without any modifier: \n”);  
printf(“[%d]\n”, 555);  
printf(“With - modifier:\n”);  
printf(“[%-d]\n”, 555);  
printf(“With digit string 10 as modifier:\n”);  
printf(“[%10d]\n”, 555);  
printf(“With 0 as modifier: \n”);  
printf(“[%0d]\n”, 555);  
printf(“With 0 and digit string 10 as modifiers:\n”);  
printf(“[%010d]\n”, 555);  
printf(“With -, 0 and digit string 10 as modifiers:\n”);  
printf(“[%-010d]\n”, 555);  
}
Kết quả như dưới đây:  
The number 555 in various forms:  
Nhập Xuất trong C  
75  
Without any modifier:  
[555]  
With - modifier:  
[555]  
With digit string 10 as modifier:  
[
555]  
With 0 as modifier:  
[555]  
With 0 and digit string 10 as modifiers:  
[0000000555]  
With -, 0 and digit string 10 as modifiers:  
[555  
]
Chúng ta đã dùng ký hiệu [‘ và ‘]’ để chỉ ra nơi trường bắt đầu nơi kết thúc. Khi chúng ta dùng  
%d mà không có bổ từ, chúng ta thấy rằng nó dùng cho một trường có cùng độ rộng với số nguyên.  
Khi dùng %10d chúng ta thấy rằng nó dùng 10 khoảng trắng cho trường số được canh lề phải theo  
mặc định. Nếu ta dùng bổ t –, số sẽ được canh trái trong trường đó. Nếu dùng bổ từ 0, chúng ta thấy  
rằng số sẽ thêm vào 0 thay vì là khoảng trắng.  
Bây giờ chúng ta hãy xem bổ từ dùng với số thực.  
dụ 6.3:  
/* Chương trình này trình bày cách dùng bổ từ trong printf() */  
#include <stdio.h>  
void main()  
{
printf(“The number 555.55 in various forms:\n”);  
printf(“In float form without modifiers:\n”);  
printf(“[%f]\n”, 555.55);  
printf(“In exponential form without any modifier:\n”);  
printf(“[%e]\n”, 555.55);  
printf(“In float form with - modifier:\n”);  
printf(“[%-f]\n”, 555.55);  
printf(“In float form with digit string 10.3 as modifier\n”);  
printf(“[%10.3f]\n”, 555.55);  
printf(“In float form with 0 as modifier:\n”);  
printf(“[%0f]\n”, 555.55);  
printf(“In float form with 0 and digit string 10.3”);  
printf(“as modifiers:\n”);  
printf(“[%010.3f]\n”, 555.55);  
printf(“In float form with -, 0 ”);  
76  
Lập trình cơ bản C  
printf(“and digit string 10.3 as modifiers:\n”);  
printf(“[%-010.3f]\n”, 555.55);  
printf(“In exponential form with 0”);  
printf(“ and digit string 10.3 as modifiers:\n”);  
printf(“[%010.3e]\n”, 555.55);  
printf(“In exponential form with -, 0”);  
printf(“ and digit string 10.3 as modifiers:\n”);  
printf(“[%-010.3e]\n\n”, 555.55);  
}
Kết quả như sau:  
The number 555.55 in various forms:  
In float form without modifiers:  
[555.550000]  
In exponential form without any modifier:  
[5.555500e+02]  
In float form with - modifier:  
[555.550000]  
In float form with digit string 10.3 as modifier  
[
555.550]  
In float form with 0 as modifier:  
[555.550000]  
In float form with 0 and digit string 10.3 as modifiers:  
[000555.550]  
In float form with -, 0 and digit string 10.3 as modifiers:  
[555.550  
]
In exponential form with 0 and digit string 10.3 as modifiers:  
[05.555e+02]  
In exponential form with -,0 and digit string 10.3 as modifiers:  
[5.555e+02]  
Theo mặc định cho %f, chúng ta có thể thấy rằng có 6 con số cho phần thập phân và mặc định cho %e  
một con số tại phần nguyên và 6 con số phần bên phải dấu chấm thập phân. Chú ý cách thể hiện 2  
Nhập Xuất trong C  
77  
số cuối cùng trong ví dụ trên, số các con số bên phải dấu chấm thập phân là 3, dẫn đến kết quả không  
được làm tròn.  
Bây giờ, chúng ta hãy xem bổ từ dùng với chuỗi số. Chú ý cách mở rộng trường để chứa toàn bộ  
chuỗi. Hơn nữa, chú ý cách đặc tả đchính xác .4 trong việc giới hạn số tự được in.  
dụ 6.4:  
/* Chương trình trình bày cách dùng bổ từ với chuỗi*/  
#include <stdio.h>  
void main()  
{
printf(“A string in various forms:\n”);  
printf(“Without any format command:\n”);  
printf(“Good day Mr. Lee. \n”);  
printf(“With format command but without any modifier:\n”);  
printf(“[%s]\n”, ”Good day Mr. Lee.”);  
printf(“With digit string 4 as modifier:\n”);  
printf(“[%4s]\n”, ”Good day Mr. Lee.”);  
printf(“With digit string 19 as modifier: \n”);  
printf(“[%19s]\n”, ”Good day Mr. Lee.”);  
printf(“With digit string 23 as modifier: \n”);  
printf(“[%23s]\n”, ”Good day Mr. Lee.”);  
printf(“With digit string 25.4 as modifier: \n”);  
printf(“[%25.4s]\n”, ”Good day Mr.Lee.”);  
printf(“With – and digit string 25.4 as modifiers:\n”);  
printf(“[%-25.4s]\n”, ”Good day Mr.shroff.”);  
}
Kết quả như sau:  
A string in various forms:  
Without any format command:  
Good day Mr. Lee.  
With format command but without any modifier:  
[Good day Mr. Lee.]  
With digit string 4 as modifier:  
[Good day Mr. Lee.]  
78  
Lập trình cơ bản C  
With digit string 19 as modifier:  
Good day Mr. Lee.]  
With digit string 23 as modifier:  
Good day Mr. Lee.]  
With digit string 25.4 as modifier:  
Good]  
With - and digit string 25.4 as modifiers:  
[Good  
[
[
[
]
Những tự ta nhập tại bàn phím không được lưu ở dạng các ký tự. Thật sự chúng lưu theo dạng các  
số dưới dạng ASCII (Bộ chuẩn Mỹ cho việc trao đổi thông tin - American Standard Code  
for Information Interchange). Các giá trị của một biến được thông dịch dưới dạng tự hay một số  
tùy vào kiểu của biến đó. dụ sau mô tả điều này:  
dụ 6.5:  
#include <stdio.h>  
void main()  
{
int a = 80;  
char b= ‘C’;  
printf(“\nThis is the number stored in ‘a’ %d”,a);  
printf(“\nThis is a character interpreted from ‘a’ %c”,a);  
printf(“\nThis is also a character stored in ‘b’ %c”,b);  
printf(“\nHey! The character of ‘b’ is printed as a number!  
%d“, b);  
}
Kết quả như dưới đây:  
This is the number stored in `a’ 80  
This is a character interpreted from `a’ P  
This is also a character stored in `b’ C  
Hey! The character of `b' is printed as a number!67  
Kết quả này mô tả việc dùng các đặc tả định dạng việc thông dịch của mã ASCII. Mặc dù các biến  
a b đã được khai báo là các biến kiểu int char, nhưng chúng đã được in như là ký tự số nhờ  
vào việc dùng các bộ định dạng khác nhau. Ðặc điểm này của C giúp việc xử dữ liệu được linh hoạt.  
Nhập Xuất trong C  
79  
Khi dùng câu lệnh printf() để cho ra một chuỗi dài hơn 80 ký tự trên một dòng, khi xuống dòng ta phải  
ngắt mỗi dòng bởi hiệu \ như được trình bày trong ví dụ dưới đây:  
dụ 6.6:  
/* Chương trình trình bày cách dùng một chuỗi dài các ký tự*/  
#include <stdio.h>  
void main()  
{
printf(“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\aaaa  
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\aaaaaaaa  
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\aaaaaaaaaaaa  
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\aaaaaaaaaaaaaaaa  
aaaaaaaaaaaaa”);  
}
Kết quả như sau:  
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa  
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa  
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa  
aaaaaaaaaaaaa  
Trong ví dụ trên, chuỗi trong câu lệnh printf() có 252 ký tự. Trong khi một dòng văn bản chứa 80 ký  
tự, do đó chuỗi được mở rộng thành 3 hàng trong kết quả như trên.  
6.2.2 scanf()  
Hàm scanf() được sử dụng để nhập dữ liệu. Khuôn dạng chung của hàm scanf() như sau:  
scanf(<Chuỗi các định dạng>, <Danh sách các tham số>);  
Ðịnh dạng được sử dụng bên trong câu lệnh printf() cũng được sử dụng cùng cú pháp trong các câu  
lệnh scanf().  
Những lệnh định dạng, bao gồm bổ tvà danh sách tham số được bàn luận cho printf() thì cũng hợp lệ  
cho scanf(), chúng tuân theo một số điểm khác biệt sau:  
Sự khác nhau trong danh sách tham số giữa printf() và scanf()  
Hàm printf() dùng các tên biến, hằng số, hằng chuỗi và các biểu thức, nhưng scanf() sử dụng những  
con trỏ tới các biến. Một con trỏ tới một biến một mục dữ liệu chứa đựng địa chỉ của nơi biến  
được cất giữ trong bộ nhớ. Những con trỏ sẽ được bàn luận chi tiết ở chương sau. Khi sử dụng scanf()  
cần tuân theo những quy tắc cho danh sách tham số:  
Nếu ta muốn nhập giá trị cho một biến kiểu dữ liệu cơ bản, gõ vào tên biến cùng với ký  
hiệu & trước nó.  
Khi nhập giá trị cho một biến thuộc kiểu dữ liệu dẫn xuất (không phải thuộc bốn kiểu cơ bản  
char, int, float, double), không sử dụng & trước tên biến.  
80  
Lập trình cơ bản C  
Sự khác nhau trong lệnh định dạng giữa printf() và scanf()  
1. Không có tùy chọn %g.  
2. Mã định dạng %f và %e có cùng hiệu qutác động. Chai nhận một hiệu tùy chọn, một chuỗi  
các con số có hay không có dấu chấm thập phân và một trường số mũ tùy chọn.  
Cách thức hoạt động của scanf()  
scanf() sử dụng những tự không được in như tự khoảng trắng, tự phân cách (tab), ký tự  
xuống dòng để quyết định khi nào một trường nhập kết thúc và bắt đầu. sự tương ứng giữa lệnh  
định dạng với những trường trong danh sách tham số theo một thứ tự xác định, bỏ qua những tự  
khoảng trắng bên trong. Do đó, đầu vào có thể được trải ra hơn một dòng, miễn là chúng ta có ít nhất  
một tự phân cách, khoảng trắng hay hàng mới giữa các trường nhập vào. Nó bỏ qua những khoảng  
trắng và ranh giới hàng để thu được dữ liệu.  
dụ 6.7:  
Chương trình sau mô tả việc dùng hàm scanf().  
#include <stdio.h>  
void main()  
{
int a;  
float d;  
char ch, name[40];  
printf(“Please enter the data\n”);  
scanf(“%d %f %c %s”, &a, &d, &ch, name);  
printf(“\nThe values accepted are: %d, %f, %c, %s”, a, d, ch,  
name);  
}
Kết quả như sau:  
Please enter the data  
12 67.9 F MARK  
The values accepted are:12, 67.900002, F, MARK  
Dữ liệu đầu vào có thể là:  
12 67.9  
F MARK  
hoặc như:  
12  
67.9  
F
MARK  
cũng được nhận vào các biến a, d, ch, và name.  
Xem ví dụ khác:  
Nhập Xuất trong C  
81  
dụ 6.8:  
#include <stdio.h>  
void main()  
{
int i;  
float x;  
char c;  
.........  
scanf(“%3d %5f %c”, &i, &x, &c);  
}
Nếu dữ liệu nhập vào là:  
21 10.345 F  
Khi chương trình được thực thi, thì 21 sẽ gán tới i, 10.34 sẽ gán tới x và ký tự 5 sẽ được gán cho c.  
Còn lại đặc tính F sẽ bị bỏ qua.  
Khi ta chỉ một chiều rộng trường bên trong scanf(), thí dụ %10s, rồi sau đó scanf() chỉ thu nhận tối  
đa 10 ký tự hoặc tới tự khoảng trắng đầu tiên (bất cứ tự nào đầu tiên). Ðiều này cũng áp dụng  
cho các kiểu int, float và double.  
dụ dưới đây tả việc sử dụng hàm scanf() để nhập vào một chuỗi gồm những tự viết hoa và  
khoảng trắng. Chuỗi sẽ chiều dài không xác định nhưng bị giới hạn trong 79 tự (thật ra, 80 ký  
tự bao gồm tự trống (null) được thêm vào nơi cuối chuỗi).  
dụ 6.9:  
#include <stdio.h>  
void main()  
{
char line[80]; /* line[80] là một mảng lưu 80 ký tự */  
..........  
scanf(“%[ ABCDEFGHIJKLMNOPQRSTUVWXYZ]”, line);  
..........  
}
Mã khuôn dạng %[] có nghĩa những tự được định nghĩa bên trong [] có thể được chấp nhận như  
những tự chuỗi hợp lệ. Nếu chuỗi BEIJING CITY được nhập vào từ thiết bị nhập chuẩn, khi  
chương trình được thực thi, toàn bộ chuỗi sẽ được gán cho mảng một khi chuỗi chỉ toàn là ký tự viết  
hoa và khoảng trắng. Nếu chuỗi được viết Beijing city, chỉ tự đơn B được gán cho mảng, khi đó  
thì ký tự viết thường đầu tiên (trong trường hợp này là ‘e’) được thông dịch như tự đầu tiên bên  
ngoài chuỗi.  
Ðể chấp nhận bất kỳ tự nào đến khi gặp tự xuống dòng, chúng ta sử dụng định dạng %[^\n],  
điều này ngụ ý rằng chuỗi đó sẽ chấp nhận bất kỳ tự nào trừ “\n” (ký tự xuống dòng). Dấu mũ (^)  
ngụ ý rằng tất cả các ký tự trừ những tự nằm sau dấu mũ đó sẽ được chấp nhận như tự hợp lệ.  
dụ 6.10:  
#include <stdio.h>  
82  
Lập trình cơ bản C  
void main()  
{
char line[80];  
……………..  
scanf(“%[^\n]”, line);  
………..  
}
Khi hàm scanf() được thực thi, một chuỗi chiều dài không xác định (nhưng không quá 79 ký tự) sẽ  
được nhập vào từ thiết bị nhập chuẩn được gán cho mảng. Sẽ không có giới hạn nào trên các ký tự  
của chuỗi, ngoại trừ tất cả chúng chỉ nằm trên một hàng. Ví dụ chuỗi sau:  
All’s well that ends well!  
thể được nhập vào từ bàn phím và được gán cho mảng.  
Bổ từ * cho kết quả khác nhau trong scanf(). Dấu * được dùng để chỉ rằng một trường sẽ được bỏ qua  
luôn hay tạm bỏ qua.  
dụ xét chương trình:  
#include <stdio.h>  
void main()  
{
char item[20];  
int partno;  
float cost;  
.........  
scanf(“%s %*d %f”, item, &partno, &cost);  
.........  
}
Nếu các mục dữ liệu tương ứng là:  
battery 12345 0.05  
thì battery sẽ được gán cho item 0.05 sẽ được gán cho cost nhưng 12345 sẽ không được gán cho  
partno bởi dấu * ngăn chặn việc gán.  
Bất cứ tự khác trong scanf() mà không là mã định dạng trong chuỗi điều khiển phải được nhập vào  
chính xác nếu không sẽ phát sinh lỗi. Ðặc điểm này được dùng để chấp nhận dấu phân cách phẩy (,).  
dụ chuỗi dữ liệu  
10, 15, 17  
lệnh nhập vào  
scanf(“%d, %f, %c”, &intgr, &flt, &ch);  
Chú ý rằng dấu phẩy trong chuỗi chuyển đổi tương ứng dấu phẩy trong chuỗi nhập và vì vậy sẽ có  
chức năng như dấu phân cách.  
Nhập Xuất trong C  
83  
tự khoảng trắng trong chuỗi điều khiển thường được bỏ qua mặc dù nó sẽ phát sinh trở ngại khi  
dùng với định dạng %c. Nếu chúng ta dùng bộ định dạng %cthì một khoảng trắng được xem như là  
một tự hợp lệ.  
Xét đoạn mã sau:  
int x, y;  
char ch;  
scanf(“%2d %c %d”,&x, &ch, &y);  
printf(“%d %d %d\n”,x, ch, y);  
ta nhập vào:  
14 c  
5
14sẽ được gán cho x, ký tự ch nhận tự khoảng trắng (số 32 trong hệ thập phân), do vậy yđược  
gán giá trị của tự ‘c’ tức số 99 trong hệ thập phân.  
Xét đoạn mã sau:  
#include <stdio.h>  
void main()  
{
char c1, c2, c3;  
…………..  
scanf(“%c%c%c”,&c1, &c2, &c3);  
………………..  
}
Nếu dữ liệu nhập vào là:  
a b c  
(với khoảng trắng giữa các ký tự), thì kết quả của phép gán:  
c1 = a,  
c2 = <Khoảng trắng>,  
c3 = b  
Ở đây chúng ta có thể thấy c2 chứa một khoảng trắng chuỗi nhập chứa tự khoảng trắng. Ðể  
bỏ qua các ký tự khoảng trắng này và đọc tự tiếp theo không phải là ký tự khoảng trắng, ta nên  
dùng tập chuyển đổi %1s.  
scanf(“%c%1s%1s”,&c1, &c2, &c3);  
Khi đó kết quả sẽ khác đi với cùng dữ liệu nhập vào như trước kết quả đúng như ý định của ta:  
c1 = a,  
c2 = b,  
c3 = c  
6.3  
Bộ nhớ đệm Nhập Xuất (Buffered I/O)  
84  
Lập trình cơ bản C  
Ngôn ngữ C bản thân nó không định nghĩa các thao tác nhập xuất. Tất cả thao tác nhập xuất  
được thực hiện bởi các hàm sẵn trong thư viện hàm của C. Thư viện hàm C chứa một hệ thống hàm  
riêng mà nó điều khiển các thao tác này. Ðó là:  
Bộ nhớ đệm Nhập Xuất được dùng để đọc viết các ký tự ASCII  
Một vùng đệm nơi lưu trữ tạm thời, nằm trên bộ nhớ máy tính hoặc trên thẻ nhớ của bộ điều khiển  
thiết bị (controller card). Các ký tự nhập vào từ bàn phím được đưa vào bộ nhớ đợi đến khi người  
dùng nhấn phím return hay enter thì chúng sẽ được thu nhận như một khối và cung cấp cho chương  
trình.  
Bộ nhớ đệm nhập xuất thể được phân thành:  
Thiết bị nhập/xuất chuẩn (Console I/O)  
Tập tin đệm nhập/xuất (Buffered File I/O)  
Thiết bị nhập/xuất chuẩn liên quan đến những hoạt động của bàn phím và màn hình của máy tính.  
Tập tin đệm nhập/xuất liên quan đến những hoạt động thực hiện đọc viết dữ liệu vào tập tin.  
Chúng ta sẽ nói về Thiết bị nhập/xuất.  
Trong C, Thiết bị nhập/xuất chuẩn một thiết bị luồng. Các hàm trong Thiết bị nhập/xuất chuẩn  
hướng các thao tác đến thiết bị nhập xuất chuẩn của hệ thống.  
Các hàm đơn giản nhất của Thiết bị nhập/xuất chuẩn là:  
getchar() Ðọc một chỉ một tự từ bàn phím.  
putchar() Xuất một tự đơn ra màn hình.  
6.3.1 getchar()  
Hàm getchar() được dùng để đọc dữ liệu nhập vào, chỉ một tự tại một thời điểm từ bàn phím.Trong  
hầu hết việc thực thi của C, khi dùng getchar(), các ký tự nằm trong vùng đệm cho đến khi người dùng  
nhấn phím xuống dòng. Vì vậy sẽ đợi cho đến khi phím Enter được gõ. Hàm getchar() không có  
tham số, nhưng vẫn phải cặp dấu ngoặc đơn. đơn giản lấy về tự tiếp theo và sẵn sàng đưa ra  
cho chương trình. Chúng ta nói rằng hàm này trả về một giá trị kiểu tự.  
Chương trình sau trình bày cách dùng hàm getchar().  
dụ 6.11:  
/* Chương trình trình bày cách dùng getchar() */  
#include <stdio.h>  
void main()  
{
char letter;  
printf(“\nPlease enter any character: “);  
letter = getchar();  
printf(“\nThe character entered by you is %c. “, letter);  
}
Kết quả như sau:  
Nhập Xuất trong C  
85  
Please enter any character: S  
The character entered by you is S.  
Trong chương trình trên ‘letter’ là một biến được khai báo là kiểu char do vậy sẽ nhận vào ký tự.  
Một thông báo:  
Please enter any character:  
sẽ xuất hiện trên màn hình. Ta nhập vào một tự, trong ví dụ là S, qua bàn phím và nhấn Enter. Hàm  
getchar() nhận tự đó và gán cho biến có tên là letter. Sau đó được hiển thị trên màn hình và ta  
được thông báo.  
The character entered by you is S.  
6.3.2 putchar()  
putchar() là hàm xuất tự trong C, nó sẽ xuất một tự lên màn hình tại vị trí con trỏ màn hình.  
Hàm này yêu cầu một tham số. Tham số của hàm putchar() thể thuộc các loại sau:  
Hằng tự đơn  
Ðịnh dạng (Escape sequence)  
Một biến tự.  
Nếu tham số một hằng phải được bao đóng trong dấu nháy đơn. Bảng 6.5 trình bày vài tùy chọn  
cho putchar() và tác động của chúng.  
Tham số  
Hàm  
Tác dụng  
Biến tự  
putchar(c)  
Hiện thị nội dung của  
biến tự c  
Hằng biến tự  
putchar(‘A’)  
putchar(‘5’)  
putchar(‘\t’)  
Hiển thị tự A  
Hiển thị con số 5  
Hằng số  
Ðịnh dạng (escape  
sequence)  
Chèn một tự khoảng  
cách (tab) tại vị trí con trỏ  
màn hình  
Ðịnh dạng (escape  
sequence)  
putchar(‘\n’)  
Chèn một xuống dòng  
tại vị trí con trỏ màn hình  
Bảng 6.5: Những tùy chọn cho putchar() và tác dụng của chúng  
Chương trình sau trình bày về hàm putchar():  
86  
Lập trình cơ bản C  
dụ 6.12:  
/* Chương trình này trình bày việc sử dụng hằng định dạng trong  
hàm putchar() */  
#include <stdio.h>  
void main()  
{
putchar(‘H’); putchar(‘\n’);  
putchar(‘\t’);  
putchar(‘E’); putchar(‘\n’);  
putchar(‘\t’); putchar(‘\t’);  
putchar(‘L’); putchar(‘\n’);  
putchar(‘\t’); putchar(‘\t’); putchar(‘\t’);  
putchar(‘L’); putchar(‘\n’);  
putchar(‘\t’); putchar(‘\t’); putchar(‘\t’);  
putchar(‘\t’);  
putchar(‘O’);  
}
Kết quả như sau:  
H
E
L
L
O
Khác nhau giữa getchar() và putchar() putchar() yêu cầu một tham số trong khi getchar() thì không.  
dụ 6.13:  
/* Chương trình trình bày getchar() và putchar() */  
#include <stdio.h>  
void main()  
{
char letter;  
printf(“You can enter a character now: ”);  
letter = getchar();  
putchar(letter);  
}
Kết quả như sau:  
You can enter a character now: F  
F
Nhập Xuất trong C  
87  
Tóm tắt bài học  
Trong C, Nhập Xuất được thực hiện bằng cách dùng các hàm. Bất cứ chương trình nào trong C  
đều quyền truy cập tới ba tập tin chuẩn. Chúng là tập tin nhập chuẩn (stdin), tập tin xuất chuẩn  
(stdout) và bộ lỗi chuẩn (stderr). Thông thường tập tin nhập chuẩn là bàn phím (keyboard), tập  
tin xuất chuẩn là màn hình (screen) tập tin lỗi chuẩn cũng là màn hình.  
Tập tin tiêu đề <stdio.h> chứa các macro của nhiều hàm nhập xuất (input/output function)  
được dùng trong C.  
Thiết bị nhập/xuất chuẩn (Console I/O) liên quan đến những hoạt động của bàn phím và màn  
hình của máy tính. Nó chứa các hàm định dạng và không định dạng.  
Hàm nhập xuất định dạng printf() scanf().  
Hàm nhập xuất không định dạng getchar() putchar().  
Hàm scanf() được dùng cho dữ liệu nhập vào có định dạng, trong khi hàm printf() được dùng để  
xuất ra dữ liệu theo một định dạng cụ thể.  
Chuỗi điều khiển của printf() scanf() phải luôn tồn tại bên trong dấu nháy kép “”. Chuỗi này sẽ  
chứa một tập các lệnh định dạng. Mỗi lệnh định dạng chứa hiệu %, một tùy chọn các bổ từ và  
các dạng kiểu dữ liệu xác định.  
Sự khác nhau chính giữa printf() scanf() là hàm scanf() dùng địa chỉ của biến chứ không phải là  
tên biến.  
Hàm getchar() đọc một tự từ bàn phím.  
Hàm putchar(ch) gởi tự ch ra màn hình.  
Sự khác nhau giữa getchar() putchar() putchar() một tham số trong khi getchar() thì  
không.  
88  
Lập trình cơ bản C  
Kiểm tra tiến độ học tập  
1. Các hàm nhập xuất định dạng là _________ và ________.  
A. printf() scanf()  
C. puts() gets()  
B. getchar() putchar()  
D. Không câu nào đúng  
2. Hàm scanf() dùng _________ tới các biến chứ không dùng tên biến.  
A. Hàm  
B. Con trỏ  
C. Mảng  
D. Không câu nào đúng  
3. ___________ xác định định dạng cho các giá trị của biến sẽ được nhập và in.  
A. Văn bản  
C. Tham số  
B. Bộ định dạng  
D. Không câu nào đúng  
4. _______ được dùng bởi hàm printf() để xác định các đặc tả chuyển đổi.  
A. %  
C. *  
B. &  
D. Không câu nào đúng  
5. getchar() một hàm không có bất cứ tham số nào.  
6. Một ___________ là một nơi lưu trữ tạm trong bộ nhớ.  
(True/False)  
A. ROM (Bộ nhớ chỉ đọc)  
C. Vùng đệm  
B. Thanh ghi  
D. Không câu nào đúng  
7. Ðịnh dạng (Escape sequence) có thể được đặt bên ngoài chuỗi điều khiển của printf().  
(True/False)  
Nhập Xuất trong C  
89  
Bài tập tự làm  
1. A. Hãy dùng câu lệnh printf() để :  
a) Xuất ra giá trị của biến số nguyên sum.  
b) Xuất ra chuỗi văn bản "Welcome", tiếp theo là một dòng mới.  
c) Xuất ra biến tự letter.  
d) Xuất ra biến số thực discount.  
e) Xuất ra biến số thực dump có 2 vị trí phần thập phân.  
1. B. Dùng câu lệnh scanf() thực hiện:  
a) Ðọc giá trị thập phân từ bàn phím vào biến số nguyên sum.  
b) Ðọc một giá trị số thực vào biến discount_rate.  
2
Viết một chương trình xuất ra giá trị ASCII của các ký tự ‘A’ và ‘b’.  
3. Xét chương trình sau:  
#include <stdio.h>  
void main()  
{
int breadth;  
float length, height;  
scanf(“%d%f%6.2f”, breadth, &length, height);  
printf(“%d %f %e”, &breadth, length, height);  
}
Sửa lỗi chương trình trên.  
4. Viết một chương trình nhập vào name, basic, daper (phần trăm của D.A), bonper (phần trăm lợi  
tức) loandet (tiền vay bị khấu trừ) cho một nhân viên. Tính lương như sau:  
salary = basic + basic * daper/100 + bonper * basic/100 - loandet  
Bảng dữ liệu:  
name  
basic  
daper  
bonper  
loandet  
MARK  
2500  
55  
33.33  
250.00  
Tính salary và xuất ra kết quả dưới các đầu đề sau (Lương được in ra gần dấu đôla ($)):  
Name Basic Salary  
Viết một chương trình yêu cầu nhập vào tên, họ của bạn và sau đó xuất ra tên, họ theo dạng họ, tên.  
90  
Lập trình cơ bản C  
doc 20 trang Thùy Anh 16280
Bạn đang xem tài liệu "Giáo trình Lập trình cơ bản C - Bài 6: Nhập và xuất trong C", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

File đính kèm:

  • docgiao_trinh_lap_trinh_co_ban_c_bai_6_nhap_va_xuat_trong_c.doc