Bài giảng Ngôn ngữ lập trình C - Tạ Tuấn Anh
C là một ngôn ngữlập trình cấu trúc bậc cao được các nhà lập trình chuyên nghiệp sửdụng
phổbiến đểphát triển các phần mềm hệthống (hệ điều hành, chương trình dịch, cơsởdữliệu,
.). Lý do ngôn ngữC đươc ưu chuộng chính là tính mềm dẻo và ngắn gọn của nọ. Một chương
trình được viết ởngôn ngữC có tính khảchuyển cao. Nó có thể được dịch và chạy trong nhiều
loại máy tính (PC, Sun, Mainframe,.) cũng nhưtrên nhiều nền hệ điều hành (DOS, UNIX,.).
Ngoài ra C cho phép viết chương trình bám sát cách tổchức bộnhớchương trình khi chạy. Do
vậy một chương trình được dịch từC luôn có kích thước nhỏgọn hơn một chương trình cùng loại
được dịch từcác ngôn ngữbậc cao khác nhưPASCAL. Nhưng cũng chính vì lí do này mà việc
nắm bắt và thành thạo ngôn ngữC sẽkhó khăn hơn nhiều so với ngôn ngữkhác. Môn học này
giới thiệu cho các học viên các kiến thức căn bản cũng nhưnâng cao vềngôn ngữlập trình C.
Bên cạnh các kiến thức vềcú pháp cũng nhưkĩnăng viết chương trình C, học viên còn nắm bắt
được các vấn đềliên quan đến tổchức bộnhớcủa một chương trình.
n.c" không cần tự viết khai báo nguyên mẫu hàm cần gọi nữa mà chỉ
việc #include tệp tiêu đề "func.h". Khi đó các khai báo nguyên mẫu hàm trong "func.h" sẽ được
ghép vào tệp "main.c".
Tệp nguồn "main.c":
#include "func.h"
void main()
{
func1(5, 6);
func2(2);
func3();
}
Như vậy có thể thấy vai trò của các tệp tiêu đề như là nơi chứa "giao diện" của các hàm có
thể gọi trong chương trình. Khi cần gọi đến hàm nào thì ta chỉ cần #include tệp tiêu đề mà chứa
khai báo nguyên mẫu hàm đó. Các tệp tiêu đề chuẩn của hệ thống như , , ...
cũng đóng vai trò này cho các hàm thư viện chuẩn của hệ thống.
Một chương trình viết với nhiều tệp nguồn được dịch trong hai pha. Pha thứ nhất là dịch
riêng rẽ mỗi tệp nguồn để chuyển thành tệp mã máy. Pha thứ hai là thực hiện liên kết tất cả các
tệp mã máy có từ pha dịch để tạo thành một tệp chạy duy nhất. Vai trò của pha liên kết là gắn kết
các lời gọi hàm trong chương trình đến phần mã máy thực sự cho nó. Do vậy khi một chương
trình có lời gọi một hàm mà hàm này không có khai báo thi hành thì sẽ bị báo lỗi tại pha này.
Pha liên k?t
Pha d?ch
main.c func.c
main.o func.o
prog.exe
Thu vi?n hàm
Hình 11: Sơ đồ biên dịch cho ví dụ trên
Khi sử dụng một IDE để biên dịch một chương trình với nhiều tệp nguồn thì cần phải tạo
dự án (project). Trong dự án ta khai báo tất cả các tệp nguồn có trong chương trình để giúp cho
quá trình biên dịch có thể thực hiện dịch và liên kết tự động các tệp cần thiết.
2. Khai báo biến extern
Theo nguyên tắc một biến tổng thể có thể sử dụng bởi mọi hàm trong chương trình. Nhưng
khi chúng ta viết chương trình với nhiều tệp nguồn thì một biến tổng thể chỉ có thể khai báo một
lần trong một tệp nào đó mà thôi. Vậy làm thế nào để một hàm ở những tệp nguồn khác vẫn có
thể sử dụng biến tổng thể này? Muốn làm được như vậy chúng ta cần phải có khai báo biến dạng
extern.
Tệp nguồn "func.c":
int global; /* khai báo biến tổng thể */
int func1(int, int) { ...}
void func2(int) { ... }
int func3() { ... }
Tệp nguồn "main.c":
#include "func.h"
void main()
{
/* khai báo extern chỉ ra rằng global là biến đã có bên ngoài */
extern int global;
global = 5; /* sử dụng biến đã có */
func1(5, 6);
func2(2);
func3();
}
Bài 38 - Khuôn dạng tệp tiêu đề
Tóm tắt nội dung:
Bài này trình bày phương pháp viết tệp tiêu đề cho các tệp nguồn của chương trình.
Thời lượng: 1 tiết
Trong một chương trình lớn với nhiều tệp nguồn thường thì chúng ta tạo tệp tiêu đề cho
mỗi tệp nguồn. Trong mỗi tệp tiêu đề chứa khai báo nguyên mẫu hàm và cấu trúc dữ liệu có sử
dụng trong tệp nguồn. Vì lí do một hàm có thể được gọi ở trong nhiều tệp nguồn khác nhau nên
tệp tiêu đề cho nó cũng có thể bị dịch nhiều lần khác nhau (mỗi một #include cho tệp là một lần
dịch). Để tránh nội dung của một tệp tiêu đề có thể bị dịch nhiều lần trong chương trình người ta
thường viết tệp tiêu đề theo khuôn mẫu sau.
#ifndef
#define
#endif
Ví dụ tệp tiêu đề "func.h":
#ifndef __FUNC_H
#define __FUNC_H
int func1(int, int);
void func2(int);
int func3();
#endif
Trong lần dịch đầu tiên __FUNC_H chưa được định nghĩa nên biên dịch có điều kiện sẽ
thực hiện dịch nội dung có trong tệp tiêu đề. Nhưng đến khi dịch lần thứ hai do __FUNC_H đã
được định nghĩa trong lần dịch thứ nhất nên biên dịch có điều kiện bỏ quả không dịch nội dung
khai báo trong tệp tiêu đề.
Chương trình mẫu với nhiều tệp nguồn: Quản lí điểm học sinh
Tệp tiêu đề "list.h":
#ifndef __LIST_H
#define __LIST_H
/* khai báo cấu trúc danh sách và các hàm xử lí trên danh sách */
struct nut_hs
{
char ten[25];
int diem;
struct nut_hs* tiep;
};
/* thêm một học sinh có ten vào danh sách có con trỏ đầu header
con trỏ đầu header của danh sách bị thay đổi nên truyền dạng tham biến
*/
void them_nuths(struct nut_hs**header_ptr, char* ten);
/* xoá một học sinh có ten vào danh sách có con trỏ đầu header
con trỏ đầu header của danh sách bị thay đổi nên truyền dạng tham biến
*/
int xoa_nuths(struct nut_hs**header_ptr, char *ten);
/* tìm một nút học sinh có tên truyền vào trong danh sách trỏ bởi header
kết quả là con trỏ đến nút tìm thấy, NULL nếu không tìm thấy
*/
struct nut_hs* tim_nuths(struct nut_hs*header, char *ten);
/* sắp xếp danh sách trỏ bởi header theo tên học sinh
*/
void sapxep_nuths(struct nut_hs*header);
#endif
Tệp nguồn "list.c":
/* thi hành cho tệp list.h */
#include "list.h"
#include
#include
#include
void them_nuths(struct nut_hs**header_ptr, char* ten)
{
struct nut_hs * hs;
hs = (struct nut_hs*)malloc(sizeof(struct nut_hs));
strcpy(hs->ten, ten);
hs->diem = -1; /* ban đầu chưa có điểm thi, vào điểm sau */
/* nối vào đầu danh sách */
hs->tiep = *header_ptr;
*header_ptr = hs;
}
int xoa_nuths(struct nut_hs**header_ptr, char *ten)
{
struct nut_hs * hs, *p;
hs = *header_ptr;
p = NULL; /* p trỏ tới nút trước nút cần xoá */
while(hs !=NULL&&strcmp(hs->ten, ten) !=0)
{
p = hs;
hs = hs->tiep;
}
if (hs !=NULL) /* nếu tìm thấy nút cần xoá */
{
/* kiểm tra có nút đứng trước nút cần xoá không */
if (p !=NULL)
p->tiep = hs->tiep;
else /* nút đầu danh sách sẽ là nút sau nút cần xoá */
*header_ptr = hs->tiep;
free(hs);
return 1;
}
return 0;
}
struct nut_hs* tim_nuths(struct nut_hs*header, char *ten)
{
struct nut_hs * hs;
hs = header;
while(hs !=NULL&&strcmp(hs->ten, ten) !=0)
hs = hs->tiep;
return hs;
}
void sapxep_nuths(struct nut_hs*header)
{
struct nut_hs *hs1, *hs2;
char ten[25];
int diem;
for (hs1=header; hs1!=NULL&&hs1->tiep!=NULL; hs1=hs1->tiep)
for (hs2=hs1->tiep; hs2!=NULL; hs2=hs2->tiep)
if(strcmp(hs1->ten, hs2->ten)>0)
{
/* doi cho thong tin ve hai nut trong danh sach */
strcpy(ten, hs1->ten);
strcpy(hs1->ten, hs2->ten);
strcpy(hs2->ten, ten);
diem = hs1->diem;
hs1->diem = hs2->diem;
hs2->diem = diem;
}
}
Tệp tiêu đề "func.h":
#ifndef __FUNC_H
#define __FUNC_H
#include "list.h"
/* các chức năng quản lí của chương trình bao gồm: */
/* thêm một học sinh vào danh sách */
void themhocsinh(struct nut_hs**header_ptr);
/* xoá một học sinh khỏi danh sách */
void xoahocsinh(struct nut_hs**header_ptr);
/* tra điểm cho môt học sinh trong danh sách */
void tradiem(struct nut_hs *header);
/* in danh sách học sinh */
void indanhsach(struct nut_hs *header);
/* nhập điểm thi cho học sinh lớp học */
void nhapdiem(struct nut_hs *header);
#endif
Tệp nguồn "func.c":
/* thi hành của các hàm khai báo trong func.h */
#include "func.h"
#include
#include
void themhocsinh(struct nut_hs**header_ptr)
{
char ten[25];
fflush(stdin); /* xoá vùng d?m stdin d? nh?p xâu tên */
printf("Ten: "); gets(ten);
if (strcmp(ten, "")!=0)
{
them_nuths(header_ptr, ten);
printf("Da them hoc sinh %s vao danh sach\n", ten);
}
}
void xoahocsinh(struct nut_hs**header_ptr)
{
char ten[25];
fflush(stdin); /* xoá vùng d?m stdin d? nh?p xâu */
printf("Ten hoc sinh can xoa: "); gets(ten);
if (xoa_nuths(header_ptr, ten))
printf("Da xoa hoc sinh %s khoi danh sach\n", ten);
else
printf("Khong co hoc sinh %s trong danh sach\n", ten);
}
void tradiem(struct nut_hs *header)
{
char ten[25];
struct nut_hs *tim;
fflush(stdin); /* xoá vùng d?m stdin d? nh?p xâu */
printf("Ten hoc sinh can tra diem: "); gets(ten);
tim = tim_nuths(header, ten);
if (tim==NULL)
printf("Khong co hoc sinh %s trong danh sach\n", ten);
else
if(tim->diem!=-1)
printf("Co diem thi la %d\n", tim->diem);
else
printf("Chua co diem\n");
}
void indanhsach(struct nut_hs *header)
{
struct nut_hs *p;
int i=1;
printf("%3s%25s%8s\n", "STT", "Ho va Ten", "Diem");
for(p=header; p!=NULL; p=p->tiep)
{
printf("%3d%-25s", i, p->ten);
if(p->diem==-1) printf("%8s\n", "Chua co");
else printf("%8d\n", p->diem);
i++;
}
}
void nhapdiem(struct nut_hs *header)
{
struct nut_hs *p;
int diem;
for(p=header; p!=NULL; p=p->tiep)
{
printf("Diem cua %s:", p->ten);
scanf("%d", &p->diem);
}
}
Tệp nguồn "menu.c":
/*
chương trình chính là một menu lựa chọn công việc
menu gọi các hàm chức năng có trong func.h và list.h
*/
#include "list.h"
#include "func.h"
#include
void main()
{
int chon;
struct nut_hs *header=NULL; /* con trỏ đầu danh sách học sinh */
/* tạo menu lựa chọn công việc */
do
{
printf("1. Them hoc sinh\n");
printf("2. Xoa hoc sinh\n");
printf("3. Nhap diem\n");
printf("4. Tra diem\n");
printf("5. In danh sach hoc sinh\n");
printf("0. Thoat\n");
printf("Lua chon: ");
scanf("%d", &chon);
switch(chon)
{
case 1:
themhocsinh(&header);
break;
case 2:
xoahocsinh(&header);
break;
case 3:
nhapdiem(header);
break;
case 4:
tradiem(header);
break;
case 5:
sapxep_nuths(header);
indanhsach(header);
}
}while(chon !=0);
}
BÀI TẬP TỔNG HỢP
Câu 1: Hãy xây dựng một cuốn từ điển bằng cách dùng cây nhị phân. Hãy xây dựng các hàm xử
lý các khâu dưới đây.
- Khởi tạo từ điển
- Chèn vào một từ mới
- In một từ
- Hiển thị từ điển
Viết một chương trình hoàn chỉnh bằng cách tạo ra các bảng chọn lệnh với các chức năng sau:
1. Tạo từ điển mới
2. Đọc một từ điển từ đĩa vào
3. Thêm các từ vào
4. Xoá một từ đi
5. Hiển thị các từ theo thứ abc
6. Cất từ điển vào đĩa.
0. Thoát ra khỏi chương trình
Câu 2: Hãy xây dựng sổ tay Telephone với các tính năng sau:
1. Đọc sổ tay từ đĩa vào
2. Tìm kiếm tên người trong danh mục phone
3. Thêm vào danh mục một người
4. Xoá một người ra khỏi danh mục
5. Cất vào đĩa.
0. Thoát ra khỏi chương trình
Lưu ý là danh mục phone luôn luôn được giữ theo thứ tự bảng chữ cái.
File đính kèm:
Bài giảng Ngôn ngữ lập trình C - Tạ Tuấn Anh.pdf

