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.

pdf106 trang | Chuyên mục: C/C++ | Chia sẻ: dkS00TYs | Lượt xem: 1666 | Lượt tải: 3download
Tóm tắt nội dung Bài giảng Ngôn ngữ lập trình C - Tạ Tuấn Anh, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
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:

  • pdfBài giảng Ngôn ngữ lập trình C - Tạ Tuấn Anh.pdf
Tài liệu liên quan