Vận dụng các nguyên lý lập trình cấu trúc cơ bản: phân rã bài toán theo chức năng, làm mịn dần từng bước, thiết kế từ trên xuống để tổ chức chương trình có cấu trúc Phân biệt phạm vi
Trang 1Bài thực hành số 10:
Tổ chức chương trình có cấu trúc
A Mục tiêu
Tổ chức chương trình có cấu trúc : Cấu trúc về lệnh, cấu trúc về dữ liệu, cấu trúc về chương trình (modul, hàm .)
Vận dụng các nguyên lý lập trình cấu trúc cơ bản: phân rã bài toán theo chức năng, làm mịn dần từng bước, thiết kế từ trên xuống để tổ chức chương trình có cấu trúc
Phân biệt phạm vi, tác dụng các loại biến
Tổ chức thư viện chương trình
B Ôn tập:
Các nguyên lý lập trình cơ bản
Phạm vi, tác dụng các loại biến : toàn cục, cục bộ, biến tĩnh
Tổ chức Project có tập tin thư viện *.h
I Phân rã bài toán theo chức năng và tiếp cận từ trên xuống:
1 Các nguyên lý lập trình cơ bản:
Phân rã theo chức năng:
Dựa vào các chức năng, các yếu tố cấu thành bài toán, ta phân rã bài toán thành các bài toán con Lời giải của bài toán đã cho sẽ được xác định từ các lời giải của các bài toán con
Lời giải của bài toán có thể xem là chương trình cần viết, tạo ra từ các modul, hàm (là lời giải của các bài toán con)
Thiết kế từ trên xuống
Đi từ cái chung đến cái riêng,từ kết luận đến cái đã biết
Phương pháp làm mịn dần
Làm mịn dần từng bước gắn liền với quá trình phân rã và thiết kế từ trên xuống, nó chính xác dần thao tác và dữ liệu theo từng mức
II Phạm vi, tác dụng các loại biến
1 Biến cục bộ (biến trong):
Trang 2-Trong hàm, khối lệnh
-Đối của hàm Trong khoảng thời gian hàm hay khối lệnh hoạt động Hàm hay khối lệnh chứa nó Lưu ý:
Khi chương trình ra khỏi khối lệnh hay hàm chứa biến cục bộ thì chúng tự động mất đi
2 Biến toàn cục (biến ngoài):
Ngoài tất cả các hàm Trong suốt thời gian chương
trình chứa nó hoạt động
Từ vị trí khai báo đến cuối tập tin
Lưu ý:
Mọi hàm đều có thể thâm nhập vào biến toàn cục bằng cách tham trỏ đến tên của nó
Biến toàn cục không tự xuất hiện và tự biến đi, cho nên chúng còn giữ lại giá trị qua mỗi lầm gọi hàm
3 Biến tĩnh trong:
Vị trí khai báo Cách khai báo Thời gian tồn tại Phạm vi tác dụng Trong hàm Thêm từ khóa static
trước định nghĩa biến thông thường
Trong suốt thời gian chương trình Bên trong hàm chứa nó
Lưu ý:
Biến tĩnh trong khác với biến cục bộ ở điểm : Giá trị của biến tỉnh trong vẫn được lưu giữ khi ra khỏi hàm
4 Biến tĩnh ngoài:
Vị trí khai báo Cách khai báo Thời gian tồn tại Phạm vi tác dụng Ngoài tất cả
các hàm Thêm từ khóa statictrước định nghĩa biến
thông thường
Trong suốt thời gian chương trình Từ vị trí khai báo đến cuối tập tin
III Tổ chức project có tập tin thư viện *h
Ta đã biết cách tổ chức project có một tập tin cpp : giả sử đã có project với tên Lab_Vd, với tập tin chương trình là Cpp_Vd.cpp
Ta tao thêm tập tin *.h, đặt tên h_Vd như sau:
Chọn Header Files – Nhấn phím phải chuột – Add – New item – Chọn Code (trong Categories – Code) – Chọn header file (.h) ( trong Templates) – đặt tên h_Vd (trong ô Name) – chọn Add
Trang 3Trong mỗi tập tin (*.h, *cpp) ta sọan thảo nội dung theo cấu trúc đã qui định.
Trong tập tin *h, nội dung nên bao gồm các định nghĩa hằng, định nghĩa kiểu
dữ liệu, định nghĩa các hàm chức năng
Trong tập tin *.cpp, cài đặt hàm main(), có thể có các hàm tổ chức menu, các hàm nhập xuất dữ liệu
C Luyện tập:
Ví dụ 1:
Ta xem tên là một xâu ký tự bao gồm nhiều từ tách biệt bằng các ký tự trắng
Từ là một dãy liên tiếp các ký tự khác ký tự trắng Viết chương trình nắn các tên nhập
từ bàn phím theo qui cách:
Khử các ký tự trắng ở đầu và cuối của tên
Khử bớt các dấu cách ở giữa các từ, chỉ để lại một ký tự trắng (khoảng cách)
Các chữ cái đầu từ được viết hoa, ngoài ra mọi chữ cái còn lại được viết thường
Phân tích:
Tên gồm nhiều từ, các từ phân biệt bằng các ký tự trằng (khoảng cách)
Vậy bài toán Nắn tên chuyền về Nắn từ
Nắn các từ theo qui cách : Đầu từ phải là ký tự hoa, nên phải gọi thao tác chuyển đổi một ký tự thành ký tự hoa: Hoa(x) Các ký tự còn lại trong Từ phải là ký tự thường, nên phải gọi thao tác chuyển đổi một ký tự thành ký tự thường: Thuong(x)
Nếu ta xử lý mỗi từ xong, ta ghi từ đó vào một xầu ký tự tạm, vật ta cần thao tác ghép từ vào cuối một xâu ký tự
Nếu ta thực hiện việc xử lý xong một ký tự của từ thì ghép ký tự đó vào xâu ký tự, thì ta có thể thay thao tác ghép 1 từ vào sau xâu ký tự bằng thao tác ghép một ký tự vào cuối xâu ký tự: GhepKT(x,a)
Trang 4Thực hiện:
Bước 1: Tạo Project với tên “Lab10_Vd1”
Bước 2: Tạo các tập tin: Cpp_Vd1.cpp, h_Vd1.h
Bước 3: Trong các tập tin Cpp_Vd1.cpp, h_Vd1.h, soạn code theo cấu trúc:
Trong tập tin thư viện h_Vd1.h:
(trong tập tin này không có định nghĩa hàm main)
//Chen cac tap tin thu vien can thiet
#include<string.h>
usingnamespace std;
//Dinh nghia cac hang
#define CACH ‘ ‘
#define MAX 100
//Dinh nghia kieu du lieu
//Khai bao nguyen mau cac ham
void Nanten(char *a);
char Hoa(char Kt);
char Thuong(char Kt);
void GhepKT(char Kt, char *a);
//Dinh nghia cac ham
//Nan ten
void Nanten(char *a)
{
char *b;
int i;
b = newchar[100];
main()
Thuong(x)
Trang 5*b = NULL;
i = 0;
while (*(a+i) == CACH )
while (*(a+i) != NULL)
GhepKT(Hoa(*(a+i)),b);
while ((*(a+i) != CACH )&& (*(a+i) != NULL)) {
GhepKT(Thuong(*(a+i)),b);
}
while (*(a+i) == CACH)
if (a[i] != NULL)
strcpy( a,b);
delete []b;
}
//Ghep ky tu vao cuoi xau
void GhepKT(char Kt, char *a)
{
int l = strlen(a);
*(a+l++) = Kt;
*(a+l) = NULL;
}
//Chuyen ky tu thanh ky tu hoa
char Hoa(char Kt)
{
if ('a' <= Kt && Kt <= 'z')
Kt = Kt - 32;
return Kt;
}
//Chuyen ky tu thanh ky tu thuong
char Thuong(char Kt)
{
if ('A' <= Kt && Kt <= 'Z')
Kt = Kt + 32;
return Kt;
Trang 6 Trong tập tin chương trình Cpp_Vd1.cpp:
//Chen cac tap tin thu vien can thiet, dac biet tap tin <\[duong dan]\h_Vd1.h>
#include<iostream>
#include<stdio.h>
#include<\Lab\Lab10_Vd1\Lab10_Vd1\h_Vd1.h>
//Khai bao nguyen mau cac ham dinh nghia trong tap tin nay
void main()
{
char *a;
a = newchar[MAX];
_flushall();
cout<<"\nNhap ten: ";
gets(a);
cout<<"\nTen truoc khi nan: "<<a;
Nanten(a);
cout<<"\nTen sau khi nan: "<<a;
cout<<'\n';
delete []a;
}
//Dinh nghia cac ham
Ví dụ 2:
Thực hiện các thao tác trên dãy n số nguyên với các chức năng sau :
1 Trả về chỉ số của phần tử cuối cùng bằng x nếu có; trả về -1 nếu không có
2 Tổng các số nguyên tố trong dãy
3 Trả về số đường chạy trong dãy
Các yêu cầu:
Dãy số: cài đặt mảng động bằng con trỏ
Chương trình: dạng menu
Các hàm chức năng: cài đặt bằng thuật toán đệ qui
Thực hiện:
Bước 1: Tạo Project với tên “Lab10_Vd2”
Bước 2: Tạo các tập tin: Cpp_Vd2.cpp, h_Vd2.h
Bước 3: Trong các tập tin Cpp_Vd2.cpp, h_Vd2.h, soạn code theo cấu trúc:
Trong tập tin thư viện h_Vd2.h:
(trong tập tin này định nghĩa các hàm chức năng, và không định nghĩa hàm main)
#include<math.h>
//Khai bao nguyen mau
int Cscc(int *a, int n, int x);
int Tong_nT(int *a, int n);
int So_DC(int *a, int n);
Trang 7int nt(int x);
// -int Cscc(int *a, int n, int x)
{
int Kq;
if (n == 1)
if (*a == x)
Kq = 0;
else
Kq = -1;
else
if(n > 1)
if(*(a+n-1)==x)
Kq = n-1;
else
Kq = Cscc(a,n-1,x);
return Kq;
}
int Tong_nT(int *a, int n)
{
int Kq;
if ( n==1)
if (nt(*a))
Kq = *a;
else
Kq = 0;
else
if (n >1)
if (nt(*(a+n-1)))
Kq = Tong_nT(a,n-1) + *(a+n-1);
else
Kq = Tong_nT(a,n-1);
return Kq;
}
int So_DC(int *a, int n)
{
int Kq;
if (n == 1)
Kq = 1;
else
if(n > 1)
if(*(a+n-1)<*(a+n-2) )
Trang 8Kq = So_DC(a,n-1) +1; else
Kq = So_DC(a,n-1); return Kq;
}
//Cac ham bo tro
int nt(int x)
{
int Kq, i, m;
double y;
if(x < 2)
Kq = 0;
else
{
Kq = 1;
y = x;
m = (int)sqrt(y);
i = 2;
while (i <= m && Kq) {
if(x % i == 0)
Kq = 0;
i++;
} }
return Kq;
}
Trong tập tin thư viện Cpph_Vd2.cpp:
#include<iostream>
#include<\Lab\Lab10_Vd2\Lab10_Vd2\h_Vd2.h>
#include<stdlib.h>
usingnamespace std;
void Nhap(int *a, int n);
void Xuat(int *a, int n);
void XL_Menu(int *a, int n, int Chon);
void Menu();
int ChonMenu();
void main()
{
int *a, n, Chon;
cout<<"\nnhap n = ";
Trang 9a = newint[n];
Nhap(a,n);
do
{
Chon = ChonMenu();
XL_Menu(a,n, Chon);
}
while(1);
cout<<'\n';
delete []a;
}
void Menu()
{
cout<<"\n BAnG MENU ";
cout<<"\n1 Chi so cua pt cuoi cung bang x";
cout<<"\n2 Tong cac so nguyen to";
cout<<"\n3 So duong chay";
cout<<"\n4 Thoat khoi chuong trinh!!!";
}
int ChonMenu()
{
int Chon;
for(;;)
{
Menu();
cout<<"\nnhap Chon tu 1 -> 4: "; cin>>Chon;
if (1 <= Chon && Chon <= 4)
break; }
return Chon;
}
void XL_Menu(int *a, int n, int Chon)
{
int Kq, x;
switch(Chon)
{
case 1:
cout<<"\n1 Chi so cua pt cuoi cung bang x"; Xuat(a, n);
cout<<"\nnhap x = "; cin>>x;
Trang 10Kq = Cscc(a,n, x);
if (Kq == -1)
cout<<"\n"<<x<<" khong co trong a!";
else
cout<<"\nchi so cua pt cuoi cung == "<<x<<" la: "<<Kq; cout<<'\n';
break;
case 2:
cout<<"\n2 Tong cac so nguyen to"; Xuat(a, n);
cout<<"\nTong cac so NT trong a: S = "<<Tong_nT(a,n); cout<<'\n';
break;
case 3:
cout<<"\n3 So duong chay"; Xuat(a, n);
cout<<"\nSo duong chay trong a: SDC = "<<So_DC(a,n);
cout<<'\n';
break;
case 4:
cout<<"\n9 Thoat khoi CT!\n"; exit(1);
}
}
//Cac ham nhap xuat
void Nhap(int *a, int n)
{
for (int i = 0; i < n; i++)
{
cout<<"\na["<<i<<"] = "; cin>>*(a+i);
}
}
void Xuat(int *a, int n)
{
int i;
cout<<"\nDay a:\n";
for (i = 0; i < n; i++)
Trang 11cout<<*(a+i)<<'\t'; }
Ví dụ 3:
Quản lý sinh viên dựa vào các thông tin sau :
Mã sinh viên
Họ tên sinh viên
Điểm trung bình
Số tín chỉ tích lũy
Viết chương trình khởi tạo dữ liệu sinh viên, và thực hiện các chức năng:
1 Tìm kiếm theo mã sinh viên
2 Thêm sinh viên vào cuối danh sách
3 Xóa sinh viên ra khỏi danh sách theo mã số
4 Xem danh sách sinh viên
Thực hiện:
Bước 1: Tạo Project với tên “Lab10_Vd3”
Bước 2: Tạo các tập tin: Cpp_Vd3.cpp, h_Vd3.h
Bước 3: Trong các tập tin Cpp_Vd3.cpp, h_Vd2.h, soạn code theo cấu trúc:
Trong tập tin thư viện h_Vd3.h:
#include<iostream>
#include<string.h>
#include<iomanip>
#include<stdio.h>
#include<conio.h>
#define MAX 1000
usingnamespace std;
//Dinh nghia kieu du lieu
struct SINHVIEN
{
char *Maso;
char *HoTen;
char *Lop;
double Dtb;
int Tichluy;
};
//Cac bien toan cuc
SINHVIEN Sv[MAX];
int n = 0;
Trang 12//Khai bao nguyen mau
void Output();
void Output_Data();
void Output_Struct(SINHVIEN p);
void Setup();
void Chen_Ct(char *Maso,char *HoTen,char *Lop,double Dtb, int Tichluy);
void Xoa_Ct(char *Maso);
int Tim_Maso (char *Maso);
//Khoi tao danh sach sinh vien
void Setup()
{
Chen_Ct("0213345","Nguyen Van","CTK100",4.5,41);
Chen_Ct("0210340","Truong Van A","CTK101",8.0,39);
Chen_Ct("0201381","Duong Mai","CTK100",4.5,38);
Chen_Ct("0211348","Tran Vuong","CTK100",5,34);
Chen_Ct("0210042","Hoang Trong","CTK101",6,38);
Chen_Ct("0201380","Duong Mai","CTK100",6,36);
Chen_Ct("0201180","Tran Hoan","CTK100",5,37);
Chen_Ct("0211380","Luu Trong","CTK100",6.5,36);
}
//Chen mot sinh vien vao danh sach Sinh vien
void Chen_Ct(char *Maso,char *HoTen,char *Lop,double Dtb, int Tichluy) {
if (n < MAX)
{
flushall();
Sv[n].Maso = newchar[12];
strcpy(Sv[n].Maso, Maso);
flushall();
Sv[n].HoTen = newchar[20];
strcpy(Sv[n].HoTen,HoTen);
flushall();
Sv[n].Lop = newchar[10];
strcpy(Sv[n].Lop,Lop);
Sv[n].Dtb = Dtb;
Sv[n].Tichluy = Tichluy;
Trang 13n++;
}
//Xoa sinh vien theo ma so
void Xoa_Ct(char *Maso)
{
int i, Kq = Tim_Maso (Maso);
if (n == 0)
{
cout<<"\nDS rong! khong xoa duoc!"; _getch();
return; }
if (Kq == -1)
{
cout<<"\nKhong co sinh vien nao co ma so "<<Maso; _getch();
return; }
cout<<"\nThong tin sinh vien bi xoa:\n";
Output_Struct(Sv[Kq]);
for (i = Kq +1; i < n; i++)
Sv[i-1] = Sv[i];
n ;
}
//xuat du lieu 1 cau truc (sinh vien)
void Output_Struct(SINHVIEN p)
{
cout<<'\n';
cout <<setiosflags(ios::left)
<<setw(12)<<p.Maso
<<setw(22)<<p.HoTen
<<setw(10)<<p.Lop
<<setw(10)<<p.Dtb
<<setw(10)<<p.Tichluy;
}
//Xuat danh sach nhan vien ra man hinh
void Output_Data()
{
for (int i = 0; i < n; i++)
Output_Struct(Sv[i]);
}
Trang 14//In tieu de
void Output()
{
cout<<'\n';
cout <<setiosflags(ios::left)
<<setw(12)<<"MASO"
<<setw(22)<<"HOTEN"
<<setw(10)<<"LOP"
<<setw(10)<<"DTB"
<<setw(10)<<"TICHLUY";
}
//Tim theo ma so: tra ve chi so i sao cho sv[i].maso = Maso neu co
int Tim_Maso (char *Maso)
{
int i=0;
while ((i < n) && (stricmp(Sv[i].Maso, Maso)))
i++;
if (i == n)
return -1; //khong co
return i;
}
Trong tập tin chương trình Cpp_Vd3.cpp:
//Chen tap tin thu vien
#include<\Lab\Lab10_Vd3\Lab10_Vd3\h_Vd3.h>
//Khai bao nguyen mau
void Menu();
int ChonMenu();
void XL_Menu(int Chon);
void main()
{
int Chon;
Setup();
do
{
Chon = ChonMenu();
XL_Menu(Chon);
}
while(1);
}
//Xuat ten cac chuc nang cua CT ra man hinh
void Menu()
{
cout<<"\n -MENU -";
Trang 15cout<<"\n1.Tim theo ma so";
cout<<"\n2.Them sinh vien";
cout<<"\n3.Xoa sinh vien";
cout<<"\n4.Xem danh sach";
cout<<"\n5.Thoat khoi chuong trinh!!!";
}
//Dieu khien viec chon chuc nang cua nguoi SD
int ChonMenu()
{
int Chon;
for(;;)
{
Menu();
cout<<"\nNhap gia tri chon chuc nang (1-5): "; cin>>Chon;
if(Chon >= 1 && Chon <= 5)
break; }
return Chon;
}
//Xu ly CT
void XL_Menu(int Chon)
{
char *Maso, *HoTen, *Lop;
double Dtb;
int Tichluy;
int Kq;
int Cd, Ct;
switch(Chon)
{
case 1:
cout<<"\n1.Tim theo ma so:\n"; cout<<"\nNhap ma so: "; flushall();
Maso = newchar[12];
gets(Maso);
cout<<"\n Danh sach sinh vien \n"; Output();
Output_Data();
cout<<"\n\nKet qua tim:\n";
Kq = Tim_Maso (Maso);
if(Kq == -1)
cout<<"\nKhong co sinh vien nay!";
else
cout<<"\nSinh vien thu "<<Kq<<" co ma so nay";
Trang 16delete []Maso;
break;
case 2:
cout<<"\n2.Them sinh vien";
cout<<"\n Danh sach sinh vien ban dau \n"; Output();
Output_Data();
Maso = newchar[12];
HoTen = newchar[20];
Lop = newchar[10];
cout<<"\nNhap ma so SV: ";
flushall();
gets(Maso);
cout<<"\nNhap Ho Ten SV: ";
flushall();
gets(HoTen);
cout<<"\nNhap ma so lop: ";
flushall();
cin>>Lop;
flushall();
cout<<"\nDiem trung binh: ";
cin>>Dtb;
cout<<"\nTich luy: ";
cin>>Tichluy;
Chen_Ct(Maso,HoTen,Lop,Dtb, Tichluy);
cout<<"\n Danh sach sinh vien ket qua \n"; Output();
Output_Data();
cout<<"\n";
delete []Maso;
delete []HoTen;
delete []Lop;
break;
case 3: