Professional Documents
Culture Documents
CLang-lect01 - 2023-Đã Gộp
CLang-lect01 - 2023-Đã Gộp
CLang-lect01 - 2023-Đã Gộp
huydq@soict.hust.edu.vn
eureka!
Giải thuật
Tập các chỉ lệnh hướng dẫn quá
trình thực hiện một công việc
Chương trình
Máy tính có thể làm gì ?
Không nhiều… Máy tính chỉ có thể hiểu
các con số!
• Lưu trữ, tìm kiếm các con số (nhanh và
chính xác).
• Thực hiện các phép tính cộng, trừ, nhân,
chia sô học (cũng nhanh và chính xác).
• So sánh số học.
• Di chuyển và thực hiện các chỉ lệnh tính
toán trong một danh sách.
Máy tính có thể làm gì nữa ?
• Các tính toán phức tạp hơn có thể được
thực hiện từ tổ hợp các tính toán căn bản.
• Kết nối với các thiết bị ngoại vi để thực
hiện nhập xuất dữ liệu (input/output)
– Input : bàn phím, con chuột, …
– Output : màn hình, máy in
• Mọi thứ đều được làm với các con số.
Mô hình máy tính Von Neumann
Chương trình máy tính là gì?
• Một chuỗi các chỉ lệnh nhằm giải quyết
một mục đích nhất định
• Các chỉ lệnh được thực hiện một cách
tuyến tính.
• Không có chỉ lệnh nào được thực hiện
khi chỉ lệnh trước đó chưa hoàn thành.
• Chương trình có thể được biểu diễn bằng
một ngôn ngữ lập trình.
Ngôn ngữ máy
10 cái kẹo
Bình này có
thể dùng để 50 g đường
chứa
3 cái bánh
v.v
Kiểu của biến
• Biến có thể được hạn chể để chỉ chứa
một kiểu cụ thể nào đó của giá trị
• Ví dụ : cân (gạo) hay lít (nước)
Chỉ lệnh
• Là lệnh chỉ dẫn thực hiện một việc mà
– đơn giản
– không nhập nhằng
– hệ thống đã biết về nó để có thể thực hiện
– có thể đưa ra hướng dẫn thực hiện trên giá trị
và biến của giải thuật
Lời khuyên về các chỉ lệnh
Chú ý: Với while…do…, điều kiện lặp được kiểm tra ngay từ lần đầu tiên
Câu hỏi ?
Hai giải thuật dưới đây có cho cùng một kết quả ?
Giải thuật 1 Giải thuật 2
sốlẻ = 1 sốlẻ = 1
while (sốlẻ nhỏ hơn 100) while (sốlẻ nhỏ hơn 100)
do do
{ {
output sốlẻ tăng thêm 2 vào sốlẻ
tăng thêm 2 vào sốlẻ output sốlẻ
} }
Trong giải thuật 1, lần nhập a đầu tiên không được thực hiện vì điều
kiện lặp không thoả mãn. Ngược lại trong giải thuật 2 a được nhập giá
trị cho lần đầu tiên mà không cần kiểm tra điều kiện.
Thủ tục
• Là một chuỗi các chỉ lệnh được đặt tên
• Vì vậy bạn có thể
– tham chiếu đến nó (thông qua tên)
– ...sử dụng lại bằng cách copy các chỉ lệnh trong thủ
tục vào giải thuật của bạn
• Thủ tục được sử dụng trong lập trình có cấu trúc
để phân chia chương trình thành các thành
phần nhỏ với nhiều tên gọi khác nhau
– Thủ tục (procedure)
– Hàm (function)
– Chương trình con (sub-routine)
Ví dụ về thủ tục
huydq@soict.hust.edu.vn
1
Nội dung
➢Tổng quan về ngôn ngữ C
2
Tại sao học ngôn ngữ C ?
• Là ngôn ngữ có tính uyển chuyển cao
– Lập trình có cấu trúc
– Có khả năng hỗ trợ các thao tác ở mức thấp
• Có tính khả chuyển cao
• Dịch ra chương trình mã máy có kích thước nhỏ
và rất hiệu quả khi thực hiện
• Được sử dụng rộng rãi trong lập trình
chuyên nghiệp
• Là ngôn ngữ nền tảng của một số ngôn ngữ
khác (C++, Java, Perl, awk)
3
Phân biệt C và C++
• Điểm giống nhau:
4
Phân biệt C và C++
• Điểm khác nhau:
C C++
Phát triển bởi Dennis Ritchie từ 1969 Phát triển bởi Bjarne Stroustrup vào
tới 1973. 1979.
Không hỗ trợ lập trình hướng đối Hỗ trợ lập trình hướng đối tượng như:
tượng. đa hình, đóng gói, kế thừa, đối tượng
Đuôi mở rộng file c là .c Đuôi mở rộng file C++ là .cpp
Là con của C. Code C có thể chạy bởi
Là cha của C++ C++ nhưng code C++ không thể chạy
bởi C.
Ngoài 32 từ khóa của C còn bổ sung
Có 32 từ khóa
thêm nhiều từ khóa mới
…. …
5
Lịch sử ngôn ngữ C
• CPL Combined Programming Language (Barron et al., 1963)
• B (Thompson, 1970)
• có nguồn gốc từ BCPL, tên thu gọn từ BCPL
• thiết kế cho các ứng dụng đệ quy, không dùng chữ số, độc
lập với máy tính, VD: như phần mềm hệ thống và ngôn ngữ.
6
Lịch sử ngôn ngữ C
• C K&R C (Ritchie, 1972)
• phát triển bởi Dennis M. Ritchie tại Bell Labs của AT&T
• thực thi lần đầu tiên trên máy tính DEC PDP-11
• 1978: C được giới thiệu trong phiên bản đầu của cuốn sách
"The C programming language”- Kernighan và Ritchie
7
Lịch sử ngôn ngữ C
• C được bổ sung thêm những tính năng và khả năng mới .
• Đồng thời tồn tại nhiều phiên bản nhưng không tương thích
nhau.
• Mã nguồn C có thể chạy tôt trên compiler này nhưng trên
compiler khác thì bị lỗi -> cần phải có một tiêu chuẩn thống
nhất
• C89, ANSI C, American National Standards Institute C
(X3J11, 1989)
• C99 (JTC1/SC22/WG14, ISO/IEC 9899, 1999)
• C11,2011
8
Nội dung
➢Tổng quan về ngôn ngữ C
9
Chương trình C đầu tiên
Hello World – Chào thế giới
Giải thuật Chương trình C
#include <stdio.h>
int main()
output “Hello World!” {
printf(“Hello World!”);
return 0;
}
10
Cấu trúc căn bản chương trình C
11
Cú pháp của C
• Chương trình được viết dựa trên
– Các từ khóa: là các từ được định nghĩa từ trước
dành riêng cho ngôn ngữ, ví dụ: main, if, do, while,
…
– Các bộ kí tự dấu: sử dụng với mục đích đặc thù
trong chương trình như tạo 1 khối lệnh { }, tạo một
chuỗi kí tự “”, …
12
Từ khoá C
• Điều khiển luồng: if, else, return, switch, case, default
• Kiểu: int, long, short, float, double, char, void, signed, unsigned,
static, const
13
Các bộ dấu thường dùng
14
Định danh - Tên
• Identifier
• Khi khai báo 1 biến hay 1 chương trình con, người
lập trình cần phải đặt tên cho nó.
• Quy tắc đặt tên của người sử dụng
– Chỉ dụng chữ cái, chữ số và kí tự gạch nối (_) để đặt tên
– Tên phải bắt đầu bằng chữ cái hoặc dấu _
– Phân biệt chữ hoa và chữ thường trong các tên
• Những tên nào sau đây là hợp lệ ?
– tong, 2k, trung binh, lon_nhat, u2, %totnghiep
15
Định danh – Tên (tiếp)
• Lưu ý:
1.Định danh gồm nhiều từ -> tách các từ bằng cách sử dụng dấu _.
VD: danh_sach_sinh_vien dễ đọc và dễ hiểu hơn so với danhsachsinhvien.
3.Ngôn ngữ C phân biệt chữ cái thường và chữ cái hoa
VD: dinh_danh khác Dinh_danh.
16
Định danh – Tên (tiếp)
• Lưu ý (tiếp):
4. Hằng đặt tên bằng chữ hoa,
biến, hàm, cấu trúc: chữ thường.
Ví dụ:
17
Ví dụ viết chương trình
Tạo hàm chính cho
chương trình
In các số từ 0 đến 9 int main()
{
đặt dem = 0
while (dem nhỏ hơn 10)
do
{
output dem
tăng 1 vào dem
} return 0;
}
18
Ví dụ (tiếp)
#include <stdio.h>
In các số từ 0 đến 9
int main()
{ Khai báo tiêu đề
đặt dem = 0
while (dem nhỏ hơn 10)
do
{
output dem
tăng 1 vào dem
return 0;
} }
19
Ví dụ (tiếp)
#include <stdio.h>
int main()
{ Chú thích
đặt dem = 0
while (dem nhỏ hơn 10)
do
{
output dem
tăng 1 vào dem
return 0;
} }
20
Ví dụ (tiếp)
#include <stdio.h>
21
Ví dụ (tiếp)
#include <stdio.h>
22
Ví dụ (tiếp)
#include <stdio.h>
23
Ví dụ (tiếp)
#include <stdio.h>
24
Ví dụ (tiếp)
#include <stdio.h>
25
Chương trình sau làm gì?
#include <stdio.h>
int main(){
float num;
if ( num < 0 ) {
printf(“%f is negative”, num);
} else {
printf(“%f is positive”, num);
}
return 0;
}
26
Giải thuật của chương trình
/* Tìm dấu của một số */
input num
if (num < 0) then
{
output “số âm”
}
else
{
output “số dương”
}
27
Nội dung
➢Tổng quan về ngôn ngữ C
28
Ngôn ngữ lập trình bậc cao
10100110 01110110
#include <stdio.h> 00100110 00000000
11111010 11111010
int main() 01001110 10100110
{ 11100110 10010110
printf(“Hello World”); 11001110 00101110
10100110 01001110
11111010 01100110
return 0; 01001110 10000110
} etc...
Mã nguồn Mã máy
29
Biên dịch chương trình C
Lỗi có thể sảy ra tại pha dịch hay pha liên kết
30
Trình biên dịch
• Để dịch chương trình thì cần phải có trình biên dịch, ví
dụ: gcc
• Trình biên dịch C luôn hỗ trợ các tham số để thực hiện
2 pha của quá trình dịch.
• Ví dụ: gcc -c để thực hiện pha dịch, và
• gcc -o để thực hiện pha liên kết.
31
IDE: Môi trường hỗ trợ lập trình
• Lập trình : lặp đi lặp lại soạn mã nguồn, thực hiện dịch, chạy
tìm lỗi và sửa
• Thực hiện độc lập = các công cụ khác nhau: ví dụ
• soạn thảo bằng emacs,
• dịch chương trình bằng gcc,
• gỡ lỗi bằng gdb
• Tích hợp các công cụ vào 1 môi trường duy nhất để hỗ trợ
việc lập trình dễ dàng hơn.
• IDE (Integrated Development Environment ) bao gồm 3 bộ
công cụ chính là:
• trình biên soạn (Editor)
• trình biên dịch (Compiler)
• trình gỡ rối (Debugger).
32
Sản phẩm IDE
• Trong Linux:
– Kdevelop
– Code::Blocks
• Trong Mac:
– Xcode
• Trong Window:
– Dev-C++,
– Turbo C++,
– Visual C++,
– etc
33
• 1998.
KDevelop • miễn phí.
• sử dụng nền tảng plug-in-> người dùng có thể bổ sung và gỡ bỏ plug để cài đặt chính
xác tính năng cần thiết
• tích hợp tính năng hỗ trợ hiện trạng do đó nhiều loại cài đặt plug-in có thể được sử
dụng trong những dự án cụ thể.
• hỗ trợ 15 ngôn ngữ lập trình cùng với nhiều tính năng hỗ trợ cho mỗi ngôn ngữ.
• tích hợp trình gỡ rối, hệ thống kiểm soát phiên bản, wizard ứng dụng, tính năng chia
code
34
Code::BLOCKS
• IDE C, C++ và Fortran miển phí.
• phần mềm mã nguồn mở với giấy phép GPLv3 (không có chi phí ẩn, không thu thập
thông tin cá nhân).
• phần mềm đa nền tảng (Cross-platform) có thể cài đặt trên Linux, Mac, Windows (sử
dụng wxWidgets).
• Thêm tính năng mở rộng thông qua các plugin.
35
Dev-C++
• IDE nguồn mở
• chỉ hỗ trợ nền tảng Windows
• Nhanh chóng tạo Windows, console, thư viện tĩnh và DLL.
• Chỉnh sửa và biên dịch các tệp tài nguyên.
• Hỗ trợ trình biên dịch dựa trên GCC.
• Có thể tùy chỉnh cú pháp tô sáng trình soạn thảo.
36
• Microsoft Visual Studio
Visual C++ • Dung lượng lớn, máy tính phải có cấu hình cao
• phần mềm trả phí.
• IDE hỗ trợ lập trình C/C++ tốt nhất
• Hỗ trợ đa nền tảng, đa hệ điều hành và nhiều ngôn ngôn ngữ lập trình.
• Hỗ trợ xây dựng, phát triển nhiều ứng dụng có quy mô lớn, an toàn và bảo mật cao.
• Hỗ trợ nhiều hệ quản trị cơ sở dữ liệu:SQL Server, oracle, Access…
• Cơ chế debug và phát hiện lỗi nhanh, tự động phát sinh code, hướng đối tượng…
• Hỗ trợ Git tích hợp, hơn 10k plugin được hỗ trợ và miễn phí
37
• lựa chọn hàng đầu cho người dùng sử
X code dụng hệ điều hành Mac.
• Hỗ trợ nhiều ngôn ngữ phổ biến
• Đây là một IDE hoàn toàn miễn phí
38
• 2008
SUBLIME TEXT • trình soạn thảo mã nguồn đa nền tảng
• Giao diện người dùng hiện đại
• kích thước nhỏ gọn.
• Điều hướng dễ dàng và nhanh chóng đến các từ, dòng và ký hiệu.
• Có thể tự động tạo một chỉ mục toàn dự án của mọi chức năng, phương thức
và lớp.
• API tùy biến cao và mạnh mẽ.
• Cú pháp tô sáng và tự động sửa lỗi.
39
Visual Studio Code •
•
2015
Miễn phí
• Đa nền tảng]
• phần mềm biên tập mã nguồn
• Hỗ trợ gỡ lỗi, tô sáng cú pháp, hoàn thành mã thông minh, đoạn mã, tái cấu trúc mã
và Git được nhúng.
• Có thể thay đổi chủ đề, phím tắt, tùy chọn và cài đặt các tiện ích mở rộng bổ sung
chức năng.
40
C PROGRAMMING
LANGUAGE
1
Nội Dung Khóa Học
1st Tổng quan lập trình máy tính
2nd Ngôn ngữ lập trình C
3rd Kiểu dữ liệu
4th Vào ra dữ liệu
5th Biểu thức trong ngôn ngữ C
6th Lệnh rẽ nhánh
7th Lệnh lặp (1)
8th Lênh lặp (2)
9th Hàm
10th Mảng
11th Con trỏ
12th Chuỗi
13th Cấu trúc dữ liệu
14th Vào ra với file
15th Final Exam
2
Câu hỏi bài cũ
https://forms.office.com/r/Gt8iM7FSBP
Kiểu dữ liệu
4
(Nhắc lại) Giá trị
5
(Nhắc lại) Biến
• Là vật chứa các giá trị - nơi mà giá trị được
lưu trữ
• Ví dụ
Biến Giá trị
10 cái kẹo
Bình này có
thể dùng để 50 g đường
chứa
3 cái bánh
v.v
6
1.1.Biến (variable)
• Biến là đối tượng lưu giữ dữ liệu và có thể thay đổi giá trị khi
chương trình được thực thi.
• Biến được đặt (allocate) trong các ô nhớ thuộc bộ nhớ chính của
máy tính.
• Số ô nhớ dành cho 1 biến phụ thuộc kiểu dữ liệu của biến.
• VD mỗi biến kiểu float chiếm 4 byte trong bộ nhớ.
• Tên biến phải được đặt theo quy tắc đặt tên.
Biến
• Trong C, 1 biến phải được khai báo bởi người sử dụng với 1 tên
định danh được đặt theo quy tắc:
• Biến không chỉ được khai báo với tên mà còn phải có kiểu
(biến của C luôn là biến có kiểu).
– VD:
int i, j;
char ch;
Đâu là biến?
#include <stdio.h>
int main()
{
int tong=0, dem=0, sopt, sosau;
printf(“Tong la %d\n",tong);
return 0;
}
Kết quả
#include <stdio.h>
int main()
{
int tong=0, dem=0, sopt, sosau;
printf(“Tong la %d\n",tong);
return 0;
}
Khai báo biến
• Một biến phải được khai báo trước khi sử dụng
• Cú pháp khai báo:
<KieuDuLieu> TenBien;
<KieuDuLieu> TenBien1, …, TenBien_N;
• Ví dụ:
//Khai báo biến x là một số nguyên 4 byte có dấu
int x;
//Khai báo các biến y, z là các số thực 4 byte
float y,z;
//Sau khi khai báo, có thể sử dụng
x = 3; y = x + 1;
11
Khai báo biến
• Sau khi khai báo, biến chưa có giá trị xác định.
• Biến cần được gán giá trị trước khi sử dụng
• C cho phép kết hợp khai báo và khởi tạo biến
KieuDuLieu TenBien = GiaTriBanDau;
KieuDuLieu Bien1 = GiaTri1, BienN = Gia_TriN;
• Ví dụ:
//Khai báo biến nguyên a và khởi tạo gia tri bằng 3
int a = 3;
//Khai báo biến thực x,y và khởi tạo giá tri bằng 5.0 và 7.6
float x = 5.0, y = 7.6;
12
1.2. Hằng
• Hằng là đại lượng có giá trị không đổi trong chương
trình.
• Giá trị hằng do người lập trình xác định.
• Các khái niệm
• Literals (Nghĩa đen)
• Constant (Biến hằng)
• Definition (macro)
• Các loại hằng
• Hằng số nguyên
• Hằng số thực
• Hằng ký tự
• Hằng chuỗi/xâu kỹ tự
13
Hằng số nguyên (int literal)
Trong C, hằng số nguyên có thể biểu diễn dưới các dạng:
cơ số 10, 8, 16
Hệ 10 Hệ 16 Hệ 8
14
Hằng số thực (floating point literal)
• Trong C, hằng số thực có thể biểu diễn dưới các dạng
• Dạng số thực dấu phẩy tĩnh
• Dạng số thực dấu phẩy động
15
Hằng ký tự (character literal)
• Hằng ký tự có thể biểu diễn theo hai cách
• Đặt ký hiệu của ký tự giữa hai dấu nháy đơn
• Dùng mã ASCII của ký tự:
• Số thứ tự của ký tự đó trong bảng mã ASCII
• Là số nguyên→tuân thủ quy tắc biểu diễn số nguyên
16
Hằng xâu ký tự (string literal)
• Hằng xâu kí tự được biểu diễn bằng dãy các kí tự trong
cặp dấu nháy kép.
• Ví dụ:
• “ngon ngu lap trinh C”
• “Tin hoc dai cuong”
• “Dai hoc Bach Khoa Ha Noi”
17
Khai báo biến hằng
• Dùng từ khóa const
• Cú pháp:
const Kiểu Tên_hằng = giá_trị;
• Ví dụ:
const int MAX_SINH_VIEN = 50;
const char CNTT[20] = “Cong nghe thong tin”;
const float DIEM_CHUAN = 23.5;
18
Khai báo hằng (dùng macro)
• Dùng chỉ thị #define
Không có dấu ;
• Cú pháp:
#define Tên_hằng Giá_trị
• Ví dụ:
#define MAX_SINH_VIEN 50
#define CNTT “Cong nghe thong tin”
#define DIEM_CHUAN 23.5
19
Khai báo hằng
Chú ý:
• Giá trị của các hằng phải được xác định ngay khi khai
báo.
20
Kiểu dữ liệu
21
Các kiểu dữ liệu
• Một kiểu dữ liệu là một tập hợp các giá trị mà một dữ liệu
thuộc kiểu dữ liệu đó có thể nhận được.
• Trên một kiểu dữ liệu, xác định một số phép toán đối với các
dữ liệu thuộc kiểu dữ liệu tương ứng.
22
Ví dụ kiểu số nguyên (int)
Một số phép toán được định nghĩa trên kiểu dữ liệu số
nguyên của C
Tên phép toán Ký hiệu Ví dụ
Đảo dấu -
Cộng;Trừ;Nhân + - *
Chia lấy nguyên / 17/3 → 5
Chia lấy phần dư % 17%3 → 2
So sánh > < >= <= == !=
Phép toán trên bit: & | ^ ~ << >> 3^17 →18
AND; OR; XOR; NOT, ~3 → -4
Shift,…
23
Các kiểu cơ bản
• Mọi biến trong C đều dùng để lưu trữ con số
– char : thường dùng lưu 1 số biểu diễn kí tự
– short : lưu 1 số nguyên nhỏ (thường 16-bits)
– int : lưu 1 số nguyên chuẩn (thường 32-bits)
– long : lưu 1 số nguyên lớn
– float : lưu 1số thực
– double : lưu 1 số thực với độ chính xác cao
Số nguyên
• Được lưu trữ dưới dạng số nhị phân trong bộ nhớ máy tính
– VD: 10100110 là số mấy dạng thập phân?
• Có nhiều kiểu số nguyên khác nhau trong C, kích thước lưu trữ
khác nhau:
char, short, int, long.
Cần chú ý tới kích thước của các loại số để tránh tràn số
trong các phép tính
Tìm giá trị phép tính
unsigned char a=128;
unsigned char b=128;
unsigned char c = a + b;
• Hãy cho biết giá trị của biến k? (biết char là biến
nguyên có dấu kích thước 1 byte).
Số thực
• Cũng có 2 kiểu số thực “ngắn” và “dài” trong ngôn
ngữ C tương ứng là: float và double
• Chỉ nên sử dụng float khi cần tiết kiệm không gian
bộ nhớ và bạn chỉ có các số thực giá trị nhỏ.
Kích thước số thực
Kiểu Cỡ lưu trữ Dãy giá trị Độ chính xác
• → 1 giá trị thực bất kì trong tự nhiên là x, máy tính sẽ tìm 1 giá trị
thực biểu diễn gần đúng nhất với x để lưu trữ nó.
VD:0.666666666 lưu với kiểu float sẽ là 0.666667
• → mọi phép tính số thực trong máy tính chỉ là phép tính “gần
đúng”.
• Chọn loại số thực có kích thước biểu diễn càng lớn thì các phép
tính có độ chính xác càng cao.
-> dùng kiểu double sẽ lưu được chính xác 0.666666666
Hằng số thực
• Sử dụng dấu chấm
– VD: 123.456, -123.456
• Sử dụng kí pháp khoa học (E)
– VD: 12.456e-2
• Ví dụ:
double x,y,z; x = 0.1;
y = 2.456E5;
z = 0;
Kí tự cũng là số!
• Các kí tự được lưu trữ như là 1 số nguyên nhỏ (1
byte) trong bộ nhớ
• Để lưu trữ kí tự ta dùng kiểu char
• Mỗi kí tự tương đương với 1 số duy nhất trong bảng
mã ASCII.
• Có 2 cách biểu diễn hằng kí tự trong C:
• kí tự trong cặp nháy đơn
• số mã ASCII của kí tự.
• VD: kí tự ‘A’ có vị trí 65 trong bảng mã ASCII. Do đó
2 khai báo sau là tương đương:
– char c = ‘A’;
– char c = 65;
Các kí tự điều khiển
• Trong bảng mã ASCII
• các kí tự có mã từ 32 (kí tự trắng) là kí tự hiển thị,
• 32 kí tự đầu tiên (mã 0 -> mã 31) được dụng làm kí tự điều
khiển
– VD: kí tự mã 13 điều khiển xuống dòng, mã 9 điều khiển tao 1
khoảng tab, …
• Các hằng kí tự điều khiển được biểu diễn bằng cách thêm
tiền tố ‘\’. Ví dụ:
#include <stdio.h>
#include <limits.h>
int main()
{
printf("Kich co luu tru cho so nguyen (int) la: %d \n", sizeof(int));
return 0;
}
In giá trị lớn nhất và nhỏ nhất kiểu float
#include <stdio.h>
#include <float.h>
int main() {
printf("Lop luu tru cho so thuc (float) la: %d \n", sizeof(float));
printf("Gia tri so thuc duong nho nhat la: %E\n", FLT_MIN );
printf("Gia tri so thuc duong lon nhat la: %E\n", FLT_MAX );
printf("Do chinh xac: %d\n", FLT_DIG );
return 0;
}
Các kiểu đơn
Tên kiểu Ý nghĩa Kích thước Miền dữ liệu
char Kí tự; 1 byte -128 127
Số nguyên có dấu
41
Các kiểu kết hợp
Với số nguyên, thêm từ khóa unsigned để chỉ ra số không dấu
Kiểu dữ liệu Ý nghĩa Kích thước Miền dữ liệu
unsigned char Số nguyên 1 byte 0 255
không dấu
42
VÀO/RA DỮ LIỆU
SOICT-HUST
Nội Dung Khóa Học
1st Tổng quan lập trình máy tính
2nd Ngôn ngữ lập trình C
3rd Kiểu dữ liệu
4th Vào ra dữ liệu
5th Biểu thức trong ngôn ngữ C
6th Lệnh rẽ nhánh
7th Lệnh lặp (1)
8th Lênh lặp (2)
9th Hàm
10th Mảng
11th Con trỏ
12th Chuỗi
13th Cấu trúc dữ liệu
14th Vào ra với file
15th Final Exam
2
Nội Dung Bài Học
• Xuất dữ liệu
• Cú pháp
• Các đặc tả dữ liệu in
• Khuôn dạng xuất dữ liệu
• Nhập dữ liệu
3
Vào ra dữ liệu
• Để đọc và xuất dữ liệu trong C, ta sử dụng 2 hàm
thư viện cơ bản có trong tệp tiêu đề <stdio.h>
• printf() – in ra màn hình,
• có thể chấp nhận tham số là biến để in giá trị
của nó
• scanf() – lấy giá trị từ thiết bị đầu vào chuẩn
và gán nó cho các biến
Hàm in dữ liệu (ra màn hình)
• printf()
• Mục đích
5
Cú pháp
printf(xau_dinh_dang [, DS_tham_so]);
• Xau_dinh_dang: Là một xâu qui định cách thức hiển thị
dữ liệu ra màn hình máy tính.
• Bao gồm các nhóm kí tự định dạng
• Nhóm kí tự định dạng thứ k xác định quy cách hiển thị tham
số thứ k trong DS_tham_số
• Số lượng tham số trong DS_tham_số bằng số lượng nhóm các kí tự
định dạng trong xâu_định_dạng.
• DS_tham_so: Danh sách các biến/biểu thức sẽ được hiển
thị giá trị lên màn hình theo cách thức được qui định
trong xau_dinh_dang.
6
Cú pháp (tiếp)
printf(xau_dinh_dang [, DS_tham_so]);
• Cách sử dụng đơn giản nhất: chỉ để in 1 chuỗi
printf ("Hello world!");
Kết quả: Hien thi mot bieu thuc nguyen 10 va mot so thuc
1.234000
8
printf()
• Chuỗi định dạng trong lệnh
printf("<chuỗi định dạng>", <ds biến hoặc giá trị>);
10
Các ký tự định dạng
Ký tự Kiểu dữ liệu Kết quả
%i, %d int, char Số thập phân
%o int, char Số hệ 8
(không có 0 đằng trước)
%x %X int, char Số hệ hexa
(chữ thường/chữ hoa)
%u unsigned int/char Số thập phân
11
Các ký tự định dạng
Ký tự Kiểu dữ liệu Kết quả
%ld, %li long Số thập phân
%lo long Số hệ 8
(không có 0 đằng trước)
%lx, %LX long Số hệ hexa
(chữ thường/chữ hoa)
%lu unsigned long Số thập phân
Nhận xét: Với kiểu long, thêm ký tự l ngay sau dấu %
12
Các ký tự định dạng
Ký tự Kiểu dữ liệu Kết quả
%f float/double Số thực dấu phẩy tĩnh
%e, %E float/double Số thực dấu phẩy động
%c int, char Kí tự đơn lẻ
%s char [] Hiển thị xâu kí tự kết
thúc bởi ‘\0’
%% Hiển thị kí tự %
13
In giá trị theo nhiều định dạng
#include <stdio.h>
int main()
{
char c = ‘A';
return 0;
}
Output: In c theo ki tu la A
In c theo so nguyen la 65
In c theo hexa la 41
In theo khuôn dạng
• Để tạo khuôn in đẹp ta sử dụng các kí tự
điều khiển như ‘\n’, ‘\t’, …
• Có thể sử dụng thêm các lựa chọn để tạo
khuôn cho giá trị in như sau:
% [-] [fwidth] [.p] X
– [fwidth] độ rộng để in giá trị
– [-] căn lề trái (mặc định căn lề phải).
– [.p] số ô dành để in số sau dấu chấm.
Ví dụ
• printf("\n%3d %15s %-3c", 1, "nguyen van a", 'g');
• printf("\n%3d %15s %3c", 2, "tran van b", 'k');
1 nguyen van ag
2 tran van b k
16
Ví dụ
Giá trị Đặc tả In ra
42 %6d | 42|
42 %-6d |42 |
'z' %3c | z|
'z' %-3c |z |
2.71828 %10f | 2.71828|
2.71828 %10.2f | 2.71|
2.71828 %-10.2f |2.71 |
2.718 %.4f |2.7180|
2.71828 %10e |2.71828e+00|
"printf" %s |printf|
"printf" %10s | printf|
In các ký tự đặc biệt
• In các chữ cái
20
Nội Dung Bài Học
• Xuất dữ liệu
• Nhập dữ liệu
• Cú pháp
• Định dạng dữ liệu nhập
21
Hàm nhập dữ liệu
• scanf()
• Mục đích
• Dùng để nhập dữ liệu từ bàn phím
• Ký tự đơn lẻ
• Chuỗi ký tự
• Số nguyên: hệ 10, 8, 16
• Số thực
Dấu phẩy tĩnh; Dấu phẩy động
• Cú pháp
scanf(xau_dinh_dang[,DS_dia_chi]);
22
Cú pháp
scanf(xau_dinh_dang [, DS_dia_chi]);
• Xau_dinh_dang: Gồm các ký tự được qui định cho từng
loại dữ liệu được nhập vào.
• Ví dụ: dữ liệu định nhập kiểu nguyên thì xâu định dạng là :
%d
• DS_dia_chi: bao gồm địa chỉ của các biến (toán tử &),
phân tách nhau bởi dấu phẩy (,)
• Phải phù hợp với các kí tự định dạng trong
xau_dinh_dang về số lượng, kiểu, thứ tự
23
scanf()
• Ví dụ
int i; char ch; float x;
scanf ("%d%c%f", &i, &ch, &x);
– Câu lệnh này cho phép chương trình đợi người sử dụng
nhập các giá trị số nguyên, kí tự và số thực
– Phải truyền địa chỉ của biến nhận giá trị cho hàm scanf().
Định dạng nhập
• Các kí tự định dạng nhập không hoàn toàn
giống cho xuất mà thương có tính chính xác hơn
%c – giá trị nhập là kí tự
%d – giá trị nguyên kiểu int
%ld – giá trị nguyên kiểu long
%x – giá trị nguyên dạng hexa
%f – giá trị thực kiểu float
%lf – giá trị thực kiểu double
%s – chuỗi kí tự
Ví dụ #include <conio.h>
#include <stdio.h>
void main(){
// khai bao bien
int a; float x;
char ch; char str[30];
// Nhap du lieu
printf(“Nhap vao mot so nguyen:”);
scanf(“%d”,&a);
printf(“\nNhap vao mot so thuc:”);
scanf(“%f”,&x);
printf(“\n Nhap vao mot ki tu:”);
scanf(“%c”,&ch);
26
Ví dụ
printf(“\nNhap vao mot xau ki tu:”);
scanf(“%s”,str);
27
Ví dụ→Kết quả thực hiện
28
Ví dụ: tính diện tích hình tròn
/* Chương trình tính diện tích hình tròn */
#include <stdio.h>
int main()
{
float r, s;
s = 3.14*r*r;
printf(“Dien cua hinh tron s=%f", s);
return 0;
}
Ví dụ: Đọc 2 số nguyên, đưa ra tổng,
hiệu, tích…
#include <stdio.h>
int main() {
int A, B;
printf("Nhap vao 2 so nguyen : "); scanf("%d %d“,&A,&B);
printf("\n");
printf("Tong %d + %d = %d \n", A, B, A + B);
printf("Hieu %d - %d = %d\n", A, B, A - B);
printf("Tich %d x %d = %d\n", A, B, A * B);
printf("Thuong %d / %d = %.3f\n", A, B, (float)A / B);
printf("Chia nguyen %d / %d = %d\n", A, B, A / B);
printf("Chia du %d %% %d = %d\n", A, B, A % B);
printf("\n");
return 0;
}
30
Ví dụ: Đọc 2 số nguyên, đưa ra tổng,
hiệu, tích…
31
Ghi chú
• Thông tin được gõ vào từ bàn phím, được lưu ở vùng
đệm trước khi được xử lý bởi hàm scanf()→Hàm scanf()
đọc từ vùng đệm
#include <stdio.h>
int main(){
int a, b;
scanf("%d",&a);
scanf("%d",&b);
printf ("%d %d", a, b);
return 0;
}
32
Lỗi thường gặp
• Tìm lỗi trong đoạn chương trình sau
float a, b, c;
scanf("%f", a);
scanf("%d", &b);
scanf("%f", &c);
scanf("%f", &d);
Ví dụ nhập xuất số nguyên khác kiểu
#include <stdio.h>
int main(){
int i ;
scanf("%o", &i);
printf("%d", i);
return 0;
}
Input: 70
Output: 56
Quét dữ liệu
• Giá trị lưu vào các biến được quét dựa trên dữ liệu nhập của
người sử dụng.
• Quá trình quét được thực hiện tuần tự và có thể dừng nếu có lỗi
khi quét.
• Ví dụ:
int i = 0;
char ch = '*';
float x = 0;
scanf("%d%c%f",&i,&ch,&x); • Nếu nhập : 1x2.3
printf ("%d %c %f\n",i,ch,x); • Kết quả in: 1 x 2.300000
• Khi gặp các dấu phân cách như tab, xuống dòng hay dấu
cách (space bar), scanf() sẽ hiểu là kết thúc nhập dữ liệu
cho một số
36
Các quy tắc cần lưu ý (tiếp)
• Khi đọc kí tự
• mọi kí tự có trong bộ đệm của thiết bị vào chuẩn đều là
hợp lệ, kể cả các kí tự tab, xuống dòng hay dấu cách
37
Bỏ qua kí tự
• Trong định dạng của xâu nhập ta có thể
chỉ ra một số kí tự cần bỏ qua khi quét
• Ví dụ:
scanf("%d-%d-%d", &day, &month, &year);
int n;
printf(“n = ”);
if (scanf(“%d", &n) != 1)
printf(“Không nhập được giá trị cho n”);
BIỂU THỨC TRONG
NGÔN NGỮ C
huydq@soict.hust.edu.vn
Nội Dung Chính
• Biểu thức
• Toán tử
2
Biểu thức
• Kết hợp các giá trị bằng toán tử hoặc gọi hàm
để tạo giá trị mới
• Giá trị trả về luôn có kiểu xác định
• Các toán tử có thể được phân loại
– theo ngôi (1 hoặc 2 toán hạng)
– theo chức năng (toán học, logic, …)
Mục đích sử dụng
• Làm vế phải của lệnh gán.
• Làm toán hạng trong các biểu thức khác.
• Làm tham số thực sự trong lời gọi hàm.
• Làm biểu thức kiểm tra trong các cấu trúc điều khiển
• Cấu trúc lặp: for, while, do while.
• Cấu trúc rẽ nhánh: if, switch.
4
Các loại biểu thức
5
Biểu thức số học
• Là biểu thức mà giá trị của nó là các đại lượng số học
(số nguyên, số thực).
• Sử dụng các toán tử là các phép toán số học (+,-,*,/…)
• Các toán hạng là các đại lượng số học (hằng số, biến, biểu
thức khác).
6
Ví dụ biểu thức
1 + 2 * 3 - 4 / 5
= 1 + (2 * 3) - (4 / 5)
6.2
Ví dụ (tiếp)
1 + 2 * 3 - 4 / 5 =
1 + (2 * 3) - (4 / 5)
1 + 2 * 3 - 4 / 5 =
1 + (2 * 3) - (4 / 5)
7
= 0
Ví dụ (tiếp)
1 + 2 * 3 - 4.0 / 5
= 1 + (2 * 3) - (4.0 / 5)
= 1 + 6 - 0.8
= 6.2
Biểu thức quan hệ
• Là những biểu thức có sử dụng các toán tử quan hệ như lớn hơn,
nhỏ hơn, khác nhau…
• Chỉ có thể trả về 1 trong 2 giá trị logic Đúng (TRUE) hoặc Sai
(FALSE)
• Ví dụ
11
Biểu thức logic
• Là biểu thức trả về các giá trị logic Đúng/Sai
• Các phép toán logic gồm có
• AND VÀ logic, sử dụng toán tử &&
• OR HOẶC logic, sử dụng toán tử ||
• NOT PHỦ ĐỊNH, sử dụng toán tử !
• Biểu thức quan hệ là trường hợp riêng của biểu thức logic.
• Biểu thức logic cũng trả về một giá trị số học 0/1
12
Biểu thức logic →Ví dụ
13
Dùng int như lôgic
• Trong C, các giá trị lôgic được biểu diễn bằng
số nguyên
– Giá trị nguyên 0 là sai.
– Giá trị nguyên khác 0 là đúng (thường dùng số 1)
• Biểu thức
• Toán tử
15
Các toán tử chính
• Toán tử số học
• Toán tử quan hệ
• Toán tử logic
• Toán tử logic bit
• Toán tử gán
16
Các toán tử số học
Toán Ý nghĩa Kiểu dữ liệu của toán Ví dụ
tử hạng (int a = 12; float x=3.0)
- Đảo dấu float, double, int, long,.. -12, -12.34, - a, - x
(Số nguyên hoặc thực)
+ Cộng float, double, int, long,.. 12 + x
- Trừ float, double, int, long,.. 12.0 - x
* Nhân float, double, int, long,.. 12 * 3.0
(Số nguyên hoặc thực) 12 * 3
/ Chia Nếu có ít nhất 1 toán 17.0/3.0 → 5.666667
hạng là số thực 17/3.0 → 5.666667
17.0/3 → 5.666667
/ Chia lấy thương Số nguyên int, long,.. 17/3 → 5
% Chia lấy số dư Số nguyên: int, long,.. 17%3 → 2
17
Các toán tử quan hệ
<, >, <=, >=, ==, !=
• Dùng cho phép so sánh giá trị 2 toán hạng
• Kết quả phép so sánh là một số nguyên
• 1 nếu quan hệ có kết quả là đúng,
• 0 nếu quan hệ có kết quả sai
• Ví dụ:
• 6 > 4 → Trả về giá trị 1
• 6 < 4 → Trả về giá trị 0
• int b = (x !=y);
Nếu x và y khác nhau, biểu thức đúng và b mang giá trị 1. Ngược lại
biểu thức sai và b mang giá trị 0
18
Toán tử lôgic
20
Ví dụ
Tránh nhầm
lẫn với và bit
(&)
Tránh nhầm
lẫn với hoặc
5 && 4 → 1 bit (|)
Tránh nhầm
lẫn với đảo
bit (~) 1 || 4 → 1
! 0 → 0
! 0 || 0 && 2 → 1
“Ngắn mạch”
• Không nhất thiết phải sử dụng tất cả các toán hạng để
đánh giá một biểu thức lôgic, chỉ cần đánh đến khi giá trị
biểu thức được xác lập
1 || 2
0 || 1 || 2
1 && 0 && -1
Ví dụ toán tử so sánh
Tránh nhầm
lẫn với phép
gán (=)
3 == 4 → 0
3 != 4 → 1
3 < 4 → 1
int main()
{
int score; Giá trị trả về
luôn là 1
scanf("%d", &score);
if ( score == 9 || 10 )
{
printf(“Xuat sac\n");
}
return 0; Giá trị trả về là
0 hoặc 1
}
Lỗi thường gặp (tiếp)
#include <stdio.h>
int main()
{
int score;
scanf("%d", &score);
if ( score == 9 || score == 10 )
{
printf(“Xuat sac\n");
}
return 0;
}
Lỗi thường gặp (tiếp)
#include <stdio.h>
int main()
{
int score; Giá trị trả về
luôn là 1
scanf("%d", &score);
int main()
{
int score;
scanf("%d", &score);
28
Toán tử trên bit
• Một biểu thức chỉ sử dụng các toán tử trên bit không
phải là biểu thức lôgic.
• Kết quả của biểu thức này là một số nguyên bất kì
5 & 4 → 4
1 | 4 → 5
~0 → 0xFFFF
Toán tử trên bit (tiếp)
char Op1 = 83, Op2 = -38, Op = 3;
char r = Op1 & Op2; char r = Op1 | Op2;
01010011 01010011
11011010 11011010
r = 0 1 0 1 0 0 1 0 → (82) r = 1 1 0 1 1 0 1 1 → (-37)
char r = Op1 ^ Op2; char r = ~ Op2;
01010011 11011010
11011010 r = 0 0 1 0 0 1 0 1 → (37)
r = 1 0 0 0 1 0 0 1 → (-119)
unsigned char r = Op1 | Op2; r = 1 1 0 1 1 0 1 1 → 219
30
Toán tử trên bit (tiếp)
char Op1 = 83, Op2 = -38, Op = 3;
char r = Op1 >> Op;
01010011
r = 0 0 0 0 1 0 1 0 → (10)
char r = Op2 >> Op; unsigned char Op =218;
11011010 unsigned char r =Op >> 3;
r =1 1 1 1 1 0 1 1 → (-5) 11011010
r =0 0 0 1 1 0 1 1 → (27)
char r = Op2 << 2;
r = 0 1 1 0 1 0 0 0 →(104)
(unsigned) int r = Op2<<2 →?
31
Toán tử gán
Biến = Biểu_thức;
32
Toán tử gán
• Gán (=) cũng là một toán tử. Vì vậy sử dụng toán tử
này tạo ra một biểu thức và trả về giá trị
• Kết quả của biểu thức gán là giá trị bên phải của
biểu thức
• Ví dụ:
(x = 4) → 4
(y = 0) → 0
• Có thể tạo 1 biểu thức với một chuỗi toán tử gán
x=y=z=4
Lỗi thường gặp (tiếp)
#include <stdio.h>
int main()
{
int score; Nhầm với
phép gán
scanf("%d", &score);
int main()
{
int score;
scanf("%d", &score);
+= x += 5 x=x+5
-= x -= 5 x=x-5
*= x *= 5 x=x*5
/= x /= 5 x=x/5
%= x %= 5 x=x%5
Toán tử tăng giảm
• ++ là toán tử tăng
++i tương đương với i = i + 1
• -- là toán tử giảm
--j tương đương với j = j - 1
• Có 2 dạng viết: tiền tố (++i) và hậu tố (i++)
• Chúng khác nhau ở giá trị trả về của biểu thức.
Ví dụ nếu i = 5
– Tiền tố trả về giá trị sau khi đã cộng, (++i) → 6
– Hậu tố trả về giá trị trước khi cộng, (i++) → 5
– Trong cả hai trường hợp giá trị của i đều tăng lên 1
Toán tử lấy địa chỉ
&Tên_biến
• Biến thực chất là một vùng nhớ của máy tính được đặt
tên → tên của biến
• Mọi ô nhớ trên bộ nhớ máy tính đều được đánh địa chỉ.
→ Mọi biến đều có địa chỉ 1
.
..
..
. 157
a D6 158
07 159
• Ví dụ: .
160
.
.
short int a = 2006;
&a là địa chỉ của ô nhớ chứa giá trị biến a
38
Toán tử điều kiện
• Có thể viết một biểu thức mà giá trị của nó phụ
thuộc vào một điều kiện
int max,a,b;
…
max = ( a > b ) ? a : b;
Ép kiểu
• Phép gán chỉ thực hiện trên biến và giá trị có cùng kiểu
• C chuyển kiểu tự động cho phép gán nếu sự chuyển kiểu
đó không làm mất thông tin.
char → int → long int → float → double → long double
• Ví dụ chuyển từ int về float
int a;
float f;
f = a; /* OK */
a = f; /* KO */
• Trong trường hợp bị mất thông tin ta phải thực hiện ép
kiểu. Ví dụ nếu chuyển từ float về int
a = (int) f;
Thứ tự ưu tiên các toán tử
Mức Toán tử Chức năng Chiều
1 -> . [ ] () ++ hậu tố --hậu tố Lựa chọn, chỉ số… →
2 ++ -- ~ ! + - * & () sizeof Toán tử 1 ngôi, ép kiểu,…
Toán tử số học lớp nhân →
42
Ví dụ
const int N=10; int a= 3, b=4, c;
float S= 0.0; c = a++ * ++b;
int b;
S = N/3 +1;
a= ? b= ? c= ?
b=(S>4);
S= ? b = ?
int k ,num=30;
k = num>5 ? (num <=10 ? 100 : 200): 500;
k=?
43
Ví dụ
const int N=10; int a= 3, b=4, c;
float S= 0.0; c = a++ * ++b;
int b;
S = N/3 +1;
a=4 b=5 c=15
b=(S>4);
S= 4 b = 0
int k ,num=30;
k = num>5 ? (num <=10 ? 100 : 200): 500;
k=200
44
Ví dụ
7+5&&4<2+3-2/3||5>2+1
(7+5)&&4<2+3-(2/3)||5>(2+1)
12 &&4<(2+3-0) ||(5>3)
12 &&(4<5)||1
(12&&1)||1
1||1
= 1
C PROGRAMMING
LANGUAGE
1
Nội Dung Khóa Học
1st Tổng quan lập trình máy tính
2nd Ngôn ngữ lập trình C
3rd Kiểu dữ liệu
4th Vào ra dữ liệu
5th Biểu thức trong ngôn ngữ C
6th Lệnh rẽ nhánh
7th Lệnh lặp (1)
8th Lênh lặp (2)
9th Hàm
10th Mảng
11th Con trỏ
12th Chuỗi
13th Cấu trúc dữ liệu
14th Vào ra với file
15th Final Exam
2
Cấu trúc điều khiển
• Lệnh rẽ nhánh
• if
• if/else
• Lệnh lựa chọn switch
Lệnh if
Cú pháp:
if ( <biểu thức điều kiện> ) <câu lệnh>
true
Biểu_thức_điều Lệnh_1
_kiện?
false
Lệnh_kế_tiếp
Lưu Đồ Khối if
Nếu (number %2 != 0) thì in_ra(“số lẻ”);
lệnh_kế_tiếp;
false
Ví dụ:
3 - 4 là true
Lệnh_kế_tiếp
Ví dụ
• Nhập vào một số nguyên rồi kiểm tra có phải là số lẻ
#include <stdio.h>
int main()
{
int number;
return 0;
}
Lỗi thường gặp
Nhầm toán tử
so sánh == Không có
dấu ; ở đây
if (number % 2 = 0);
{
printf(“%d\n”, number);
printf(“La so chan");
}
• Lỗi logic:
• Ảnh hưởng khi thực hiện chương trình
• Không nguy hiểm: chương trình chạy nhưng cho ra kết quả
không chính xác
• Nguy hiểm: chương trình kết thúc bất thường
Lệnh đơn và Lệnh ghép (compound)
11
Lệnh ghép/Khối lệnh
• 1 khối lệnh bao gồm các câu lệnh đặt trong cặp dấu { }
{
lệnh_1;
lệnh_2;
....
lệnh_n;
}
{
V.d. number = number + 1;
printf("%d\n", number);
}
Cấu trúc lồng nhau
• Trong lệnh ghép có thể chứa lệnh ghép khác
{
lệnh;
{
lệnh;
{
lệnh;
....
}
…..
}
…..
}
13
Cấu trúc lồng nhau
• Có thể khai báo biến trong khối lệnh
{//Khai báo đối tượng cục bộ trong khối
lenh;
{//Khai báo đối tượng cục bộ trong khối
lenh;
...
} Nếu các đối tượng được
… khai báo trùng tên nhau ?
}
14
Ví dụ
15
Ví dụ→Kết quả thực hiện
16
Lệnh else
if ( <điều kiện> )
<câu lệnh 1>
else
<câu lệnh 2>
int main()
{
int number;
if (number % 2 != 0)
printf("%d la so le\n", number);
else
printf("%d la so chan\n", number);
return 0;
}
Ví dụ: So sánh 2 số thực
20
Ví dụ: So sánh 2 số thực được nhập vào
if(a < b)
max = b;
max = a > b ? a : b;
else
max = a;
21
Lỗi thường gặp
if (number % 2 != 0)
Không có
dấu ; ở đây {
printf(“%d\n”, number);
printf(“La so le");
};
else
{
printf(“%d\n”, number);
printf(“La so chan");
}
Lệnh if lồng (else-if)
Ví dụ
if (expr1) if (ch >= ’a’ && ch <= ’z’)
statement1 {
printf(“%c la chu thuong”, ch);
else if (expr2) }
else if (ch >= ’A’ && ch <= ’Z’)
statement2 {
else if (expr3) printf(“%c la chu hoa”. ch);
}
statement3 else if (ch >= ’0’ && ch <= ’9’)
{
else printf(“%c la chu so”, ch);
statement4 }
Cấu trúc lệnh if lồng được sử dụng khi có sự lựa chọn với nhiều điều kiện
khác nhau
Cấu trúc if / if… else lồng nhau
Cấu trúc if.. và if …else có thể lồng nhau
– Khi đó else sẽ tương ứng với if (phía trên,
chưa có else) gần nhất
if (đ/k_1) if (đ/k_1)
if (đ/k_2) { if (đ/k_2)
lệnh_1; lệnh_1;
else }
lệnh_2; else
lệnh_2;
24
Cấu trúc if / if… else lồng nhau →Ví dụ
int a, b, c = 10;
if (a==0) a ≠ 0, b=? →c=
if (b == 0) 10
c = 20; a=0, b=0 →c = 20
else
c = 30; a=0, b ≠ 0 →c =
30
if (a==0){ a ≠ 0, b=? →c=
if (b == 0) 30
c = 20; a=0, b=0 →c = 20
}else
c = 30; a=0, b ≠ 0 →c=
10
25
Bài tập
• Viết chương trình tính số ngày của một tháng.
• Giải thuật
if (tháng 4, 6, 9, 11)
output “30 ngày”
else if (tháng 2)
output “28 hoặc 29 ngày”
else
output “31 ngày”
#include <stdio.h>
int main() {
unsigned char thang;
printf("Nhap vao thang:");
scanf("%d",&thang);
if (thang == 4 || thang == 6 || thang == 9 || thang == 11)
printf("30 ngay");
else if (thang == 2)
printf("28 hoac 29 ngay");
else if (thang > 0 && thang < 13)
printf("31 ngay");
else printf("Du lieu khong hop le");
return 0;
}
Cấu trúc điều khiển
• Lệnh rẽ nhánh if
• Lệnh lựa chọn switch
Lệnh lựa chọn switch
switch (bieu_thuc)
{
case gia_tri_1: lenh_1; [break];
case gia_tri_2: lenh_2; [break];
…
[default: lenh_n+1; [break];]
}
Câu_lệnh_tiếp
29
Lệnh switch
• Một lệnh đa lựa chọn dựa trên các giá trị nguyên
– Giống như khi sử dụng cấu trúc lệnh if lồng
• Biểu thức phải có giá trị nguyên
• Khi thực hiện giá trị của biểu thức được tính và trường
hợp case có giá trị khớp với biểu thức sẽ được thực
hiện
• Nếu không có case nào tương ứng, tập lệnh tuỳ chọn
default được thực hiện
Lệnh lựa chọn switch
Tính g/trị
Biểu thức
Câu_lệnh_tiếp
31
sử dụng break
• Khi một case của lệnh switch được tìm thấy, các lệnh
được thực hiện bắt đầu từ điểm này
• Nó tiếp tục thực hiện tất cả các lệnh tiếp theo trừ khi gặp phải một
break
• Lệnh break làm chương trình nhảy lập tức sang câu lệnh sau lệnh
switch
int a = 1;
switch ( a ) {
case 1: Output:
printf("a=1\n"); a=1
case 2: a=2
printf("a=2\n");
break;
case 3:
printf("a=3\n");
}
Cấu trúc lựa chọn switch→Ví dụ 1
Lập trình đọc từ bàn phím một số
nguyên 1N 10 và đưa ra từ tiếng Anh
tương ứng
33
Cấu trúc lựa chọn switch→Ví dụ 1
34
Cấu trúc lựa chọn switch→ Thực hiện
35
Cấu trúc lựa chọn switch→Ví dụ 2
Nhập vào số nguyên không âm, đưa
ra ngày trong tuần tương ứng (theo
số dư khi chia cho 7).
36
Cấu trúc lựa chọn switch→Ví dụ 2
37
Cấu trúc lựa chọn switch →Thực hiện
39
Cấu trúc lựa chọn switch
Có thể sử dụng đặc điểm Không có lệnh
break chương trình sẽ tự động chuyển xuống
thực hiên các câu lệnh tiếp sau để viết chung
mã lệnh cho các trường hợp khác nhau
nhưng được xử lý như nhau
40
Ví dụ 3
printf(“Yes/No (Y/N)?”);
scanf(“%c”, &ch)
switch (ch)
{
case 'y' :
case 'Y' :
printf(“say yes”);
break;
default :
printf(“say no”);
}
Ví dụ 4
• Xác định học lực dựa trên điểm kiểm tra
switch (diem) if (diem==9||diem==10)
{ {
case 9: printf(“Loai gioi\n");
case 10: }
printf(“Loai gioi\n"); else if (diem==7||diem==8)
break; {
case 7: printf(“Loai kha\n");
case 8: }
printf(“Loai kha\n"); else if (diem==5||diem==6)
break; {
case 5: printf(“Loai TB\n");
case 6: }
printf(“Loai TB\n"); else
break; {
default: printf(“Loai yeu\n");
printf(“Loai yeu\n"); }
}
Bài tập
43
Cấu trúc lựa chọn switch→ Ví dụ
44
Cấu trúc lựa chọn switch→ Thực hiện
45
Cấu trúc lựa chọn switch→Lưu ý
• Giá trị của biểu thức trong cấu trúc switch
phải là số nguyên (kiểu đếm được)
– Phải có kiểu dữ liệu là char, int, long
• Các giá trị sau từ khóa case (gia_tri_1,
gia_tri_2,.. ) cũng phải là số nguyên
46
Bài tập
1. Viết chương trình nhập 2 (hoặc 3) số
nguyên và tìm giá trị lớn nhất của chúng.
2. Viết chương trình để giải phương trình
ax+b=0 với a, b là các hệ số được nhập
vào từ bàn phím.
Ví dụ: Giải phương trình ax + b = 0
48
C PROGRAMMING
LANGUAGE
1
Nội Dung Khóa Học
1st Tổng quan lập trình máy tính
2nd Ngôn ngữ lập trình C
3rd Kiểu dữ liệu
4th Vào ra dữ liệu
5th Biểu thức trong ngôn ngữ C
6th Lệnh rẽ nhánh
7th Lệnh lặp (for…)
8th Lênh lặp (while,do…while)
9th Hàm
10th Mảng
11th Con trỏ
12th Chuỗi
13th Cấu trúc dữ liệu
14th Vào ra với file
15th Final Exam
2
Vòng lặp (loop)
• Là một dạng của vòng lặp while với các thành phần khởi
tạo và cập nhật được chỉ ra trong câu lệnh
• Các thành phần trong câu lệnh for là tuỳ chọn. Khi điều
kiện lặp không được chỉ rõ thì nó được lấy giá trị ngầm
định là đúng.
• Cập nhật luôn thực hiện sau câu lệnh của vòng lặp
Cấu trúc lặp for
Dùng để thực hiện nhiều lần một công việc
for([b.thuc_1];[b.thuc_2];[b.thuc_3]) Lệnh;
• b.thuc_1: Khởi tạo giá trị ban đầu cho vòng lặp
• b.thuc_2: Điều kiện tiếp tục vòng lặp
• b.thuc_3: Thay đổi biến điều khiển của vòng lặp
• Lệnh: Có thể là lệnh đơn lệnh kép hoặc lệnh rỗng
5
Lưu đồ
6
Sử dụng
int i;
for(i = 0; i < 100; i++) Câu_lệnh;
int i;
for(i = 0; i < 100; i+=2)Câu_lệnh;
int i;
for(i = 100; i > 0; i--) Câu_lệnh;
7
Ví dụ 1
• Hãy đưa ra màn hình các số
nguyên dương nhỏ hơn 10.
• Cách làm: có 9 số nguyên dương
nhỏ hơn 10 là 1, 2, 3, 4, 5, 6, 7,
#include <stdio.h>
8 và 9. #include <conio.h>
• Để in 9 số nguyên dương này ta void main() {
cần sử dụng một biến nguyên int i;
đặt tên là i. for (i = 1;i <= 9;i++)
• Bước 1: gán cho i giá trị bằng 1.
• Bước 2: đưa ra màn hình giá trị
printf(“%5d”,i);
của i. // ta dành 5 vị trí để in mỗi số
• Bước 3: tăng giá trị của i thêm 1 đơn getch();
vị. }
• Bước 4: kiểm tra nếu giá trị của i ≤ 9
thì quay về bước 2, nếu giá trị của
i > 9 thì chuyển sang bước 5. }
• Bước 5: kết thúc.
LƯU Ý
➢Theo chuẩn C89: biến phải được khai báo trước khi sử dụng
trong vòng for.
int i;
for (i = 0; i < n; i++)
• output tổng
Tìm các số nguyên lẻ nhỏ hơn 100 (1)
11
Tìm các số nguyên lẻ nhỏ hơn 100 (2)
12
Nhập n và tính n!
13
Nhập n và tính tổng S = 1+1/2+..+1/n
14
Tìm số 3 chữ số thỏa mãn abc=a3+b3+c3
15
Tìm số 3 chữ số thỏa mãn abc=a3+b3+c3
16
Chú ý
Không nhất thiết phải có đầy đủ các
thành phần trong vòng lặp for
17
Chú ý
1. Biểu thức khởi tạo
char c; int i=0; Hello world
for( ; (c=getchar())! = '\n’ ; i++) Hello world
putchar(c); So ky tu: 11
printf(“\nSo ky tu: %d”,i);
2. Biểu thức điều khiển
for(i=0 ; ; c=getchar(), i++) Hello world
if(c==‘\n’) break;
printf(“\nSo ky tu: %d”,i); So ky tu: 12
3. Thân vòng lặp
for(i=0 ; getchar() != ‘\n’, i++); Hello world
printf(“\nSo ky tu: %d”,i); So ky tu: 11
18
Lỗi thường gặp
for (dem=0; dem<sopt; )
{
scanf("%d", &sosau);
Biến đếm không được
cập nhật sau mỗi lần lặp
tong += sosau;
}
• Ví dụ:
for (i=0, j=100; i<=j; i++,j--)
printf(”(%d, %d\n)”, i, j);
1
ĐIỀU KHIỂN LẶP (2)
while và do … while
Lệnh while
• Kết thúc vòng lặp khi điều kiện trở nên sai (có
giá trị bằng 0)
Lưu đồ
Lệnh
Biểu thức != 0
Đúng
Sai
4
Ví dụ
• Đọc một tập số nguyên và in
tổng của chúng #include<stdio.h>
int main()
• tổng = 0 {
• đếm = 0 int tong=0, dem=0, sopt, sosau;
printf(“So phan tu trong day so:");
• input sốpt
scanf("%d", &sopt);
Không có
• while (đếm < sốpt) do while (dem < sopt) do ở đây
{
{
scanf("%d", &sosau);
• input sốsau
tong += sosau; dem++;
• cộng sốsau vào tổng }
thêm 1 vào đếm printf(“Tong la %d\n",tong);
} return 0;
• output tổng }
Ví dụ (tiếp)
#include <stdio.h>
int main()
{ sopt sosau tong dem
int tong=0, dem=0, sopt, sosau;
printf(“Tong la %d\n",tong);
return 0;
}
Lỗi thường gặp
while (dem < sopt)
scanf("%d", &sosau); Chỉ có lệnh scanf là
tong += sosau; được lặp nhiều lần
dem++;
• xác định kết thúc của 1 dãy số được nhập thông qua
dấu hiệu EOF trả về bởi hàm scanf.
Kết quả
10
So sánh while và for
#include <stdio.h> #include <stdio.h>
int main() int main()
{ {
int tong=0, dem; int tong=0, dem;
int sopt, sosau; int sopt, sosau;
do {
<tập lệnh>
} while ( <điều kiện> );
• Là vòng lặp mà lần lặp đầu tiên điều kiện không được
kiểm tra
• Tập lệnh trong vòng lặp được thực hiện ít nhất 1 lần,
ngay cả khi điều kiện lặp không bao giờ đúng
Lưu đồ
Lệnh
Đúng
Biểu thức != 0
Sai
13
Ví dụ
#include <stdio.h>
• Tính tổng của một dãy số
nguyên với số cuối cùng là int main()
nhập là 0
{
int tong=0, so;
• tổng =0
printf(“Nhap cac so trong day\n");
do
do
{ {
• input số scanf("%d", &so);
• cộng số vào tổng
tong += so;
} while (số khác 0)
}while (so != 0);
int n;
do {
printf(“Input a positive number: ”);
n = -1;
fflush(stdin);
if (scanf(“%d”, &n) != 1)
printf(“Input data is not a number\n”);
}while (n<0);
17
Dùng vòng lặp while
18
Dùng vòng lặp while → Kết quả
20
Dùng vòng lặp do…while
21
Vòng lặp vô tận
• Trong vòng for các nhánh khởi tạo, điều kiện và cập nhật là
tùy chọn.
• Có thể tạo vòng lặp vô tận bằng lệnh while hoặc for
– Vòng lặp là vô tận khi điều kiện lặp là luôn luôn đúng
while (1)
{
/* lặp vô tận */
}
for (;;)
{
/* lặp vô tận */
}
Lệnh break
• Lệnh trực tiếp cho phép thoát ngay khỏi vòng lặp
mà không cần kiểm tra điều kiện lặp
• Thường được áp dụng trong các vòng lặp vô tận
for (;;)
{
…
if (<điều kiện thoát OK>) break;
}
Ví dụ
int n;
while (1) {
printf(“Input a positive number: ”);
fflush(stdin);
if (scanf(“%d”, &n) != 1)
printf(“Bad number. Try again\n”);
else if (n<0)
printf(“Must be positive. Try again\n”);
else
break;
}
printf(“The number is %d\n”, n);
Kết quả chạy
for (…)
{
…
if (<cần bỏ qua lần lặp này>) continue;
…
}
Ví dụ
for(i=1;i<=100;i++)
if (i % 5 != 0)
printf(‘‘%d’’,i);
28
Ví dụ
int n;
do {
printf(“Input a positive number: ”);
fflush(stdin);
if (scanf(“%d”, &n) != 1) {
printf(“Bad number. Try again\n”);
continue;
}
printf(“The number is %d\n”, n);
}while (n<0);
Kết quả chạy
• Ví dụ: 6 = 2x3,
• 24 = 2x2x2x3,
• 23 = 23
Bài tập 2
34
Bài tập
1
Nội Dung Khóa Học
1st Tổng quan lập trình máy tính
2nd Ngôn ngữ lập trình C
3rd Kiểu dữ liệu
4th Vào ra dữ liệu
5th Biểu thức trong ngôn ngữ C
6th Lệnh rẽ nhánh
7th Lệnh lặp (1)
8th Lênh lặp (2)
9th Hàm
10th Mảng
11th Con trỏ
12th Chuỗi
13th Cấu trúc dữ liệu
14th Vào ra với file
15th Final Exam
2
Khái niệm chương trình con
• Chương trình con
– Là đoạn chương trình thực hiện 1 nhiệm vụ cụ thể và
được đóng gói theo cấu trúc xác định
– Được định nghĩa 1 lần và sử dụng lại nhiều lần.
• Vai trò
– Tổ chức 1 chương trình thành nhiều phần nhỏ để tăng
tính cấu trúc.
– Tiết kiệm thời gian bằng cách sử dụng chương trình con
đã có thay vì viết lại.
– Mở rộng tính năng cho chương trình bằng cách sử dụng
các thư viện, ví dụ printf(), scanf()…
– Gỡ lỗi, bảo trì chương trình dễ dàng hơn
3
Hàm trong ngôn ngữ C
• Các ngôn ngữ lập trình nói chung: 2 loại chương
trình con
– Hàm: thực hiện công việc và trả lại kết quả.
– Thủ tục: thực hiện công việc, không trả lại kết quả.
• Ngôn ngữ C:
– Chỉ có 1 loại chương trình con là hàm (function).
– Hàm trong C tương đương cả hàm và thủ tục trong các
ngôn ngữ khác.
– Sử dụng kiểu void (kiểu dữ liệu không định kiểu) khi hàm
không trả về dữ liệu.
4
Hàm
• Là một nhóm các khai báo và câu lệnh được đặt tên
• Các chương trình con này lại có thể sử dụng các hàm
khác, và cứ tiếp tục như vậy
/*
* Goi ham in loi chao mung
*/
int main(void)
{
Gọi hàm sayHello();
return 0;
}
Tại sao sử dụng hàm?
• Chúng cho phép chia nhỏ vấn đề thành các công
việc con
– Giúp giải quyết dễ dàng hơn những vấn đề phức tạp
• Sử dụng hàm chương trình được viết sẽ sáng sủa hơn
nhờ khả năng “trừu tượng hoá”
– Chúng ta chỉ cần biết một hàm làm gì mà không quan tâm
nó làm thế nào
• Chúng cho phép tổng quát hoá một số nhóm lệnh lặp
nhiều lần
– Tránh viết đi viết lại nhiều lần một số nhóm lệnh
Xây dựng hàm
• Với mỗi hàm xây dựng cần phải đặc tả:
– Tên hàm
– Tham số truyền vào
– Loại giá trị mà hàm trả về nếu có
– Khối lệnh được thực hiện khi hàm được gọi đến
printf(“Nhap so nguyen:");
scanf("%d",&num);
printf("%d!=%d\n",
num, giaithua(num));
Return 0;
}
Ví dụ hàm tính bình phương
#include<stdio.h>
int bp(int x){
Khai báo và
int y;
định nghĩa
y = x * x;
hàm
return y;
}
int main(){
int i;
for (i=1; i< 20; i+=2)
Gọi hàm ra printf("%4d\n", bp(i));
thực hiên printf("\n");
return 0;
}
11
Tham số hàm
• Là các biến địa phương của hàm mà giá trị được xác
định cho mỗi lần gọi hàm
– Vì vậy tham số có giá trị khác nhau cho mỗi lần gọi
– Tham số chỉ có thể truy nhập bên trong hàm mà thôi
– Khi gọi hàm giá trị cho tất cả các tham số phải được xác định
• Một hàm không có tham số có thể được khai báo với từ khoá void
cho danh sách tham số
Tham số hàm
• Chú ý phân biệt
– Biến địa phương bên trong hàm dùng chứa tham số và biến mà giá trị
của nó được dùng để gọi hàm
– Vì thế nếu hàm thay đổi giá trị cho tham số, nó sẽ không làm thay
đổi giá trị của biến được sử dụng để gọi hàm
Ví dụ tham số
#include <stdio.h>
Khai báo tham số
int addOne ( int i ) là biến địa phương
{
i = i + 1; Thay đổi giá trị biến
return i; địa phương
}
int main(void)
{ Truyền giá trị của biến
int i = 3; i trong hàm main cho
lời gọi hàm
printf(“%d\n”, addOne(i) );
printf(“%d\n”, i);
Output:
return 0; 4
} 3
Ví dụ (tiếp)
void badSwap ( int a, int b )
{ int temp;
temp = a;
a = b;
b = temp;
printf("Called environment: %d %d\n",a,b);
}
int main(void)
{ int a = 3, b = 5;
printf("Calling environment: %d %d\n",a,b);
badSwap ( a, b );
printf("Calling environment: %d %d\n",a,b);
return 0;
}
Trả về giá trị
• Lệnh return dùng để trả về giá trị cho hàm
• Một hàm không trả về giá trị nào phải được khai báo
với kiểu trả về void
– Khi đó có thể không cần sử dụng lệnh return trong hàm
Kiểu dữ liệu trả về
• Có thể là kiểu dữ liệu bất kì (kiểu dữ liệu có sẵn hoặc kiểu dữ liệu
do người dùng tự định nghĩa)
• Nếu kiểu dữ liệu trả về là kiểu void thì hàm không trả về giá trị
nào cả.
• Nếu không khai báo kiểu dữ liệu trả về → chương trình dịch của
C sẽ ngầm hiểu rằng kiểu dữ liệu trả về của hàm là kiểu int.
17
Sử dụng hàm
Tên_hàm (DS_tham_số_thực _sự);
Ví dụ:
N = bp(1);N= bp(3);,…
Lưu ý:
• Gọi hàm thông qua tên hàm và các tham số được cung cấp thực sự
cho hàm (tham số thực sự).
• Nếu hàm nhận nhiều tham số thì các tham số ngăn cách nhau bởi dấu
phẩy
• Các tham số hình thức của hàm sẽ nhận các giá trị từ tham số truyền
vào
• Sau khi thực hiện xong, trở về điểm mà hàm được gọi
18
Ví dụ: Cho biết kết quả thực hiện chương trình
#include <stdio.h> 3
int fun(int a){ fun(3)
a++;
4
return a;
} fun(4)
5
int main(){
fun(5)
printf("%d\n", fun(fun(fun(3))));
return 0;
}
6
19
Ví dụ: Cho biết kết quả thực hiện chương trình
fun(5)
#include<stdio.h>
5 * fun(4)
int fun(int n){
if(n==0) return 1; 4 * fun(3)
else return n*fun(n-1);
} 3 * fun(2)
printf(“Nhap so nguyen:");
scanf("%d",&num);
printf("%d!=%d\n",
num, giaithua(num));
}
24
Phân loại biến
• Biến được khai báo trong hàm
• biến cục bộ.
• chỉ được truy cập trong hàm của nó mà thôi
Hàm main() cũng là 1 chương trình con nhưng là nơi chương trình
được bắt đầu
Biến khai báo trong hàm main() cũng là biến cục bộ, chỉ có phạm
vi trong hàm main().
Biến trùng tên
• Khi có sự trùng tên giữa biến tổng thể và biến cục bộ
trong 1 hàm, thì biến cục bộ được ưu tiên dùng trong
hàm đó.
• Ví dụ:
int i;
void f() {
int i;
i++; // chỉ làm thay đổi giá trị biến i cục bộ
}
void g() {
i++; // làm thay đổi giá trị của biến i tổng thể
}
Biến static
• Biến cục bộ ra khỏi phạm vi thì bộ nhớ
dành cho biến được giải phóng
• Yêu cầu lưu trữ giá trị của biến cục bộ một
cách lâu dài => sử dụng từ khóa static
Cú pháp:
static <kiểu_dữ_liệu> tên_biến;
28
Ví dụ→Kết quả
#include <stdio.h>
void fct() {
static int count = 1;
printf("\n Day la lan goi ham fct lan thu %2d", count++);
}
int main() {
int i;
for (i = 0; i < 10; i++) fct();
return 0;
}
29
Ví dụ
30
Các hàm thư viện
• Ngôn ngữ C cung cấp một số hàm thư viện như vào
ra, toán học, quản lí bộ nhớ, xử lí xâu chuỗi, v.v.
• Các khai báo nguyên mẫu như thế này đã được viết
trong các tệp tiêu đề (.h), ta chỉ cần #include chúng
vào chương trình
Thư viện toán học math.h
• Bao gồm một tập các hàm toán học với khai báo nguyên mẫu
như sau:
34
VD Đọc tọa độ 3 điểm A,B,C và
đưa ra d/tích ABC…
35
NGÔN NGỮ LẬP TRÌNH C
1
Nội Dung Khóa Học
1st Tổng quan lập trình máy tính
2nd Ngôn ngữ lập trình C
3rd Kiểu dữ liệu
4th Vào ra dữ liệu
5th Biểu thức trong ngôn ngữ C
6th Lệnh rẽ nhánh
7th Lệnh lặp (1)
8th Lênh lặp (2)
9th Hàm
10th Mảng
11th Con trỏ
12th Chuỗi
13th Cấu trúc dữ liệu
14th Vào ra với file
15th Final Exam
2
Nội Dung Bài Học
➢ Khái niệm mảng
▪ Giới thiệu
▪ Khai báo
▪ Cấp phát bộ nhớ
4
Giới thiệu
• Trong thực tế, thường gặp các đối tượng có tính chất chung
– Tháng trong năm
– Điểm trung bình của sinh viên trong lớp
• Các đối tượng được nhóm lại dưới 1 tên
• Đối tượng được đặc trưng bởi tên nhóm và thứ tự trong nhóm
– Tháng thứ 3 trong năm: Tháng 3
– Sinh viên thứ 17 trong lớp:…
• Số thứ tự của đối tương trong nhóm là chỉ số phần tử
5
Khái niệm mảng
• mảng là 1 kiểu dữ liệu gồm
– Một số hữu hạn thành phần.
– Các thành phần có cùng 1 kiểu: kiểu cơ sở hay là kiểu
thành phần.
• Mỗi phần tử của mảng được tham khảo thông qua
– Tên mảng và
– Chỉ số của phần tử trong mảng
Ví dụ:
<d7>: Điểm thi tin của sinh viên thứ tự 7 trong lớp
6
Khai báo mảng
Kiểu_dữ_liệu Tên_Mảng[Kích thước];
7
Cấp phát bộ nhớ cho mảng
• Các phần tử trong mảng được cấp phát các
ô nhớ kế tiếp nhau trong bộ nhớ
• Kích thước của mảng bằng kích thước 1
phần tử nhân với số phần tử
Ví dụ:
int A[10];//Mảng A gồm 10 phần tử nguyên
A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] A[9]
8
Truy nhập phần tử của mảng
• Biến mảng lưu trữ địa chỉ ô nhớ đầu tiên
trong vùng nhớ được cấp phát
• Ngôn ngữ C đánh chỉ số các phần tử trong
mảng bắt đầu từ 0
• Các phần tử của mảng được truy nhập
thông qua
– Tên mảng và
– Chỉ số của phần tử của phần tử trong mảng
Tên_Mang[Chỉ_số_phần_tử];
9
Ví dụ
int A[10];//Mảng A gồm 10 phần tử nguyên
7
A[0] 5
A[1] A[2] A[3] 7
A[4] A[5] A[6] A[7] A[8] A[9]
A
A[0] = 7;
A[1] = 5;
A[4] = 7;
int N = A[1] + A[4]; → N = 12
10
Ví dụ
int A[10];
for(int i = 0; i < 10; i++) A[i]= 2* i;
0? 2? 4? 6
? 8? 10
? 12
? 14
? 16
? 18
?
0
i : 10
7
1
4
2
6
5
3
8
9
Chú ý: C không kiểm tra vượt quá giới hạn
của mảng khi truy nhâp
11
Chỉ số mảng
• 1 mảng luôn có kích thước cố định
• Không có 1 phương thức cài đặt sẵn nào để
kiểm tra chỉ số trong phạm vi của mảng
• Người lập trình phải tự kiểm soát chỉ số trong phạm vi
của mảng
int A[n];
Lỗi chỉ số
int B[5]; vượt phạm vi
for (i=1; i<=n; i++) của mảng
B[i] = 0;
Ví dụ
Chú ý: C không kiểm tra vượt quá giới hạn
của mảng khi truy nhập
13
Nội Dung Bài Học
18
Nhập dữ liệu → Ví dụ 1
Nhập vào lượng mưa (mm) trong năm
#include <stdio.h>
#define MONTHS 12
int main(){
int rainfall[MONTHS], i;
for ( i=0; i < MONTHS; i++ ){
printf("Nhap luong mưa tháng %d: ", i+1);
scanf("%d", &rainfall[i] );
}
return 0;
}
19
Nhập dữ liệu → Lưu ý
• Nếu số phần tử của mảng chỉ được biết tại thời điểm
thực hiện chương trình (nhưng biết số phần tử tối
đa)
– Khai báo mảng với kích thước tối đa
– Sử dụng biến nguyên lưu số phần tử thực sự của mảng.
Ví dụ:
• Nhập vào mảng không quá 100 số thực
– Khai báo mảng thực Table có tối đa 100 phần tử.
– Nhập số phần tử thực sự của mảng
– Nhập giá trị cho từng phần phần tử (dùng for)
20
Nhập dữ liệu→Ví dụ 2
#include<stdio.h>
int main(){
float A[100];
int n, i;
do{
printf("\n Cho biet so phan tu cua mang: ");
scanf("%d",&n);
}while (n>100 || n<=0);
for(i = 0; i < n; i++){
printf("A[%d] = ", i); scanf("%f",&A[i]);
}
}
21
Chương trình dãy số
• Nhập 1 dãy số nguyên (nhiều nhất 10 phần tử) và in dãy số đó
theo thứ tự đảo ngược
#include <stdio.h>
int main(void) {
int i, n, A[10];
printf(“Nhap so phan tu trong day (n<=10):");
scanf("%d",&n);
printf(“Nhap cac phan tu trong day:\n");
for(i=0; i<n; i++) {
printf(“Phan tu thu %d:”, i+1);
scanf("%d",&A[i]);
}
printf(“Day so sau khi dao lai:\n");
for(i=n-1; i>=0; i--)
printf("%5d",A[i]);
return 0;
}
Truyền mảng cho hàm
return 0;
}
Đếm số phần tử thỏa mãn điều kiện
• Duyệt từng phần tử của dãy (dùng for )
• Nếu phần tử xét thỏa mãn điều kiện
– Ghi nhận
• Chuyển sang xem xét phần tử tiếp theo
Ví dụ: Đếm số tháng có lượng mưa lớn hơn 50mm
int dem = 0;
for(i = 0; i < MONTHS; i++)
if(rainfall[i] > 50)
dem++;
printf("\nThang mua nhieu hon 50mm: %d", dem);
26
Ví dụ: Nhập mảng, đưa ra TBC các số
chia hết cho 7
#include<stdio.h>
int main(){
int A[100];
int n, i, d = 0, S=0;
printf("\n So phan tu cua mang (<100) : "); scanf("%d",&n);
for(i = 0; i < n; i++){
printf("A[%d] = ", i); scanf("%d",&A[i]);
}
for(i = 0; i < n; i++)
if(A[i] %7==0){
d++;
S+= A[i];
}
if(d > 0) printf("TBC so chia het cho 7: %7.2f",(float)S/d);
else printf("Trong day khong co so chia het cho 7");
}
27
Tìm kiếm phần tử
Tìm phần tử lớn nhất (nhỏ nhất)
– Giả sử phần tử đó là phần tử đầu tiên
– Lần lượt so sánh với các phần tử còn lại
• Nếu phần tử mới của dãy lớn hơn coi đây là phần tử lớn nhất
và tiếp tục so sánh với phần tử kế
• Nếu không đúng, so sánh tiếp với phần tử kế
Ví dụ: Tìm tháng có lượng mưa nhiều nhất trong năm
max = rainfall[0];
for(i = 1; i < MONTHS; i++)
if(rainfall[i] > max)
max = rainfall[i];
printf("\n Luong mua nhieu nhat la: %d", max);
28
Tìm kiếm phần tử
• Tìm kiếm các phần tử thỏa mãn điều kiện (giống
bài toán đếm)
– Dùng for duyệt toàn bộ
– Nếu cần thiết, dùng thêm mảng ghi lại chỉ số
29
Tìm kiếm phần tử (tiếp)
• Tìm phần tử đầu tiên của danh sách
– Dùng vòng lặp for kết hợp với break;
– Dùng vòng lặp while
Ví dụ
Đưa ra phần tử đầu của mảng có giá trị
bằng k;
30
Tìm kiếm phần tử →Ví dụ
int Table[100]
int N, i, k, f;//N: số phần tử, k phần tử cần tìm
• Dùng for
for(i = 0; i < N; i++)
if(Table[i] == k) break;
if(i< N) printf("Tim thay tai vi tri %d",i);
• Dùng while
i=0; f =0; //f: found. f = 1 k is found
while(i < N && f==0){
if(Table[i] == k) f = 1;
else i++;}
if (f==1) printf("Tim thay tai vi tri %d",i);
31
Bài tập
i=0
j=1
5 1 4 2 8
i=0
j=5
Selection sort
Lượt 2
i=1
j=2
1 5 4 2 8
i=1
j=3 1 4 5 2 8
i=1
j=5
Selection sort
Lượt 3
i=2
j=3
1 2 5 4 8
i=2
j=5
Selection sort
Lượt 4
i=3
j=5
Lượt 5
i=4
j=5 1 2 4 5 8
Ví dụ→Kết quả
39
Nội Dung Bài Học
41
Ví dụ mảng hai chiều
43
Mảng nhiều chiều→Ví dụ
int b[3][4][5]; b[2][2][4]
b[2]
b[1]
b[0]
b[0][1][2]
• Mảng b gồm 3 phần tử b[0], b[1], b[2]
• Mỗi phần tử là mảng 2 chiều gồm 4 hàng (hàng 0, 1, 2, 3)
và 5 cột (0, 1, 2, 3, 4)
• Mỗi phần tử là 1 số nguyên có dấu 4 byte
44
Khởi tạo giá trị cho mảng
Các phần tử của mảng có thể được khởi tạo
giá trị ngay khi khai báo
Ví dụ
int a[4] = {1,4,6,2};
int b[2][3]={ {1,2,3}, {4,5,6} };
int t[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
};
45
Khởi tạo giá trị cho mảng → Chú ý
• Số lượng giá trị khởi tạo không được lớn hơn số
lượng phần tử trong mảng
– Nếu số lượng này nhỏ hơn, các phần tử còn lại được
khởi tạo giá trị 0
int A[3][4] = { {1}, {4,5} };
int A[3][4] = { };Tất cả đều mang giá trị 0
46
Ví dụ bảng cửu chương
#include <stdio.h>
void main()
{
/* bảng cửu chương cho cả số 0 */
int cuuchuong[10][10];
int i, j;
#define NYEARS 5
#define NMONTHS 12
int table[NYEARS][NMONTHS] ={
{30,40,75,95,130,220,210,185,135,80,40,45},
{25,25,80,75,115,270,200,165, 85, 5,10, 0},
{35,45,90,80,100,205,135,140,170,75,60,95},
{30,40,70,70, 90,180,180,210,145,35,85,80},
{30,35,30,90,150,230,305,295, 60,95,80,30}
};
• table[i][j] cho phép truy cập vào giá trị lượng mưa tháng
thứ (j+1) và năm (2000+i)
Ví dụ (tiếp)
1
Nội Dung Khóa Học
1st Tổng quan lập trình máy tính
2nd Ngôn ngữ lập trình C
3rd Kiểu dữ liệu
4th Vào ra dữ liệu
5th Biểu thức trong ngôn ngữ C
6th Lệnh rẽ nhánh
7th Lệnh lặp (1)
8th Lênh lặp (2)
9th Hàm
10th Mảng
11th Con trỏ
12th Chuỗi
13th Cấu trúc dữ liệu
14th Vào ra với file
15th Final Exam
2
Nội Dung Bài Học
4
Địa chỉ bộ nhớ của biến
• Bộ nhớ gồm dãy các ô nhớ
• Mỗi ô nhớ là 1 byte
• Mỗi ô nhớ có 1 địa chỉ riêng
• Các biến trong chương trình được lưu tại vùng nhớ nào
đó trong bộ nhớ
char ch = ’A’;
ch:
0x2000 ’A’
– Địa chỉ của biến, là địa chỉ của byte đầu tiên trong số các byte
được cấp
– Khi gán giá trị cho biến, nội dung các byte cung cấp cho biến
sẽ thay đổi
6
Ví dụ
int N; Địa chỉ biến N ?
?
E8
float x; 03 N
char Arr[4]; ?
00
Địa chỉ biến X ?
00
?
00
N = 1000;//03E8 ?
00
?
1B X
X=9.6875;//411B0000 Địa chỉ biến Arr ?
41
for(i=0;i<4;i++) ?
01
?
05
Arr[i]= 4*i+1; ?
09 Arr
?
Địa chỉ của 1 biến là địa chỉ byte 0D
0x2000
chPtr
Kiểu * Tên;
Ví dụ:
char* cPtr;
cPtr:
0x2004
12
Khai báo con trỏ (tiếp)
•Có thể tạo con trỏ đến biến có kiểu dữ liệu bất kì
•Một biến con trỏ luôn được khai báo đi kèm với
toán tử *
Ví dụ: int *numPtr1, *numPtr2;
float *xPtr, *yPtr;
Toán tử địa chỉ (&)
• Ký hiệu: &
• Là toán tử 1 ngôi, trả về địa chỉ của biến
Địa chỉ biến có thể được gán cho 1 con trỏ,
trỏ tới đối tượng cùng kiểu
• Ví dụ
char ch = ’A’;
0x2000 ’A’
&ch trả về giá trị 0x2000
14
Tham chiếu
•Dùng toán tử & để xác lập địa chỉ tham chiếu cho con trỏ
c: cPtr:
… A … 0x2000
0x2000 0x2004
Toán tử địa chỉ (&) (tiếp)
• Ví dụ 0000
short int N; // &N→ ABCD Biến N
short int *pi; ABCD
pi = &N; // piABCD
ABCD EFCD
Biến pi
FFFF
Bộ nhớ
16
Chú ý về con trỏ
•Chỉ có thể xác lập tham chiếu cho con trỏ tới địa
chỉ của biến có kiểu tương thích với con trỏ
int aNumber;
Lỗi tương thích
char *ptr; về kiểu dữ liệu
Ví dụ:
ptr = &aNumber;
•Để in giá trị địa chỉ lưu bởi 1 con trỏ ta có thể
sử dụng định dạng in %p
???
numPtr
• Ví dụ
• short int N;
• short int * pi;
N= 10; *pi = 10;
• pi = &N;
• N = 10;//Vùng nhớ mà pi trỏ tới ABCD EFCD
mang giá trị 10; Vậy *pi=10 Con trỏ pi
• *pi = 20;// Vùng nhớ pi trỏ tới được
gán giá trị 20; Vậy N= 20 FFFF
Bộ nhớ
20
Các bước sử dụng con trỏ
int num;
char ch = ‘A’;
float x;
num:
ch: ‘A’
x:
Các bước sử dụng con trỏ (tiếp)
26
Ví dụ
#include <stdio.h> #include <stdio.h>
int main(){ int main(){
int N=5, M=10; int N=5, M=10;
int *p1 = &N; int *p1 = &N;
int *p2 = &M; int *p2 = &M;
*p1 = *p2; p1 = p2;
printf("%d %d",*p1,*p2); printf("%d %d",*p1,*p2);
} }
10 10 10 10
27
Ví dụ→Trường hợp 1 0000
#include <stdio.h>
int main(){ 10
5 ABCD
int N=5, M=10; 10 ABCF
int *p1 = &N;
int *p2 = &M;
p2 p1
ABCF
*p1 = *p2;
printf("%d %d",*p1,*p2); ABCD
}
FFFF
Bộ nhớ
28
Ví dụ→Trường hợp 2 0000
#include <stdio.h>
int main(){ 5 ABCD
int N=5, M=10; 10 ABCF
int *p1 = &N;
int *p2 = &M;
p2 p1
ABCF
p1 = p2;
ABCD
ABCF
printf("%d %d",*p1,*p2);
}
FFFF
Bộ nhớ
29
Các phép toán trên con trỏ
30
Ví dụ
0000
• int N=1000,
E8 ABC0
M=2000,P=3000; P 03 ABC1
• int * p1 = &P, *p2 = &N; M D0 ABC2
07 ABC3
p1 - p2 → -2 B8 ABC4
N 0B ABC5
* (p2-1) → 2000 ABC6
* ++ p1 → 2000 p2 ABC4
Ghi chú: p1 ABC0
ABC2
• Kiểu int, các phần tử cách nhau 4 bytes
• Kiểu float, các phần tử cách nhau 4 bytes FFFF
Bộ nhớ
31
Con trỏ void
void * Tên_con_trỏ
• Là 1 con trỏ đặc biệt: con trỏ tới dữ liệu không định
kiểu.
• Có thể nhận giá trị là địa chỉ của 1 biến có kiểu dữ
liệu bất kỳ
• Ví dụ:
void * p, *q;
int n; float x;
p = &n; q= &x; \\Các câu lệnh hợp lệ
32
Nội Dung Bài Học
x: 1 x: 2
swap
y: 2 y: 1
Truyền theo tham trị
#include <stdio.h>
void swap1(int a, int b) tmp:
{
int tmp; a: 1
tmp = a;
a = b; b: 2
b = tmp;
return;
}
int main()
{
int x = 1, y = 2; x: 1
swap1(x, y); y: 2
printf(“%d %d\n”, x, y);
return 0;
}
TRUYỀN THEO THAM TRỊ (TIẾP)
#include <stdio.h>
void swap1(int a, int b) tmp: 1
{
int tmp; a: 2
tmp = a; b: 1
a = b;
b = tmp;
return;
}
int main()
{ x: 1
int x = 1, y = 2;
swap1(x, y); y: 2
printf(“%d %d\n”, x, y);
return 0;
}
TRUYỀN THEO THAM CHIẾU
#include <stdio.h>
void swap2(int* a, int* b) tmp:
{
int tmp; a:
&x
tmp = *a;
*a = *b; b:
&y
*b = tmp;
return;
}
int main()
{
int x = 1, y = 2; x: 1
swap2(&x, &y); y: 2
printf(“%d %d\n”, x, y);
return 0;
}
TRUYỀN THEO THAM CHIẾU
#include <stdio.h>
void swap2(int* a, int* b) tmp: 1
{
int tmp; a:
&x
tmp = *a;
*a = *b; b:
&y
*b = tmp;
return;
}
int main()
{
int x = 1, y = 2; x: 2
swap2(&x, &y);
printf(“%d %d\n”, x, y); y: 1
return 0;
}
Tham số hàm là con trỏ
• Chỉ dùng hàm với tham số dạng tham chiếu (con trỏ)
khi cần thiết thay đổi giá trị 1 biến được truyền vào
cho hàm.
Mảng và con trỏ
◼ Chú ý rằng 1 mảng tương ứng với địa chỉ phần tử đầu tiên
của nó
◼ Do vậy 1 mảng A là con trỏ đến phần tử A[0]
Ví dụ: int A[10];
int *ptr;
ptr = A; /* ptr = &A[0] */
• Có thể truy cập vào các phần tử của 1 mảng thông qua
con trỏ
Ví dụ: int A[10];
int *ptr=A;
ptr[2] = 5; /* A[2] = 5 */
• Con trỏ có thể được tăng hoặc giảm trỏ đến phần tử khác
trong mảng
• Nếu p là một con trỏ tới 1 kiểu xác định, p+1 đưa ra địa chỉ
chính xác của biến tiếp theo trong bộ nhớ có cùng kiểu
• p++, p--, hay p += i cũng đem lai ý nghĩa tương tự
44
Câu hỏi 1
#include<stdio.h>
30
int main()
{
int a=3, *p;
p = &a;
printf("%d\n", a * *p * a + *p);
return 0;
}
45
Câu hỏi 2
#include<stdio.h>
int main(){
int arr[2][2][2] = {10, 2, 3, 4, 5,
6, 7, 8};
int *p, *q; 8, 5
p = &arr[1][1][1];
q = (int *) arr;
printf("%d, %d\n", *p, *(q+4) );
return 0;
}
46
Truyền mảng cho hàm
#include <stdio.h>
int main(void)
{
int n, A[10];
printf(“Nhap so phan tu trong day (n<=10):");
scanf("%d",&n);
return 0;
Chương trình chính
}
vẫn không thay đổi khi
thay cách khai báo
hàm
Bài TẬP
1
Nội Dung Khóa Học
1st Tổng quan lập trình máy tính
2nd Ngôn ngữ lập trình C
3rd Kiểu dữ liệu
4th Vào ra dữ liệu
5th Biểu thức trong ngôn ngữ C
6th Lệnh rẽ nhánh
7th Lệnh lặp (1)
8th Lênh lặp (2)
9th Hàm
10th Mảng
11th Con trỏ
12th Chuỗi
13th Cấu trúc dữ liệu
14th Vào ra với file
15th Final Exam
2
Khái niệm xâu ký tự
3
Khai báo chuỗi
char tên_xâu [số_kí_tự_tối_đa];
•4
Biểu diễn trong bộ nhớ
• Nhắc lại:
– Các ô trong bộ nhớ được đánh địa chỉ
– Một khai báo biến kí tự cho phép dành 1 “ô”
để chứa giá trị
ch = ‘B’;
0 x1 FFE 0 x1 FFF 0 x2 0 0 0 0 x2 0 0 1 0 x2 0 0 2
‘B’ etc
ch
Biểu diễn chuỗi kí tự
• 1 chuỗi được biểu diễn bởi 1 mảng kí tự
• Mỗi phần tử của mảng chứa 1 char
• Tên chuỗi là địa chỉ trỏ đến phần tử đầu tiên của
mảng
name
= 0x2000
Khai báo 1:
char name[5] = “Ann”; Kí tự đánh dấu kết
thúc xâu (kí tự rỗng)
name A n n \0
= 0x2000
name A n n \0
= 0x2000
0x2 000 0x2003
Chú ý:
char name[] = ‘Ann’; Không có kí tự kết
thúc xâu (‘\0’)
name A n n
= 0x2000
0x2 000 0x2 002
Khai báo chuỗi (tiếp)
Khai báo 3:
char *name = “Ann”;
0x3000 A n n \0
name
return 0;
}
Mảng kí tự và Chuỗi kí tự
• Tập hợp các kí tự viết liên tiếp nhau
• Truy nhập 1 phần tử của xâu ký tự (là 1 ký tự)
giống như truy nhập vào 1 phần tử của mảng:
Tên[Chỉ_số]
12
Truy nhập phần tử của xâu
Giống như truy nhập tới 1 phần tử của mảng
ký tự
tên_xâu [chỉ_số_của_kí_tự]
Ví dụ: char Str[10] = "Tin hoc";
T i n - h o 1 \0
c \0 ? ?
Str[0] → ‘T’ Str[3] = ‘-’;
Str[3] → ‘ ’ Str[7] = ‘ ’;
Str[7] → ‘\0 ‘ Str[8] = ‘1 ‘ ;
Str: Tin-hoc 1
Str[8] → ? Str[9] = ‘\0’;
13
Kí tự trong xâu
0 x3 9 9 5 0x399C
name J o h n \0
= 0x3995
index 0 index 2
o u t p u t : Char a t i n d e x 2 i s h .
Chương trình đếm kí tự
• Đếm số kí tự không phải là kí tự trắng trong 1 chuỗi được nhập vào
#include <stdio.h>
int main()
{
char str[80]; int dem, i;
dem = 0; i = 0;
while ( str[i] != '\0' ) {
if ( str[i] != ' ' ) dem++; i++;
}
printf(“So ki tu khac trang trong xau la %d", dem);
return 0;
}
Ví dụ: Nhập xâu và đếm số ký tự ‘*’
#include <stdio.h> Tính chiều dài của xâu
void main(){ d=0;
char Str[100];
while(Str[d] != '\0') d++;
int d=0, i=0;
printf("Nhap xau ky tu: "); gets(Str);
while(Str[i] != '\0'){
if(Str[i]=='*')
d++;
i++;
}
printf("Ket qua : %d",d);
}
16
Nhập câu và đưa ra dưới dạng cột
1. #include <stdio.h>
2. void main(){
3. char S[100];
4. int i=0;
5. printf("Nhap xau: "); gets(S);
6. while(S[i] != '\0'){ //32 là mã ASCII của phím space
7. if(S[i] != 32 && S[i+1]==32) printf("%c\n",S[i]);
8. else if(S[i] != 32) printf("%c",S[i]);
9. i++;
Đếm số từ, nếu các từ
10. }
11. printf("\n\n");
được cách nhau bởi dấu
12.} phân cách
17
Các hàm xử lý xâu ký tự
Vào/ra xâu ký tự
• Tệp tiêu đề: stdio.h
• Nhập xâu kí tự
– gets(tên_xâu);
– scanf("%s",&tên_xâu);
• Hiển thị xâu kí tự
– puts(tên_xâu);
– printf("%s",tên_xâu);
18
Lưu ý:
• Hàm gets: các trình biên dịch mới hiện tại không còn hỗ trợ
nữa
• Lý do: gets không kiểm tra kích thước xâu được nhập
19
Các hàm xử lý xâu ký tự
Tệp tiêu đề: string.h
• #include <string.h>
• Phải sử dụng các hàm thư viện cho các thao tác
xử lí chuỗi:
– Gán: strcpy()
– Nối chuỗi: strcat()
– So sánh: strcmp()
– Lấy độ dài xâu: strlen()
– v.v.
20
Các hàm xử lý xâu ký tự
Chú ý:
char str[100] = "Hello world";
char * p = str;
• p là con trỏ, trỏ tới mảng các ký tự/xâu ký tự
p+6 : (Phép tính toán trên con trỏ), cũng là xâu ký tự. p+6
trỏ tới xâu "world"
• Xâu ký tự, có thể được khai báo char *
21
Các hàm xử lý xâu ký tự
size_t strlen(const char * xâu)
– Trả về độ dài xâu
printf("%d ",strlen("Hello world")); 11
char * strcpy(char * đích, const char * nguồn)
– sao chép nội dung xâu nguồn vào xâu đích, trả về giá trị
xâu nguồn
char Str[20];
printf("%s ",strcpy(Str,"Hello")); Hello
printf("%s", Str); Hello
Chú ý: Phép gán Str = "Hello" là không hợp lệ
22
Gán chuỗi
#include <stdio.h>
#include <string.h>
int main()
{
char string1[MAXLENGTH];
char string2[MAXLENGTH];
return 0;
}
0x2000 A n n \0
name1
0x3990 D a v e \0
name2
name2 = name1;
0x2000 A n n \0
name1
0x2000 D a v e \0
name2
• Không đủ bộ nhớ
char name[] = “Ann”;
strcpy(name, “David”);
name A n n \0
name D a v i d \0
Các hàm xử lý xâu ký tự
int strcmp(const char * xâu_1, const char * xâu_2)
– So sánh hai xâu.
– Trả về giá trị 0 nếu hai xâu giống nhau;
– Giá trị < 0: xâu_1 < xâu_2
– Giá trị >0: xâu_1 > xâu_2
Ví dụ
char Str[20];
strcpy(Str, "hello");
printf("%d", strcmp(Str, "hello"));→0
printf("%d", strcmp(Str, "hello! "); →-1 (!?)
printf("%d", strcmp(Str, "Hello"); → 1 (!?)
27
So sánh chuỗi
Trả về
0 : nếu string1 giống string2
strcpy(string1, “Apple”); < 0: nếu string1 < string2
strcpy(string2, “Wax”); > 0: nếu string1 > string2
if (strcmp(string1, string2) < 0)
{
printf(“%s %s\n”, string1, string2);
}
else
{
printf(“%s %s\n”, string2, string1);
}
o u t p u t : Apple Wax
Lỗi về so sánh
30
Nối chuỗi
char string1[80];
char string2[80];
strcpy(string1, “Goodbye”);
strcpy(string2, “, Cruel ”);
strcat(string1, string2);
strcat(string1, string2);
strcat(string1, “World!”);
char name[5];
strcpy(name, “Ann”);
strcat(name, “ Smith”);
name A n n \0
= 0x2000
A n n S m i t h \0
Các hàm xử lý xâu ký tự
char * strchr (const char * s, int c)
– Trả về con trỏ trỏ tới vị trí xuất hiện đầu tiên của ký tự
c trong s. Nếu không có trả về con trỏ null
strcpy(Str,"Hello world");
printf("%s ",strchr(Str,‘o')); o world
char* strstr(const char * s1, const char * s2)
– Trả về con trỏ trỏ tới vị trí xuất hiện đầu tiên của chuỗi
s2 trong s1. Nếu không tồn tại, trả về con trỏ null
printf("%s ",strstr(Str, "llo")); llo world
33
Lưu ý:
34
Các hàm xử lý xâu ký tự (tiếp)
Tệp tiêu đề: stdlib.h
• int atoi(const char * str):
– Chuyển một xâu kí tự thành một số nguyên tương ứng
– Ví dụ: atoi("1234") →1234
• int atol(const char * str):
– Chuyển xâu kí tự thành số long int
• float atof(const char * str):
– Chuyển xâu kí tự thành số thực
– Ví dụ: atof("123.456E-2") →1.23456
• Thất bại cả 3 hàm: trả về 0
35
Tham số hàm là chuỗi
• Giống như mảng ta có thể khai báo chuỗi như là
tham số với char* hoặc char[]
void greeting (char* name)
void greeting (char name[])
• Chúng trỏ đến kí tự đầu tiên của chuỗi (mảng kí tự)
• Thay đổi nội dung chuỗi truyền vào sẽ làm thay
đổi chuỗi kí tự gốc
• Không cần truyền số kí tự trong chuỗi cho hàm
Ví dụ
hoten T r a n T i e n \0
Vị trí kí tự trắng
được tìm thấy (i=4)
Chương trình tách tên (tiếp)
Khai báo const thể hiện
#include <stdio.h> giá trị của tham số không
bị thay đổi trong hàm
#include <string.h>
char * timten(const char hoten[]);
int main()
{
char hoten[80];
timten(hoten)); return 0;
}
Bài tập
1
Nội Dung Khóa Học
1st Tổng quan lập trình máy tính
2nd Ngôn ngữ lập trình C
3rd Kiểu dữ liệu
4th Vào ra dữ liệu
5th Biểu thức trong ngôn ngữ C
6th Lệnh rẽ nhánh
7th Lệnh lặp (1)
8th Lênh lặp (2)
9th Hàm
10th Mảng
11th Con trỏ
12th Chuỗi
13th Cấu trúc dữ liệu
14th Vào ra với file
15th Final Exam
2
Nội Dung Bài Học
3
Ví dụ → Bài toán quản lý thí sinh thi đại học
4
Ví dụ → Bài toán quản lý thí sinh thi đại học
(tiếp)
Để quản lý danh sách (dưới 1000) thí sinh dự
thi, cần nhiều mảng rời rạc
5
Ví dụ → Bài toán quản lý thí sinh thi đại học (tiếp)
DS_SBD
123 456 789
DS_Ten Mảng ký tự
Nguyễn Nguyễn Trần An
Văn An Hoàng Nghĩa
DS_KhoiThi
A D A
DS_KetQua
24.5 28.5 22.0
8
Khái niệm → Ví dụ
• Kết quả học tập của sinh viên
– TenSV: Chuỗi ký tự
– MaSV: Chuỗi số/ số nguyên
– Điem: Số thực
9
Nội Dung Bài Học
10
Khai báo kiểu cấu trúc
struct Tên_kiểu_cấu_ trúc {
<Khai báo các trường dữ liệu>
};
• struct: từ khóa, cho phép người dùng khai báo kiểu dữ liệu
mới: kiểu cấu trúc
• Tên_kiểu_cấu_truc: Tên của kiểu cấu trúc do người dùng
tự định nghĩa
– Tuân theo nguyên tắc đặt tên đối tượng trong C
• Khai báo các trường dữ liệu: Danh sách các khai báo
thành phần (trường:field) của cấu trúc
– Giống khai báo biến
– Các trường có thể có kiểu bất kỳ
11
Khai báo cấu trúc
struct complex
{ Khai báo tên của
int real; cấu trúc
int img;
}; Các trường của
cấu trúc
struct studentRec
{
Đừng quên dấu ; sau
char name[80]; khai báo cấu trúc
int mark;
};
Khai báo này mới chỉ tạo kiểu của cấu trúc chứ chưa có biến
Khai báo kiểu cấu trúc → Ví dụ
Thẻ sinh viên
Số hiệu:…(Chuỗi ký tự).. struct SinhVien{
char SHSV[10];
Tên sinh viên: (Chuỗi ký tự)
char Ten[30];
Năm sinh:…(Số nguyên)… int NS;
Khóa:……(Số nguyên)……. int Khoa;
Lớp:…… :.(Chuỗi ký tự). … char Lop [10];
};
Point2D
struct Point{
Hoành độ (x)…(Số thực)..
float x, y;
Tung độ (y)…..(Số thực).. };
13
Khai báo biến cấu trúc
• Khai báo kiểu cấu trúc nhằm tạo định nghĩa toàn thể cho các
cấu trúc sẽ được dùng sau này
– Không cung cấp không gian nhớ cho kiểu
• Khai báo biến cấu trúc nhằm yêu cầu chương trình tạo vùng
nhớ để lưu trữ các dữ liệu cho biến cấu trúc
– Chứa dữ liệu của các trường của cấu trúc
14
Khai báo biến cấu trúc → Cú pháp
Tồn tại định nghĩa kiểu cấu trúc
struct Kiểu_cấu_ trúc Tên_biến;
Khai báo trực tiếp
struct {
<Khai báo các trường dữ liệu>
}Tên_biến;
Kết hợp với khai báo kiểu
struct Kiểu_cấu_ trúc {
<Khai báo các trường dữ liệu>
}Tên_biến;
15
Khai báo biến cấu trúc → Ví dụ
Tồn tại định nghĩa kiểu cấu trúc
struct SinhVien SV1, SV2, Thu_khoa;
Khai báo trực tiếp
struct {
float x, y; //Tọa độ trên mặt phẳng
}A, B; //Khai báo 2 điểm A, B
Kết hợp với khai báo kiểu
struct Point_3D{
float x, y, z;// Tọa độ không gian
}A, B;
16
Khai báo biến cấu trúc → Ví dụ 2
Tồn tại định nghĩa kiểu cấu trúc
struct complex num;
Khai báo trực tiếp
struct {
int real, img;
}num; //Khai báo biến số phức
Kết hợp với khai báo kiểu
struct complex{
int real, img;
}num;
17
Khai báo biến cấu trúc → Ví dụ 3
Tồn tại định nghĩa kiểu cấu trúc
struct studentRec john;
Khai báo trực tiếp
struct {
char name[80];
int mark;
} john;
18
Khai báo biến cấu trúc →Chú ý
Các cấu trúc có thể được khai báo lồng nhau
struct diem_thi {
float dToan, dLy, dHoa;
}
struct thi_sinh{
char SBD[10];
char ho_va_ten[30];
struct diem_thi ket_qua;
} thi_sinh_1, thi_sinh_2;
19
Khai báo biến cấu trúc →Chú ý
Có thể khai báo trực tiếp các trường dữ liệu của 1
cấu trúc bên trong cấu trúc khác
struct thi_sinh{
char SBD[10];
char ho_va_ten[30];
struct{
float dToan, dLy, dHoa;
} ket_qua;
} thi_sinh_1, thi_sinh_2;
20
Khai báo biến cấu trúc →Chú ý
Có thể gán giá trị khởi đầu cho một biến cấu
trúc, theo nguyên tắc như kiểu mảng
Ví dụ: struct SinhVien{
struct Date { char Ten[20];
int day; struct Date {
int month; int day;
int year; int month;
}; int year;
struct SinhVien{ } NS;
char Ten[30]; } SV = {"Tran Anh",20,12,1990};
struct Date NS;
} SV = {"Tran Anh",20,12,1990};
21
Định nghĩa kiểu dữ liệu với typedef
typedef <tên_cũ> <tên_mới>;
Mục đích
• Đặt tên mới đồng nghĩa với tên của 1 kiểu dữ liệu
đã được định nghĩa
– Thường được sử dụng cho kiểu cấu trúc
• Giúp cho khai báo trở nên quen thuộc và ít bị sai hơn
Ví dụ
typedef char Str80[80];
typedef long mask;
Str80 str="Bonjour tout le monde !";
mask a, b;
22
Định nghĩa kiểu (typedef)
• Ví dụ:
struct studentRec
{
char name[80];
int mark;
}; Cấu trúc dữ liệu Tên kiểu
hiện có mới
25
Chú ý
typedef struct point_2D {
float x, y;
} point_2D, diem_2_chieu, ten_bat_ki;
point_2D X;
diem_2_chieu Y;
ten_bat_ki Z;
Chú ý:
point_2D, diem_2_chieu, ten_bat_ki là
các tên cấu trúc, không phải tên biến
26
Nội Dung Bài Học
27
Truy cập các trường dữ liệu
• Cú pháp
tên_biến_cấu_trúc.tên_trường
• Lưu ý
– Dấu “.” là toán tử truy cập vào trường dữ
liệu trong cấu trúc
– Nếu trường dữ liệu là 1 cấu trúc → sử dụng
tiếp dấu “.” để truy cập vào thành phần mức
sâu hơn
28
Truy nhập cấu trúc
• Ví dụ:
struct studentRec {
char name[80];
int mark;
};
31
Ví dụ
Bài toán: Xây dựng một cấu trúc biểu diễn
điểm trong không gian 2 chiều.
– Nhập giá trị cho một biến kiểu cấu trúc này
– Hiển thị giá trị các trường dữ liệu của biến này
ra màn hình.
Thực hiện:
– Cấu trúc gồm: tên điểm, tọa độ x, tọa độ y
– Nhập, hiển thị từng trường của biến cấu trúc
như các biến dữ liệu khác
32
Ví dụ
#include<stdio.h>
#include<string.h>
typedef struct {
char ten[5];
int x, y;
} toado;
int main() {
toado t;
printf("Nhap thong tin toa do\n");
printf("Ten diem: ");
fgets(t.ten, sizeof(t.ten), stdin);
t.ten[strlen(t.ten) - 1] = '\0'; // Bỏ ký tự xuống dòng
printf("Toa do x: "); scanf("%d", &t.x);
printf("Toa do y: "); scanf("%d", &t.y);
printf("Gia tri cac truong\n");
printf("%-5s%3d%3d\n", t.ten, t.x, t.y);
return 0;
}
33
Phép gán giữa các biến cấu trúc
• C cho phép gán hai biến cấu trúc cùng kiểu:
Biến_cấu_trúc_1 = biến_cấu_trúc_2
• Ví dụ
– Xây dựng cấu trúc gồm họ tên và điểm thi học kỳ của
sinh viên
– Khai báo 3 biến cấu trúc: a, b, c
– Nhập giá trị cho biến a.
– Gán biến a cho biến b
– gán từng trường của a cho c.
– So sánh a, b và c ?
34
Ví dụ
#include<stdio.h>
#include<string.h>
typedef struct {
char hoten[20];
int diem;
} sinhvien;
int main() {
sinhvien a, b, c;
printf("Nhap thong tin sinh vien\n");
printf("Ho ten: ");
fgets(a.hoten, sizeof(a.hoten), stdin);
a.hoten[strlen(a.hoten) - 1] = '\0'; // Bỏ ký tự
xuống dòng
printf("Diem:"); scanf("%d", &a.diem);
35
Ví dụ
b = a; //Gan bien cau truc
strcpy(c.hoten, a.hoten); //Gan tung truong
c.diem = a.diem;
printf("Bien a: ");
printf("%-20s%3d\n", a.hoten, a.diem);
printf("Bien b: ");
printf("%-20s%3d\n", b.hoten, b.diem);
printf("Bien c: ");
printf("%-20s%3d\n", c.hoten, c.diem);
return 0;
}
36
Ví dụ →Kết quả
37
So sánh cấu trúc
if (studA == studB)
{
printf(“Du lieu trung nhau.\n”);
}
if (strcmp(studA.name, studB.name) == 0
&& (studA.mark == studB.mark) )
{
printf(“Du lieu trung nhau.\n”);
}
Mảng của cấu trúc
stud_list
name: "fred"
0 stud_list[0]
mark:5
name: "ralph"
1
mark:7
name: "fong"
2
mark:4
name: "rachel"
3
mark:9
Chương trình ví dụ (1)
#include <stdio.h>
#define MAXLEN 80
#define MAXN 40
int main()
{
int total, i;
Student stud_list[MAXN];
return 0;
}
Truyền cấu trúc làm tham số
• Giống như mọi biến khác, cấu trúc có thể
được dùng làm tham số của hàm
• Cũng có 2 cách truyền tham số cho 1 cấu trúc
– Truyền cấu trúc theo dạng sử dụng giá trị của các
trường sẽ không làm thay đổi nội dung của biến
cấu trúc gốc
– Truyền địa chỉ của cấu trúc để có thể làm thay
đổi nội dung của cấu trúc gốc
Hàm trả về cấu trúc
• Trả về 1 “gói” chứa nhiều giá trị
Student readRecord ( void )
{
Student newStud;
printf(“Nhap ten va diem: ");
scanf("%s %f",newStud.name,&(newStud.mark));
return newStud;
}
main()
{
Student studA;
studA = readRecord();
}
Truyền cấu trúc qua con trỏ
int main()
{
Student studentA;
readStudent(&studentA);
}
Nội Dung Bài Học
45
Một số ví dụ
1. Nhập vào 2 số phức và đưa ra tổng và tích của chúng
46
Ví dụ 1→Kết quả thực hiện
47
Một số ví dụ
2. Nhập vào một danh sách (<100) sinh viên gồm họ tên, năm sinh. Kết
thúc nhập khi gặp SV có tên là rỗng
• Đưa danh sách vừa nhập ra màn hình.
• Đưa ra màn hình sinh viên lớn tuổi nhất
48
Ví dụ 2→Kết quả thực hiện
49
Một số ví dụ
3. Nhập danh sách có N (N < 100, nhập từ bàn phím) thí sinh gồm họ tên,
số báo danh, khoa dự thi và điểm thi
• Đưa ra DSSV đã sắp xếp theo kết quả thi
• Đưa ra danh sách sinh viên dự thi khoa CNTT có điểm thi từ 22.5
trở lên
• Nhập vào một số báo danh và in ra họ tên, điểm thi và khoa đăng
ký của thí sinh nếu tìm thấy. Nếu không tìm thấy thí sinh thì đưa ra
thông báo « không tìm thấy »
50
Ví dụ 3→Kết quả thực hiện
51
Ví dụ 3→Kết quả thực hiện
52
Ví dụ 3→Kết quả thực hiện
53
NGÔN NGỮ LẬP TRÌNH C
1
Nội Dung Bài Học
VÀO RA TỆP
➢ Khái niệm tệp
➢ Khái niệm kênh nhập xuất
➢ Nhập xuất với tệp văn bản
➢ Nhập xuất với tệp nhị phân
2
Khái niệm
• Tệp (Tập tin/File):
– Tập hợp các dữ liệu cùng kiểu
– Có liên quan tới nhau
• Lưu trữ tệp
– Lưu trữ trên thiết bị lưu trữ ngoài
– Có tên riêng để phân biệt
• Phân thành 2 loại
– Tệp văn bản (text file)
– Tệp nhị phân (binary file)
3
Phân loại
• Tệp văn bản
– Được tổ chức theo từng dòng
• Trên mỗi dòng là các ký tự ASCII hiện thị được như chữ cái,
chữ số, dấu câu,…
– Cuối mỗi dòng là các ký tự điều khiển
• CR: Carriage Return - mã ASCII 13
• LF:Line Feed- Mã ASCII 10
• Tệp nhị phân
– Các phần tử của tệp là các số nhị phân dung mã hóa
thông tin
– Thông tin được mã hóa: số, cấu trúc dữ liệu,..
4
Tệp dữ liệu và mảng
• Mảng
– Được lưu trong bộ nhớ →dữ liệu bị mất đi khi tắt máy
– Truy nhập trực tiếp tới một phần tử qua số hiệu
– Kích thước mảng xác định trước
• Tệp
– Lưu trữ trên thiết bị lưu trữ ngoài→dữ liệu được lưu trữ
lâu dài, không bị mất đi khi tắt máy
– Không truy nhập trực tiếp qua số hiệu phần tử
– Kích thước có thể rất lớn và không cần xác định trước
5
Tổ chức tệp
Phần tử dữ liệu ngay sau khi mở file Ký hiệu đánh dấu kết thúc file
EOF
6
Nội Dung Bài Học
VÀO RA TỆP
➢ Khái niệm tệp
➢ Khái niệm kênh nhập xuất
➢ Nhập xuất với tệp văn bản
➢ Nhập xuất với tệp nhị phân
7
Kênh xuất nhập
• Là 1 vùng đệm dùng cho việc
nhập xuất dữ liệu ở mức cao
Input.c
$input
#include <stdio.h> 10
void main() Nhap so 10
{ $input
abc
int a; Khong phai so nguyen
$input >out.txt
if ( scanf("%d", &a) != 1 ) 10
$input >out.txt
perror(“Khong phai so nguyen\n”); abc
else Khong phai so nguyen
printf(“Nhap so %d", a);
} Chuyển hướng stdout
ra tệp out.txt
Vào ra tệp
VÀO RA TỆP
➢ Khái niệm tệp
➢ Khái niệm kênh nhập xuất
➢ Nhập xuất với tệp văn bản
➢ Nhập xuất với tệp nhị phân
13
Quy trình
• Khai báo biến tệp
• Đóng tệp
14
Khai báo biến tệp
FILE * Con_Trỏ_Tệp
• Ví dụ
– FILE * f1, *f2;
– FILE *finput,*foutput;
15
Mở tệp
Con_Trỏ_Tệp = fopen(Tên_Tệp, Chế_độ mở)
• Hàm fopen() khi báo trong thư viện stdio.h
• Tên_Tệp: Kiểu chuỗi, xác định tên tệp trên đĩa
– Tên đầy đủ của tệp hoặc tệp trên thư mực hiện thời
• Chế độ mở: Hằng xâu, gồm các ký tự r/w/a/+/t/b
– Tùy thuộc kiểu tệp và mục đích sử dụng
– Kiểu tệp: t: text file; b: binary file
• Trả về NULL nếu có lỗi mở tệp
16
Chế độ mở tệp
“r” Đọc (tệp đã tồn tại) Báo lỗi nếu tệp
chưa tồn tại
“w” Mở mới để ghi, ghi đè (tệp đã tồn tại)
18
Ví dụ
#include <stdio.h>
Mở tệp để ghi
int main()
{
FILE *out = fopen(“hello.txt”, “w”);
if (out == NULL)
{
perror(“Khong the mo tep de ghi.\n”);
return 1;
} Ghi dữ liệu ra
tệp
fprintf(out, “Hello world”);
fclose(out);
ðóng tệp khi
return 0;
kết thúc
}
Truy nhập tệp văn bản
• Tương tự như với bàn phím/ màn hình
• Yêu cầu chỉ rõ nguồn/đích thông tin
• Các thao tác
– Đọc dữ liệu từ tệp : fscanf() / fgets() /fgetc()
– Ghi dữ liệu ra tệp : fprintf() / fputs() /fputc()
– Dịch chuyển con trỏ tệp : fseek() / rewind()
– Kiểm tra kết thúc tệp : feof()
• Ví dụ:
– fprintf(FILE *fptr, Xâu_định dạng [,DS giá trị])
– fgets(char * Xâu ký tự, int n, FILE *fptr)
20
fprintf() và printf()
• fprintf(FILE * stream, …) hoạt động giống như
printf(…) nhưng được áp dụng trên 1 kênh xuất dữ
liệu bất kì (thường là tương ứng với 1 tệp)
• printf(…) là một trường hợp cụ thể tương đương với
fprintf(stdout, …)
• Quá trình nhập liệu tương ứng với việc quét dữ liệu
trên vùng đệm theo 1 đặc tả dữ liệu được chỉ ra
• Sau mỗi lần quét thành công con trỏ vùng đệm di
chuyển để có thể quét dữ liệu kế tiếp cho những
lần đọc sau
• Khi dữ liệu trong vùng đệm không còn, con trỏ
vùng đệm trỏ đến vị trí EOF.
– Để kiểm tra con trỏ có ở vị trí kết thúc hay không
sử dụng hàm: int feof(FILE*)
fscanf() và scanf()
• fscanf(<stream>, …) dùng để đọc dữ liệu hoạt
động trên một kênh nhập bất kì
• Hoạt động giống như scanf() dùng để đọc dữ liệu
trên kênh stdin
• Kết quả của fscanf() và scanf() là số phần tử dữ liệu
đọc được
Input.c
#include <stdio.h> C:\>input
Nhap so: 12
void main() Nhap xau: ab
{ So 12, xau ab
int a;
char s[20];
printf(“Nhap so: ”);
scanf(“%d”, &a);
%d chỉ lấy hai kí tự
fflush(stdin); ’12’ để chuyển thành
printf(“Nhap xau: “); số, còn dư kí tự
gets(s); được làm sạch bằng
fflush() trước khi nhập
printf(“So %d, xau %s”, a, s); xâu bằng gets()
}
Đếm số từ của một tệp
#include <stdio.h>
int main()
{
Mở tệp để đọc
int dem = 0;
char s[80];
FILE * f = fopen(“vanban.txt”, “r”);
if (f == NULL)
{
perror(“Loi mo tep vanban.txt\n”);
return 1;
} Mỗi lần chỉ
while (!feof(f)) đọc 1 từ
dem += fscanf(f, “%s”, s);
fclose(f);
printf(“Tong so tu: %d”, dem);
return 0;
}
fgetc() và fputc()
VD:Chương trình chép nội dung 2 file
ch = fgetc( input );
while( ch != EOF ) {
fputc( ch, output );
ch = fgetc( input );
}
fclose(input);
fclose(output);
fgets()
#include <stdio.h>
#define LINE_LENGTH 80
main()
{
FILE* fp;
char line[LINE_LENGTH];
int count=0;
fp=fopen("input.txt","r");
while ( fgets(line, LINE_LENGTH, fp) != NULL)
count++;
printf("File contains %d lines.\n", count);
fclose(fp);
}
Nội Dung Bài Học
VÀO RA TỆP
➢ Khái niệm tệp
➢ Khái niệm kênh nhập xuất
➢ Nhập xuất với tệp văn bản
➢ Nhập xuất với tệp nhị phân
30
Tệp văn bản vs. tệp nhị phân
Tệp văn bản Tệp nhị phân
Nội dung file là các ký tự điều khiển và Dãy các bit 0 và 1 -> con người
chữ cái (văn bản) con người có thể đọc không đọc được
được
Có thể được đánh dấu kết thúc bằng 1 Không có ký tự đặc biệt đánh dấu
kí tự điều khiển (kí tự mã 26 ) kết thúc file
Các ký tự được lưu trữ 1 ký tự trong 1 Số nguyên 1245 lưu trữ trong 2 byte
byte.
Ví dụ: số nguyên 1245 chiếm 2 bytes
trong bộ nhớ nhưng sẽ chiếm 5 bytes
trong file văn bản.
Muốn mở ở chế độ văn bản ta chỉ cần kí tự ‘b’ nếu mở ở dạng nhị phân
thêm kí tự ‘t’ vào cho chế độ mở ("r+b", "wb", “a+b",...)
("r+t", "wt",...)
Truy nhập tệp nhị phân
Đọc dữ liệu
int fread(void * Địa_Chỉ_Đích, int Kích_thước,
int số_phần_tử, FILE *fptr)
– Đọc từ file xác đinh bởi biến fptr một khối dữ liệu kích thước
Số_Phần_Tử x Kích_Thước vào vùng nhớ xác định bởi Địa_Chỉ_Đích
– Nếu đọc thành công: Trả về số phần tử đọc được
– Nếu không thành công: Trả về giá trị 0
• Ví dụ:
int Buf[100];
FILE * fptr = fopen(“so.dat”,”rb”);
fread( Buf, sizeof(int), 100, fptr);
Ví dụ 2:
int a[10]; f=fopen("songuyen.dat", "r+b");
fread(a, 10, sizeof(int), f);
32
Truy nhập tệp nhị phân
Ghi dữ liệu
int fwrite(void * Đ_Chỉ_Nguồn, int Kích_thước,
int số_phần_tử, FILE *fptr)
– Ghi từ vùng nhớ xác định bởi Địa_Chỉ_nguồn một khối dữ liệu có kích
thước Số_Phần_Tử x Kích_Thước ra file được xác đinh bởi biến fptr
– Nếu ghi thành công: Trả về số phần tử đã ghi
– Nếu không thành công: Trả về giá trị 0
• Ví dụ:
int Buf[100];
FILE * fptr = fopen(“so.dat”,”wb”)
fwrite(Buf, sizeof(int), 100, fptr);
33
Truy nhập tệp nhị phân
Dịch chuyển con trỏ file
int fseek(FILE *fptr, long int N, int Vị_Trí_Đầu)
– Dịch chuyển con trỏ file của file fptr đi một khoảng N so
với Vị_Trí_Đầu
• SEEK_SET / 0: Vị trí đầu là đầu tệp
• SEEK_CUR / 1: Vị trí đầu là vị trí con trỏ file hiện thời
• SEEK_END / 2: Vị trí đầu là cuối tệp
– void rewind(FILE *fptr): Đưa con trỏ về đầu tệp
Kiểm tra kết thúc file
int feof(FILE *fptr) Chú ý khi dùng, có thể lỗi
– Trả về 0 nếu con trỏ file vẫn còn trỏ tới một phần tử dữ
liệu, 1 nếu con trỏ file đang trỏ tới EOF
34
Ví dụ 1
Tạo file Songuyen.dat ghi 100 số lẻ đầu tiên.
#include <stdio.h>
int main() {
FILE * f = fopen("SoNguyen.Dat", "wb");
int i, n;
for(i = 0; i <100; i++) {
n = 2*i+1;
fwrite(&n, sizeof(int), 1, f);
}
fclose(f);
return 0;
}
35
Ví dụ 2
Đọc file Songuyen.dat, đưa ra màn hình các số
lẻ từ vị trí số thứ 50 của file
#include <stdio.h>
int main() {
FILE * f = fopen("SoNguyen.Dat", "rb");
int n;
fseek(f, 50*sizeof(int), SEEK_SET);
while(!feof(f)){
fread(&n, sizeof(int), 1, f);
printf("%4d", n);
}
fclose(f);
return 0;
}
36
Ví dụ 3
• Nhập danh sách từ bàn phím các thí sinh dự thi, mỗi thí sinh gồm họ
tên, số báo danh, khoa dự thi và điểm thi. Dữ liệu nhập được ghi vào file
ThiSinh.dat. Kết thúc nhập khi gặp một thí sinh có tên là « *** »
• Đọc từ file ThiSinh.Dat, đưa ra màn hình danh sách các thí sinh thi vào
ngành CNTT có điểm thi lớn hớn 21 theo quy cách
STT Số Báo Danh Ho Tên Điểm Thi
• Từ file ThiSinh.Dat, tạo file CNTT.Dat chỉ chứa danh sách các thí inh thi
vào khoa CNTT
• Nhập vào một số báo danh, tìm trong file ThiSinh.Dat và in ra họ tên,
điểm thi và khoa đăng ký của thí sinh nếu tìm thấy. Nếu không tìm thấy
thí sinh thì đưa ra thông báo « không tìm thấy »
37
Ví dụ 3
#include <stdio.h>
#include <string.h>
typedef struct {
char Ten[30];
long SBD;
char Khoa[10];
float Diem;
} SinhVien;
int main() {
FILE *f1,*f2;
SinhVien SV;
int i, SBD;
//Nhap thong tin cho file ThiSinh.Dat
//Tao file CNTT.Dat
return 0;
}
38
Ví dụ 3
//Nhap thong tin cho file ThiSinh.Dat
f1 = fopen("ThiSinh.Dat", "wb");
i = 1;
do {
printf("Thi sinh %d :\n", i);
printf(" Ho Ten : "); fflush(stdin); fgets(SV.Ten, sizeof(SV.Ten), stdin);
SV.Ten[strlen(SV.Ten) – 1] = '\0'; // Bỏ ký tự xuống dòng
if(strcmp(SV.Ten,"***") == 0) break;
printf(" So Bao Danh: "); scanf("%d", &SV.SBD);
printf(" Khoa : "); fflush(stdin); fgets(SV.Khoa, sizeof(SV.Khoa), stdin);
SV.Khoa[strlen(SV.Khoa) – 1] = '\0'; // Bỏ ký tự xuống dòng
printf(" Diem : "); scanf("%f", &SV.Diem);
fwrite(&SV, sizeof(SinhVien), 1, f1);
i++;
} while(1);
fclose(f1);
39
Ví dụ 3
printf("\n\n DANH SACH BAN DAU \n");
f1 = fopen("ThiSinh.Dat", "rb");
i = 0;
while (fread(&SV, sizeof(SinhVien), 1, f1) > 0)
printf("%-3d %-5d %-20s %-20s %-5.1f\n", ++i, SV.SBD,
SV.Ten, SV.Khoa, SV.Diem);
printf("\n\n Thi Sinh thi CNTT tren 21.0\n");
i = 0;
rewind(f1);
40
Ví dụ 3
printf("\n\n Tao file CNTT.Dat\n");
i = 0;
rewind(f1);
f2 = fopen("CNTT.Dat", "wb");
while (fread(&SV, sizeof(SinhVien), 1, f1) > 0)
if (strcmp(SV.Khoa, "CNTT") == 0 )
fwrite(&SV, sizeof(SinhVien), 1, f2);
fclose(f2);
f2 = fopen("CNTT.Dat", "rb"); //doc lai file
while (fread(&SV, sizeof(SinhVien), 1, f2) > 0)
printf("%-3d %-5d %-20s %-5.1f\n", ++i, SV.SBD, SV.Ten,
SV.Diem);
fclose(f2);
41
Ví dụ 3
printf("\n\nTim Sinh Vien\n");
printf(" So Bao Danh "); scanf("%d", &SBD);
rewind(f1);
while (fread(&SV, sizeof(SinhVien), 1, f1))
if (SV.SBD == SBD){
printf("Tim thay sinh vien %s", SV.Ten);
break;
}
42
Bài tập
1.Viết chương trình tạo ra tệp văn bản F3 từ việc ghép nội dung hai
tệp văn bản F1 và F2.
2.Viết một chương trình cho phép cắt hết chú thích của một chương
trình C được lưu trữ trong một tệp. Tên tệp chương trình được
nhập vào từ bàn phím. Giả thiết rằng chương trình không có lỗi cú
pháp.
3.Giả thiết một tệp dữ liệu thu thập về thời tiết trong một năm có
định dạng theo mỗi dòng là:
<ngày>/<tháng> <nhiệt độ thấp nhất>-<nhiệt độ cao nhất> <độ ẩm>
1/1 11-17 70
2/1 12-17 75
…
Hãy viết chương trình đọc dữ liệu của tệp này và in ra nhiệt độ trung
bình của các tháng trong năm, tháng khô hanh nhất và tháng ẩm
ướt nhất.