Lập trình C: Bài 3 – Nhập xuất trong c
Nội dung
Ở các bài trước, chúng ta đã làm quen với một số chương trình mà in lên màn hình một số thông tin. Bài này chúng ta sẽ tìm hiểu kỹ hơn về cách nhập xuất trong C.
1. Chuỗi định dạng dữ liệu
Trước khi đến với phần nhập, xuất dữ liệu cho các biến mình sẽ nói về một số định dạng để nhập và xuất. Sau đây là các dấu mô tả định dạng:
- %c : Ký tự đơn
- %s : Chuỗi
- %d : Số nguyên hệ 10 có dấu
- %f : Số chấm động (VD 5.54 khi in sẽ ra 5.540000)
- %e : Số chấm động (ký hiệu có số mũ)
- %g : Số chấm động (VD 5.54 khi in sẽ in ra 5.54)
- %x : Số nguyên hex không dấu (hệ 16)
- %o : Số nguyên bát phân không dấu (hệ 8)
- l : Tiền tố dùng kèm với %d, %x, %o để chỉ số nguyên dài (ví dụ%ld)
2. Xuất dữ liệu dùng printf
Chúng ta sử dụng hàm printf để xuất dữ liệu ra màn hình console (từ print có nghĩa là in). Kết hợp với các chuỗi định dạng ở trên, chúng ta xét một ví dụ đơn giản sau.
Ví dụ 1:
#include <stdio.h> int main() { int a = 12; float b = 13.5; char c = 'Q'; long d = 3454; char* s = "nguyenvanquan7826"; // khai bao kieu chuoi printf("Vi du ve su dung lenh printf\n"); printf("Tong cua %d va %f la %f \n", a, b, a+b); printf("Tich cua %d va %ld la %ld \n", a, d, a*d); printf("Ky tu c la: %c \n", c); printf("Chuoi s la: %s \n", s); printf("Dinh dang so mu cua b la %e \n", b); printf("So he 16 va he 8 cua %d la %x va %o \n", a, a, a); printf("Ma ASCII cua %c la %d", c, c); return 0; }
Ở trên mình có dùng một số ký tự điều khiển (\n – xuống dòng) đã được đề cập ở bài trươc, các bạn có thể xem lại nếu không nhớ. Các bạn chạy chương trình và rút ra nhận xét cho riêng mình.
Mình giải thích 1 câu lệnh để làm rõ hơn việc xuất của chúng ta.
Chuỗi định dạng được đặt trong ngoặc kép: “”. Tương ứng với mỗi định dạng là một biến có kiểu tương ứng, nếu khác kiểu sẽ dẫn đến sai sót.
Các bạn cũng chú ý là đối với số nguyên và ký tự có sự qua lại với nhau thông qua mã ASCII nên chúng ta có thể in mã của ký tự bằng định dạng %d và cũng có thể in ký tự có mã là số nào đó thông qua định dạng %c. Tuy nhiên bản chất của biến không thay đổi. Ở Vd trên câu lệnh in mã ASCII của c sẽ cho số nguyên nhưng bản chất c vẫn là một biến kiểu char.
Ví dụ 2:
#include <stdio.h> int main() { int a = 12; float b = 13.5; char c = 'Q'; long d = 3454; char s[] = "nguyenvanquan7826"; // khai bao kieu chuoi printf("%6d %5.3f %.3f \n", a, b, a+b); printf("%-5d %5ld %5ld \n", a, d, a*d); printf("%5c \n", c); printf("%30s \n", s); return 0; }
Các bạn thấy ví dụ này chúng ta dùng các định dạng %d, %f nhưng lại chèn thêm các số ở giữa thành %6d, %5.3f. Ý nghĩa của chúng như sau:
- %5c : Xuất ký tự có bề rộng 5
- %5d : Số nguyên có bề rộng 5
- %20s : Xuất chuỗi có bề rộng 20
- %5.3f : Xuất số thực có bề rộng 5 trong đó có 3 số sau dấu phẩy
- %-5d : Số nguyên có bề rộng 5 nhưng căn lề trái
Các bạn chạy chương trình, xem kết quả để thấy rõ hơn. Trong TH nếu bề rộng của chúng ta có kích thước bé hơn độ dài của số thì sao? Ví dụ chúng ta có số int a = 1234 nhưng chỉ in là %2d, rõ ràng dành 2 phần trống là ít hơn số a có 4 chữ số nhưng kết quả là số vẫn được in đầy đủ. Các bạn có thể thử.
Ví dụ 3:
Đặt bài toán là giả sử chúng ta có các biến thể hiện ngày tháng năm sinh bất kỳ (ví dụ ngay = 12, thang = 8, nam = 1992). Hãy in ra theo định dạng là dd/mm/yyyy. Nghĩa là chúng ta phải in ra kết quả 12/08/1992.
#include <stdio.h> int main() { int ngay = 12; int thang = 8; int nam = 1992; printf("KQ: %02d/%02d/%04d\n", ngay, thang, nam); return 0; }
Ở trên, các bạn chú ý chúng ta dùng %02d nghĩa là sao? Nhĩa là số in ra sẽ có 2 chữ số, nếu ban đầu số có ít hơn 2 thì sẽ thêm số 0 đằng trước để đủ 2 chữ số. Ví dụ số 8 sẽ thành 08. Nếu dùng %05d thì sẽ là 00008.
3. Nhập dữ liệu dùng scanf
Trong các ví dụ trước, chúng ta chỉ khai báo biến và gán giá trị cho biến nhưng như thế làm chương trình không linh hoạt vì chỉ hoạt động với những giá trị đã định trước, muốn hoạt động với các dữ liệu khác nhau chúng ta lại phải sửa lại code, như vậy thì không phải một chương trình tốt. Một chương trình phần mềm làm ra là phải dành cho nhiều bộ giá trị khác nhau có thể dùng được.
Chính vì vậy dữ liệu sẽ được đưa vào trong quá trình phần mềm được dùng và cụ thể đơn giản là nhập dữ liệu vào từ bàn phím. Chúng ta sử dụng lệnh scanf để nhập dữ liệu từ bàn phím (từ scan có nghĩa là quét và chúng ta dùng để quét dữ lệu từ bàn phím).
Ví dụ 1:
#include <stdio.h> int main() { int a; float b; printf("Nhap so nguyen a = "); scanf("%d", &a); printf("Nhap so thuc b = "); scanf("%f", &b); printf("a = %d \t b = %.3f", a, b); return 0; }
Việc sử dụng lệnh scanf kết hợp với chuỗi định dạng để nhập dữ liệu sẽ tương tự như khi xuất dữ liệu bằng lệnh printf.
Chú ý đừng quên ký tự & trước mỗi biến khi nhập. Nếu không sẽ sai.
Ví dụ 2:
/* Tinh dien tich hinh chu nhat */ #include <stdio.h> int main() { int a, b; printf("Nhap chieu dai, chieu rong: \n"); scanf("%d%d", &a, &b); printf("Dien tich HCN: %d\n", a * b); return 0; }
Ở ví dụ trên, các bạn thấy chúng ta có thể dùng 1 lệnh scanf để nhập dữ liệu cho nhiều biến, mỗi biến tương ứng với 1 định dạng nhất định.
4. Nhập chuỗi trong C
4.1 Lỗi khi nhập chuỗi bằng scanf
Nếu các bạn dùng hàm scanf để nhập chuỗi thì bạn sẽ thấy rằng không thể nhập được chuỗi có dấu cách hoặc nếu trước đó bạn nhập số thì sau đó không nhập được chuỗi nữa. Nếu không tin bạn có thể thử chạy với chương trình sau:
#include <stdio.h> int main() { int tuoi = 0; // khai bao chuoi co toi da 30 ky tu char ten[30], tenNguoiYeu[30]; printf("Ho va ten cua ban ten la gi? "); scanf("%s", ten); // nhap chuoi khong can dau & printf("Ban bao nhieu tuoi roi? "); scanf("%d", &tuoi); printf("Nguoi yeu cua ban ten la gi? "); scanf("%s", tenNguoiYeu); printf("\n====\n"); printf("Ten: %s \nTuoi:%d \nNY:%s \n", ten, tuoi, tenNguoiYeu); return 0; }
Kết quả là bạn sẽ không nhập được tuổi và tên người yêu như hình sau.
Lý do là scanf chỉ đọc được dữ liệu không có khoảng trắng (đấu cách, dấu tab, enter, …) và các khoảng cách này sẽ được lưu vào bộ đệm bàn phím do đó bạn chỉ nhận được chuỗi đầu tiên trước đấu cách mà thôi (chữ Nguyen), sau mỗi dấu cách, các giá trị tiếp theo nếu phù hợp với kiểu dữ liệu của các biến tiếp theo thì nó sẽ gán luôn cho chúng và bạn sẽ không được nhập nữa. Do tuoi kiểu nguyên nên không nhận được, tenNguoiYeu sẽ nhận giá trị tiếp theo trong các giá trị nhận được là chữ Van.
4.2 Hiện tượng trôi lệnh
Hiện tượng như trên được gọi là hiện tượng trôi lệnh. Nếu bây giờ bạn thực hiện cho nhập số trước và chuỗi ngay sau đó thì hiện tượng này cũng xảy ra vì scanf chỉ đọc số theo đúng định dạng mà không đọc được phím enter khi bạn nhấn lúc nhập xong số (enter là ký tự hoặc cũng có thể coi là chuỗi), nó được lưu vào bộ đệm và khi đọc giá trị nhập cho chuỗi nó tìm trong bộ đệm thấy ký tự enter là kiểu chuỗi nên nó gán luôn cho chuỗi đó.
Để nhập được chuỗi có khoảng trắng (dấu cách) chúng ta sử dụng hàm gets.
Để không bị trôi lệnh khi nhập số trước và chuỗi sau ta cần xóa bộ đệm bàn phím bằng lệnh fflush(stdin); ngay sau khi nhập số.
#include <stdio.h> int main() { int tuoi = 0; // khai bao chuoi co toi da 30 ky tu char ten[30], tenNguoiYeu[30]; printf("Ho va ten cua ban ten la gi? "); gets(ten); // nhap chuoi khong can dau & printf("Ban bao nhieu tuoi roi? "); scanf("%d", &tuoi); fflush(stdin); printf("Nguoi yeu cua ban ten la gi? "); gets(tenNguoiYeu); printf("\n====\n"); printf("Ten: %s \nTuoi:%d \nNY:%s \n", ten, tuoi, tenNguoiYeu); return 0; }
Nếu bạn dùng Linux thì fflush(stdin); sẽ không hoạt động, bạn có thể khắc phục bằng cách nhập vào 1 chuỗi tạm ngay sau khi nhập số. Việc nhập chuỗi tạm này chỉ để xóa bỏ các ký tự, chuỗi ký tự thừa có trong bộ đệm như sau (cách này cũng dùng được khi bạn làm trên windows).
#include <stdio.h> int main() { int tuoi = 0; // khai bao chuoi co toi da 30 ky tu char ten[30], tenNguoiYeu[30], temp[255]; printf("Ho va ten cua ban ten la gi? "); gets(ten); // nhap chuoi khong can dau & printf("Ban bao nhieu tuoi roi? "); scanf("%d", &tuoi); //fflush(stdin); gets(temp); printf("Nguoi yeu cua ban ten la gi? "); gets(tenNguoiYeu); printf("\n====\n"); printf("Ten: %s \nTuoi:%d \nNY:%s \n", ten, tuoi, tenNguoiYeu); return 0; }
5. Giải thích một chút về printf, scanf và stdio.h
5.1 Chữ f trong printf và scanf
Như các bạn đã biết print nghĩa là in, scan là quét hay ta gọi trong này là để nhập. Vậy tại sao chúng lại có chữ f đằng sau để thành printf và scanf ?
Chữ f này có nghĩa là format (định dạng). Như các bạn thấy chúng ta nhập hoặc xuất các giá trị của các biến đều có định dạng % gì đó ví dụ %d là số nguyên, %f là số thực,… và chữ f này chính là có ý nghĩa như thế.
5.2 Thư viện stdio.h ?
Trong tất cả các chương trình từ trước tới giờ, chúng ta luôn có #include <stdio.h>
, vậy nó là gì?
#include
nghĩa là bao gồm tức là chương trình của chúng ta sẽ khai báo sử dụng một cái gì đó, mà ở đây là sử dụng thư viện stdio.h
Vậy stdio.h là gì? std viết tắt của standard , i viết tắt của input, o viết tắt của output, h viết tắt của header (header – đầu, trên đầu – vì nó được khai báo ở trên đầu của các chương trình). Vậy nó có nghĩa là standard input output – nhập xuất chuẩn. Chúng ta hiểu nó là thư viện phục vụ cho việc nhập xuất chuẩn của chương trình. Nhập xuất chuẩn chính là nhập từ bàn phím và xuất ra màn hình. Có còn rất nhiều nguồn nhập xuất như nhập từ file, nhập từ con trỏ chuột,… xuất ra máy in, xuất ra file,… nhưng họ coi bàn phím và màn hình là hệ thống nhập xuất chuẩn.
Bài tập
- Viết chương trình nhập vào một số a bất kỳ và in ra giá trị a2, a3, a4
- Viết chương trình đọc từ bàn phím 3 số nguyên biểu diễn ngày, tháng, năm và xuất ra màn hình dưới dạng “dd/mm/yyyy”.
- Viết chương trình đọc và 2 số nguyên và in ra kết quả của phép (+), phép trừ (-), phép nhân (*), phép chia (/). Nhận xét kết quả chia 2 số nguyên.
- Viết chương trình nhập vào bán kính hình cầu, tính và in ra diện tích, thể tích của hình cầu đó.
Hướng dẫn: S = 4πR^2 và V = (4/3)πR^3.- Nhập vào một số là số giây, đổi số giây này ra giờ phút giây và xuất theo dạng gio:phut:giay, mỗi thành phần có 2 chữ số. Ví dụ 3661 = 01:01:01.
số nguyên dài cỡ nào thì mới cần dùng tiền tố l để đi kèm ạ, em thử chạy chương trình ở vd 2 rồi xóa đi chữ l thành %5d %5d nhưng ko bị lỗi j, cả 2 chương trình đều ra kq y hệt, nhân tiện bài của anh rất hay ạ, rất dễ hiểu cho người mới chưa biết j như em! =)
Khi mà kiểu dữ liệu của bạn là long thì có tiền tố l đằng trước.
mình cũng đag thắc mắc
Tại sao khi em chạy CT thì lại has stopped working z ạ?? T_T
#include
int main()
{
char Ten[30],Dia_chi[50],So_thich[100];
int ngay[31],thang[12],nam;
printf(“Ho va ten “);
gets(Ten);
printf(“Dia chi “);
gets(Dia_chi);
printf(“Ngay sinh “);scanf(“%d”,&ngay);
printf(“Thang sinh “);scanf(“%d”,&thang);
printf(“Nam sinh “);scanf(“%d”,&nam);
fflush(stdin);
printf(“So thich “);gets(So_thich);
printf(“\n==============\n\n”);
printf(“Ten: %s\nDia chi: %s\nNgay thang nam sinh:%d\t%d\t%d\t\nSo thich: %s”,Ten,Dia_chi,So_thich,ngay,thang,nam);
return 0;
}
Em fix lại đc rồi nhưng lý do nó stopped working thì anh giải thích hộ em với ạ @@, đây là cái file nguồn em vừa fix lại:
#include
int main()
{
char Ten[30],Dia_chi[50],So_thich[100];
int ngay,thang,nam;
printf(“Ho va ten “);
gets(Ten);
printf(“Dia chi “);
gets(Dia_chi);
printf(“Ngay sinh “);scanf(“%d”,&ngay);
printf(“Thang sinh “);scanf(“%d”,&thang);
printf(“Nam sinh “);scanf(“%d”,&nam);
fflush(stdin);
printf(“So thich “);gets(So_thich);
printf(“\n==============\n\n”);
printf(“Ten: %s\nDia chi: %s\n”,Ten,Dia_chi);
printf(“Ngay thang nam sinh:%d/%d/%d\n”,ngay,thang,nam);
printf(“So thich: %s”,So_thich);
return 0;
}
Anh nói ở bình luận trước rồi nhé. Do em khai báo mảng thôi.
Vì em khai báo biến ngày và biến tháng bị sai. ngày tháng là các số, em khai báo ngay[31] nghĩa là 1 mảng gồm 31 số giông như Ten[30] là 1 mảng 30 ký tự (ghép lại thành chuỗi). Sửa thành int ngay, thang, nam. Vậy là được
anh ơi a có thể cho e xin facebook để e hỏi một số thứ không ạ. Em là du học sinh mà đang học về phần ngôn ngữ C. Do vấn đề về giao tiếp nên học ở trường e còn nhiều thứ không biết. MOng anh có thể chỉ giáo thêm ạ. EM cảm ơn
Bạn có thể gửi mail cho mình quá: nguyenvanquan7826@gmail.com nhé.
Anh có thể cho em xin phần code bài số 5 được không ạ?
#include
#include
#include
//———————————————————————-
int main() {
float so;
printf(“\n\n\tNhap vao 1 so: “); scanf(“%f”, &so); fflush(stdin);
printf(“\n\tBinh phuong so vua nhap la:\t\t%7.2f”, pow(so, 2));
printf(“\n\tLap phuong so vua nhap la:\t\t%7.2f”, pow(so, 3));
printf(“\n\n\n\n\n\n\n\n\n\n\n”);
return 0;
}
//———————————————————————
int main() {
int ngay, thang, nam;
printf(“Ban hay nhap vao ngay, thang va nam: \n”); scanf(“%d%d%d”, &ngay, &thang, &nam);
system(“cls”);
printf(“Ngay, thang va nam (dd/mm/yyyy) vua nhap la %02d/%02d/%4d”, ngay, thang, nam);
printf(“\n\n\n\n\n\n\n\n\n\n\n”);
return 0;
}
//———————————————————————
int main() {
int a, b;
printf(“\n\n\tNhap vao 2 so nguyen a, b: “); scanf(“%d%d”, &a, &b); fflush(stdin);
system(“cls”);
printf(“\n\n\tVoi so a co gia tri la %d, so b co gia tri la %d thi:”, a,b);
printf(“\n\n\ta + b = %d\n\n\ta – b = %d\n\n\ta * b = %d\n\n\ta / b = %d”, a + b, a – b, a * b, a / b);
if (a % b == 0) {
printf(“\n\n\tSo a chia het cho so b”);
}
else {
printf(“\n\n\tSo a khong chia het cho so b, cu the la %d / %d duoc %d, du %d”, a, b, a / b, a % b);
printf(“\n\n\n\n\n\n\n\n\n\n\n”);
}
return 0;
}
//———————————————————————
int main() {
float r;
printf(“\n\n\tNhap ban kinh r: “); scanf(“%f”, &r); fflush(stdin);
system(“cls”);
printf(“\n\n\tVoi ban kinh r = %.2f, dien tich S cua hinh cau la: %.2f”, r, 4 * 3.14 * pow(r, 2));
printf(“, the tich V cua hinh cau la: %.2f”, 4 * 3.14 * pow(r, 3) / 3);
printf(“\n\n\n\n\n\n\n\n\n\n\n”);
return 0;
}
//———————————————————————
int main() {
int giay;
printf(“\n\n\tNhap vao tong so giay: “); scanf(“%d”, &giay); fflush(stdin);
system(“cls”);
printf(“\n\n\tVoi tong so %d giay da cho, ta co dinh dang theo hh:mm:ss la: %02d:%02d:%02d”, giay, giay / 3600, (giay % 3600) / 60, giay % 60);
printf(“\n\n\n\n\n\n\n\n\n\n\n”);
return 0;
}
Note:
– Để xài được lệnh xóa màn hình system(“cls”), ngoài #include bạn cần có thêm #include .
– Cũng tương tự, để xài hàm pow cho việc tính lũy thừa của một số, bạn cần có #include vào nhé. VD: để tính lũy thừa 4 cho một con số mà đại diện là biến a, thì ta gõ pow(a, 4).
– Để hiểu sâu xa hơn nữa thì bạn nhờ thầy Quân nhé.
Bạn vào trang chấm code online code.cachhoc.net để nộp code nhé. sẽ biết mình làm đúng hai sai.
#include
int main()
{
int a,hh,pp,ss;
a=3666;
hh=a/3600;
pp=(a%3600)/60;
ss=(a%3600)%60;
printf(“0%d:0%d:0%d”,hh, pp, ss);
return 0;
}
Có video hướng dẫn không ad?
cho em hỏi ở ví dụ 2 tính diện tích hình chữ nhật khi nhập giá trị chiều dài chiều rộng vào mà cho ra kết quả diện tích là một chuỗi số dài vậy ạ
Có thể việc nhập hoặc xuất của bạn bị sai nên nó in ra một số rất lớn. Bạn có thể vào trang https://chamcode.net để test và làm bài tập nhé.
Không thể chuyển đổi giá trị thành char * ở VD 1 (2. Xuất dữ liệu dùng printf).
Trong phần xuất dữ liệu có nói về %d %f %c vậy cho em hỏi mình tìm những định dạng này cho các kiểu dữ liệu khác (ví dụ như : double, long int, unsigned char, …) ở đâu vậy ạ ?
Bạn có thể lên google tìm thêm nhé. Hoặc tham khảo link này: https://codeforwin.org/2015/05/list-of-all-format-specifiers-in-c-programming.html
khi mà nhập chiều dai chiều rộng hay tuổi thì phải cần điều kiện để số đo lớn hơn 0 chứ ạ..
Đúng rồi, tuy nhiên ở đây mình không chú trọng vào nó nhiều.
cho em hỏi ở ví dụ 1 char vs char* khác nhau ntn ạ?
char là kiểu ký tự, char * là kiểu chuỗi hoặc con trỏ ký tự.
=(( có cách nào cho mấy người nhỏ tuổi chưa biết gì về C, nhưng có thể code được không ạ. Em làm mỗi bài tập 2, còn mấy bài kia em không biết làm, thấy mấy bạn bảo muốn tính a mũ 2,3,4 phải dùng pow mà trong bài em chả thấy pow đâu. Nếu chỉ có mấy anh biết về nó mới làm được , còn em không làm được =(( khá buồn
a^2 = a*a, a^3 = a*a*a. sao phải dùng pow ?
em cảm ơn thầy, do em mới học hết lớp 9 nên…. =))
#include
int main()
{
int gio, phut, giay;
printf(“nhap so gio now:\nNhap so phut now:\nNhap so giay now:\n “);
scanf(“%d%d%d”, &gio, &phut, &giay);
printf(“KQ: %dgio %dphut %dgiay”, gio, phut, giay);
return 0;
}
Bạn có thể vào trang https://chamcode.net để nộp bài nhé.
em xin code bài 5 thấy ơi
nên tự làm nhé.
// doi so giay sang dinh dang gio:phut:giay
#include
int main()
{
int a;
printf(“Nhap vao so giay can quy doi:\n”);
printf(“So giay: “);
scanf(“%d”, &a);
int b = a-(a/3600)*3600;
int c = b-(b/60)*60;
printf(“\r=========Ket qua quy doi=========\n”);
printf(“Thoi gian sau quy doi: %02d:%02d:%02d”, a/3600, b/60, c);
return 0;
}
Bạn có thể vào https://chamcode.net để nộp bài nhé, có hệ thống chấm lun.
thầy ơi làm sao để tính căn của 1 số vậy thầy
dùng sqrt(x) trong thư viện math.h nhé.
nếu muốn nhận một dãy số thực từ labview về vi điều khiễn thì trong chương trình CCS nên dùng: scanf , fgets , gets . AK????/
cái này mình ko rõ vì không làm vi điều khiển nhé.
A ơi cho e hỏi, e mới học c thôi ạ nếu ở bài 3 e chia 2 số nguyên thì e tách ra làm một biến mới theo kiểu thực,xong e dùng cthuc thương=a/b; thì có ổn không? và nếu làm vậy thì e thêm hàm thư viện vô có khác biệt gì không? Vì 2 kết quả e thấy k khác nhau? Mong a giúp
Khi chia 2 số nguyên cho nhau muốn có kết quả là một số thực thì cần ép kiểu nhé. Bạn xem bài 4 về phép toán, toán tử để biết thêm nhé.
rất hay
Giờ học lại chịu
#include
int main()
{
int h,m,s,a;
printf(“nhap so giay\n”);
scanf(“%d”, &a);
h=a/3600;
m=(a-h*3600)/60;
s=a-(m*60+h*3600);
printf(“%02d:%02d:%02d”,h,m,s);
return 0;
}