Trong
C, thư viện chuẩn cung cấp những thủ tục cho việc nhập và xuất. Thư viện chuẩn
có 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ự và
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 và 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 và 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 có thể được
gửi đến máy in.
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, ký hiệu # nên đặt tại cột đầu tiên. stdio.h là
một tập tin và được gọi là tập tin tiêu đề (header). Nó chứa các macro cho nhiều hàm nhập và xuất
được dùng trong C. Hàm printf(), scanf(), putchar() và 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.
Nhập
và 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 và xuất có định dạng.
Chúng là:
printf() – Hàm xuất có định dạng.
scanf() – Hàm nhập có định dạng.
Những
hàm này gọi là 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.
Hàm printf()
Cú pháp:
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.
Chuỗi
điều khiển (control string): 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 và 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 là dấu phân cách. Chuỗi điều khiển chứa một hay nhiều hơn ba thành phần dưới
đây :
Ký tự văn
bản (Text characters) – Bao gồm các ký tự có thể in ra được
và 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 ký hiệu % và
theo sau là một mã đị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ự và kiểu từ trái sang phải. Một
mã đị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
và dấu xuống dòng.
Mỗi lệnh định dạng gồm một hay nhiều mã
định dạng. Một mã định dạng bao gồm ký
hiệu % và 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()
|
Ký tự đơn (Single
Character)
|
%c
|
%c
|
Chuỗi (String)
|
%s
|
%s
|
Số nguyên có dấu
(Signed decimal integer)
|
%d
|
%d
|
Số thập phân có
dấu chấm động (Floating point)
|
%f
|
%f hoặc %e
|
Số thập phân có
dấu chấm động - Biểu diễn phần thập phân
|
%lf
|
%lf
|
Số thập phân có
dấu chấm động - Biểu diễn dạng số mũ
|
%e
|
%f hoặc %e
|
Số thập phân có
dấu chấm động (%f hoặc %e, con số nào ít
hơn)
|
%g
|
|
Số nguyên không
dấu (Unsigned decimal integer)
|
%u
|
%u
|
Số thập lục phân
không dấu (Dùng “ABCDEF”)
(Unsigned
hexadecimal integer)
|
%x
|
%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 và x là 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:
Mã định dạng
|
Quy ước in ấn
|
%d
|
Các con số trong
số nguyên.
|
%f
|
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ố, nó 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.
|
%e
|
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.
Số
|
Câu lệnh
|
Chuỗi điều khiển
|
Nội dung mà chuỗi điều khiển chứa đựng
|
Danh sách tham số
|
Giải thích danh sách tham số
|
Hiển thị trên màn hình
|
1.
|
printf(“%d”,
300);
|
%d
|
Chỉ chứa lệnh
định dạng
|
300
|
Hằng số
|
300
|
2.
|
printf(“%d”,
10+5);
|
%d
|
Chỉ chứa lệnh
định dạng
|
10 + 5
|
Biểu thức
|
15
|
3.
|
printf(“Good
Morning Mr. Lee.”);
|
Good Morning Mr.
Lee.
|
Chỉ là các ký tự
văn bản
|
Không có (Nil)
|
Không có
|
Good Morning Mr.
Lee.
|
4.
|
int count = 100;
printf(“%d”,
count);
|
%d
|
Chỉ chứa lệnh
định dạng
|
Count
|
Biến
|
100
|
5.
|
printf(“\nhello”);
|
\nhello
|
Chỉ là các ký tự
văn bản và ký tự không in được.
|
Không có
|
Không có
|
Hello
(Trên dòng mới)
|
6.
|
#define str “Good
Apple”
……..
printf(“%s”,
str);
|
%s
|
Chỉ chứa lệnh
định dạng
|
Str
|
Hằng chuỗi
|
Good Apple
|
7.
|
……..
int
count,stud_num;
count = 0;
stud_num = 100;
printf(“%d %d\n”,
count, stud_num);
|
%d %d
|
Chỉ chứa lệnh
định dạng và trình tự thoát ra
|
count, stud_num
|
Hai biến
|
0, 100
|
Bảng 6.4 : Chuỗi điều khiển và mã định
dạng
Ví dụ:
Ðây là một chương trình đơn giản dùng
minh họa cho một chuỗi có thể được in theo lệnh định dạng. Chương trình này
cũng hiển thị một ký tự đơn, số nguyên và số thực (a single character, integer,
và float).
#include <stdio.h>
void main(){
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 có thể có 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 có 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 là 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 có độ 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 vị trí cho đủ yêu cầu.Ví dụ, %10f
là 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 ký 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 là một số nguyên. Nếu sử dụng
với kiểu float và double, chuỗi số chỉ ra số con số tối đa
có 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 ký tự. Ví 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.
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 mà 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 nó đối với những dữ liệu kiểu
số nguyên.
Ví dụ:
/* 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:
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
và 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 và 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.
Ví dụ:
/* 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 ”);
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 là 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 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ố ký tự được in.
Ví dụ:
/* 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.]
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 ký 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 mã ASCII
(Bộ mã 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
ký tự hay một số tùy vào kiểu của biến đó. Ví dụ sau mô tả điều này:
Ví dụ:
#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 và việc thông dịch của mã ASCII. Mặc dù các biến a và b
đã được khai báo là các biến kiểu int và char, nhưng chúng đã được
in như là ký tự và 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ử lý dữ liệu được linh hoạt.
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 ký hiệu \ như được trình bày trong ví dụ dưới đây:
Ví dụ:
/* 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\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\aaaaaaaaaaaaaaaaaaaaaaaaaaaaa”);
}
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.
Hàm 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ổ từ và
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 là một mục dữ liệu chứa đựng địa chỉ của nơi
mà 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 có 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.
Sự khác nhau trong lệnh định dạng giữa printf()
và scanf()
Không có
tùy chọn %g.
Mã định dạng
%f và %e có cùng hiệu quả tác động. Cả hai nhận một ký 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 ký tự không được
in như ký tự khoảng trắng, ký 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. Có 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
ký 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 ký 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.
Ví dụ:
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.
Ví dụ:
#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 là đặc tính F sẽ bị bỏ qua.
Khi ta chỉ rõ 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 ký tự khoảng trắng đầu tiên (bất cứ ký tự nào đầu tiên). Ðiều này cũng áp dụng
cho các kiểu int, float và double.
Ví dụ dưới đây mô tả việc sử dụng hàm
scanf() để nhập vào một chuỗi gồm có những ký tự viết hoa và khoảng trắng. Chuỗi
sẽ có chiều dài không xác định nhưng nó bị giới hạn trong 79 ký tự (thật ra, 80
ký tự bao gồm ký tự trống (null) được thêm vào nơi cuối chuỗi).
Ví dụ:
#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 ký tự
được định nghĩa bên trong [] có thể được chấp nhận như những ký 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 là Beijing city,
chỉ ký 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ư ký tự đầu tiên bên ngoài chuỗi.
Ðể chấp nhận bất kỳ ký tự nào đến khi gặp
ký tự xuống dòng, chúng ta sử dụng mã định dạng %[^\n], điều này ngụ ý rằng chuỗi
đó sẽ chấp nhận bất kỳ 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 ký tự nằm sau dấu mũ đó sẽ được chấp nhận như
ký tự hợp lệ.
Ví dụ:
#include <stdio.h>
void main() {
char
line[80];
……………..
scanf(“%[^\n]”,
line);
………..
}
Khi hàm scanf() được thực thi, một
chuỗi có 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 và đượ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!
Có 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.
Ví dụ:
#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 và 0.05 sẽ được gán
cho cost nhưng 12345 sẽ không được gán cho partno bởi
vì dấu * ngăn chặn việc gán.
Bất cứ ký 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
(,).
Ví dụ:
10,
15, 17
và 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 nó sẽ có chức năng như dấu phân cách.
Ký 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 mã định dạng
%c. Nếu chúng ta dùng bộ định dạng %c thì một khoảng trắng được xem như là một
ký 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
14 sẽ được gán cho x, ký tự ch nhận ký
tự khoảng trắng (số 32 trong hệ thập phân), do vậy y được gán giá trị của ký tự
‘c’ tức là 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 vì chuỗi nhập có chứa ký tự khoảng trắng. Ðể bỏ qua các ký tự khoảng trắng này và đọc
ký 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 và kết quả đúng như ý định của ta:
c1 = a, c2 = b, c3 = c
إرسال تعليق