lOMoARcPSD| 58833082
Một số vấn đề
TS. Trần Thanh Hải
Đặt vấn đề
Một số vấn đề thường gặp
Thực hiện phép chia a/b = ?, nếu b = 0.
Khi cấp phát động dữ liệu nếu không được thì báo lỗi thế nào?
Nếu le không mở được thì thông báo thế nào?
lOMoARcPSD| 58833082
Đối với ma trn:
Nếu số chiều nhập vào lớn hơn số chiều trong khai báo?
Nhân 2 ma trận không vuông nếu số cột của ma trận a không
bằng số hàng của ma trận b?
Đây những vấn đề ngoại lệ phát sinh ra trong quá trình lập cn
phải được hạn chế và đưa ra cảnh báo đối với người sử dụng
Phân loại các loại ngoại l
Ngoại lệ th1: do người lập trình bắt lỗi với các nh
huống riêng như: chia 0, vượt qua chỉ số mảng,…
lOMoARcPSD| 58833082
Ngoại lệ th 2: do y bắt lỗi đưa ra: dụ cấp phát
động, mở le… thì ta sử dụng trực ếp lớp ngoại lệ
<excepon>
Xngoại lệ - try ….catch
try{
// try block
}
catch( type1 arg){
// catch block
}
.
.
lOMoARcPSD| 58833082
catch(typeN arg){
// catch block
}
Xử lý ngoại lệ thường sử dụng để kết nối những lỗi rt nặng (chia 0)
Ví dụ - try_catch_3.cpp
int main(){ cout<<"start \n";
try{// bat dau khoi lenh
+ Khi x được đưa ra, điều
khiển được chuyển cho catch,
khối try bị dừng.
+ Chương trình ếp tục dòng lệnh
trong catch
+ Tuy nhiên khối catch thường kết
thúc bằng cách gọi exit(), abort().
cout<<"ben trong khoi lenh try \n";
throw 99;// dua ra mot loi
cout<<"Doan nay khong duoc goi \n";
}
lOMoARcPSD| 58833082
catch(int i){ // bat loi cout<<"Bat mot ngoai len
-- gia tri i = "; cout<<i<<"\n";
}
cout<<"end \n";
}
Sử dụng nhiều câu lệnh
catch – try_catch_4.cpp
thể kết hợp một câu lệnh try với nhiều câu lệnh catch() try
{ if(test==0) throw "value is zero";
if(test==1) throw 10;
if(test==2) throw 'a';
if(test==3) throw 123.23;
}
catch(int i){ cout << "Caught an integer. " <<
i << endl;
}
catch(double i){ cout << "Caught an double. " << i <<
endl;
} catch (char c) { cout << "Caught an char " << c
<< endl;
} catch(const char *str) { cout<<"bat mot xau ky tu
(test = 0): str = "; cout<<str<<endl;
lOMoARcPSD| 58833082
}
catch(...){ // bat toan bo loi neu tren thieu catch cho loai nao thi tat ca chu vao day
cout << "Caught one." << endl;
}
Rethrowing an excepon try_catch_5.cpp
sử dụng một cảnh báo cho nhiều nơi
void
XHandler(){ try{ thr
ow "hello";
}
catch(const char *) { cout<<"bat throw
trong ham \n";
throw; // nem tro lai char * cho ben ngoai ham
}
}
int main()
{ try{
XHandler();
}
lOMoARcPSD| 58833082
catch(const char * ){ cout<<"bat throw ngoai ham - trong
ham main()\n“;
}
}
Ví dụ về ma trn (ngoại lệ 1)
try { nhapmat(a, row_a, col_a);
nhapmat(b, row_b, col_b);
if (col_a!= row_b) { throw
1;
}
chMatran_AB(a,b,c,row_a, col_a); disp(c,row_a,col_b);
}
catch(int s)
{
cout<<"Khong the thuc hien phep nhan ch 2 ma tran \n"; exit(1);
}
lOMoARcPSD| 58833082
Ngoại lệ 2: excepon - #include <excepon>
Tất cả các ngoại lệ được ném (throw) bởi các thành phần của thư
viện chuẩn C ++ excepon, dẫn xuất từ lớp excepon.
excepon
descripon
bad_alloc
thrown by new on allocaon failure
bad_cast
thrown by dynamic_cast when it fails in a dynamic cast
bad_excepon
thrown by certain dynamic excepon speciers
bad_typeid
thrown by typeid
bad_funcon_call
thrown by empty funcon objects
bad_weak_ptr
thrown by shared_ptr when passed a bad weak_ptr
Thông báo lỗi
excepon
descripon
logic_error
error related to the internal logic of the program
lOMoARcPSD| 58833082
runme_error
error detected during runme
Ví dụ sử dụng <excepon>
try{ int* myarray= new int[1000]; // bad_alloc
}
catch (excepon& e){ cout << "Standard excepon: " <<
e.what() << endl;
}
return 0;
}
Ví dụ: try – catch8.cpp
// bad_allocstandard excepon
#include <iostream>
#include <excepon>
intmain () {
int* foo;
foo = new(nothrow) int[5];
if (foo == nullptr) {
// error assigning memory. Take measures.
}
lOMoARcPSD| 58833082
void readFloatFile(const string& leName, oat a[12])
{ ifstream istr; int i = 0; istr.open(leName.c_str());
if (istr.fail()) {
throw excepon(); // nen ra ham main()
} while
(!istr.eof())
{ istr>>a[i]; i =
i+1;
} // lename = "E:\\\\ncoso4\\\\side\\\\matran\\\\MATRAN.txt"; }
// hằng ký tự {\\backslash (\)} - ngạch ngang “\\” = \
Ví dụ: try_catch9.cpp
lOMoARcPSD| 58833082
Sử dụng I/O manipulators: include <iomanip>
Hệ thống I/O của C++ một cách thứ 2 sử dụng để định dạng
tham số của stream. Đây phương pháp sử dụng các hàm đặc
biệt, được gọi là manipulator
Manipulor
Purpose
Input/output
dec
Format numeric data in decimal
Input/output
hex
Format numeric data in hexadecimal
Input/output
oct
Format numeric data in octal
Input/output
setbase(int base)
Set the number base to base
Output
seill(int ch)
Set the ll character to ch
Output
seoags(long f)
Turn on the ags specied in f
Input/output
setprecision(int p)
Set the number of digits of precision
Output
lOMoARcPSD| 58833082
setw(int w)
Set the ed width to w
Output
ws
Skip leading whitespace
Input
reseosags(long f)
Turn o the ags specied in f
Input/output
hps://www.includehelp.com/cpp-tutorial/cpp-manipulators-endl-
setwsetprecision-se-cpp-programming-tutorial.aspx
Manipulator
Declaraon in
endl
iostream.h
setw
iomanip.h
setprecision
iomanip.h
se
iomanip.h
Cờ định dạng
lOMoARcPSD| 58833082
ios::le , ios::right, ios::internal (-**89) căn phải dấu bên
trái
ios::dec , ios::oct, ios::hex
ios::xed , ios::scienc ios::showpos
ios::uppercase ios::showpoint ios::showbase
Sử dụng trong các câu lệnh
seosags(ios::le)
reseosags(long f)
include<iomanip>
setw(int n) // như cout.width(int n)
setpecision(int n) // như cout.pecision(int n)
seill(char ch) // như cout. ll(char ch)
lOMoARcPSD| 58833082
setiosflags(long l) // như cout.setf(long f)
resetiosflags(long l) // như cout.unsetf(long f)
int i = 5;
//cout<<setw(10)<<i<<endl; // dat do rong cua so la 10, can
phai
cout.width(10);
cout<<i<<endl;
cout<<seosags(ios::le); // can tai
cout<<123<<endl;
cout<<seosags(ios::scienc); // dang khoa hoc e
cout<<setprecision(2);
cout<<123.45<<endl;
Tạo hàm riêng manipulator
Output funcon:
lOMoARcPSD| 58833082
ostream &manip_name(ostream &stream) { // code here
return stream;
}
input manipulator funcon
istream &manip_name(istream &stream)
{
// code here
return stream;
}
Biến stac – từ khóa stac
Biến kiểu stac là một biến vĩnh cửu trong hàm riêng hoặc trong
le.
Nó khác biến toàn cục bởi vì nó bên ngoài hàm hoặc le / 203.
lOMoARcPSD| 58833082
stac: tác động lên các biến cục bộ khác
Biến stac cục bộ
Khai báo : stac int count; // giống như const int count = 10;
stac int count = 10; // khởi đầu
Một biến cục bộ stac duy trì giá trị của nó giữa các lần gọi hàm
Ví dụ: stac cục bộ
stac toàn cục
Trao đi – vấn đề
C++: tạo ra các le .cpp, .h, và .exe.
.c Vấn đề:
lOMoARcPSD| 58833082
Số liệu (hàm, biến) giữa các le có thể liên kết
Làm thế nào là liên kết giữa các le?
B1. Tạo project – làm việc trên nhiều tệp
Các bước tạo project
lOMoARcPSD| 58833082
Link: extern (.cpp)
lOMoARcPSD| 58833082
Tkhóa extern: sử dụng khi một chương trình viết trên nhiều
tệp và các tệp này được dịch độc lập sau đó mới liên kết với nhau
để tạo thành chương trình khả thi (.exe)
Ví dụ: extern int b_chung;
Khai báo extern báo cho chương trình dịch biết biến b_chung đã
được định nghĩa đâu đó. Do đó, không cần cấp phát bnh
cho nó một lần nữa
dụ 1: trong trường hợp y trong le: addToprojet9_1.cpp
định nghĩa hàm ch của 2 biến x*y
extern int x, y; // gia trị x, y thay đổi dựa vào hàm main() int
func(){
return x*y;
}
Vị trí khai báo và phạm vi sử dụng của biến extern
lOMoARcPSD| 58833082
Ví dụ 2:
Vị trí khai báo extern:
Có thể ngoài các hàm
Có thể bên trong một hàm hoặc một khối lệnh.
Phạm vi sử dụng của biến extern (nguyên lý): Dù khai báo ở
đâu thì phạm vi sử dụng của biến extern (trên tệp chứa khai báo
y) được nh từ vị trí khai báo cho đến cuối tp.
Do đó: Mảng a có thể sử dụng trên toàn tệp
Biến x khai bao trong disp_xExtern(): chỉ sử dụng trong
hàm
TH1: Kết nối biến tổng thể không là hằng: (cpp)
//leA.cpp
//leB.cpp (le sử dụng)
// declaraon and denion
int i = 42;
// declaraon only same as i in FileA
extern int i;

Preview text:

lOMoAR cPSD| 58833082 Một số vấn đề TS. Trần Thanh Hải Đặt vấn đề
Một số vấn đề thường gặp
• Thực hiện phép chia a/b = ?, nếu b = 0.
• Khi cấp phát động dữ liệu nếu không được thì báo lỗi thế nào?
• Nếu file không mở được thì thông báo thế nào? lOMoAR cPSD| 58833082
Đối với ma trận:
• Nếu số chiều nhập vào lớn hơn số chiều trong khai báo?
• Nhân 2 ma trận không vuông nếu số cột của ma trận a không
bằng số hàng của ma trận b?
• Đây là những vấn đề ngoại lệ phát sinh ra trong quá trình lập cần
phải được hạn chế và đưa ra cảnh báo đối với người sử dụng
Phân loại các loại ngoại lệ
• Ngoại lệ thứ 1: do người lập trình bắt lỗi với các tình
huống riêng như: chia 0, vượt qua chỉ số mảng,… lOMoAR cPSD| 58833082
• Ngoại lệ thứ 2: do máy bắt lỗi đưa ra: ví dụ cấp phát
động, mở file… thì ta sử dụng trực tiếp lớp ngoại lệ
Xử lý ngoại lệ - try ….catch try{ // try block } catch( type1 arg){ // catch block } . . lOMoAR cPSD| 58833082 catch(typeN arg){ // catch block }
Xử lý ngoại lệ thường sử dụng để kết nối những lỗi rất nặng (chia 0) Ví dụ - try_catch_3.cpp
+ Khi xử lý được đưa ra, điều
khiển được chuyển cho catch, và khối try bị dừng.
+ Chương trình tiếp tục dòng lệnh
int main(){ cout<<"start \n"; trong catch
+ Tuy nhiên khối catch thường kết try{// bat dau khoi lenh
thúc bằng cách gọi exit(), abort().
cout<<"ben trong khoi lenh try \n"; throw 99;// dua ra mot loi
cout<<"Doan nay khong duoc goi \n"; } lOMoAR cPSD| 58833082
catch(int i){ // bat loi cout<<"Bat mot ngoai len -- gia tri i = "; cout<} cout<<"end \n"; }
Sử dụng nhiều câu lệnh catch – try_catch_4.cpp
• Có thể kết hợp một câu lệnh try với nhiều câu lệnh catch() try
{ if(test==0) throw "value is zero"; if(test==1) throw 10; if(test==2) throw 'a'; if(test==3) throw 123.23; }
catch(int i){ cout << "Caught an integer. " << i << endl; }
catch(double i){ cout << "Caught an double. " << i << endl;
} catch (char c) { cout << "Caught an char " << c << endl;
} catch(const char *str) { cout<<"bat mot xau ky tu (test = 0): str = "; cout< lOMoAR cPSD| 58833082 }
catch(...){ // bat toan bo loi neu tren thieu catch cho loai nao thi tat ca chu vao day
cout << "Caught one." << endl; } Rethrowing an exception try_catch_5.cpp
sử dụng một cảnh báo cho nhiều nơi void XHandler(){ try{ thr ow "hello"; }
catch(const char *) { cout<<"bat throw trong ham \n";
throw; // nem tro lai char * cho ben ngoai ham } } int main() { try{ XHandler(); } lOMoAR cPSD| 58833082
catch(const char * ){ cout<<"bat throw ngoai ham - trong ham main()\n“; } }
Ví dụ về ma trận (ngoại lệ 1)
try { nhapmat(a, row_a, col_a); nhapmat(b, row_b, col_b);
if (col_a!= row_b) { throw 1; }
tichMatran_AB(a,b,c,row_a, col_a); disp(c,row_a,col_b); } catch(int s) {
cout<<"Khong the thuc hien phep nhan tich 2 ma tran \n"; exit(1); } lOMoAR cPSD| 58833082
Ngoại lệ 2: exception - #include
• Tất cả các ngoại lệ được ném (throw) bởi các thành phần của thư
viện chuẩn C ++ exception, dẫn xuất từ lớp exception. exception description bad_alloc
thrown by new on allocation failure bad_cast
thrown by dynamic_cast when it fails in a dynamic cast bad_exception
thrown by certain dynamic exception specifiers bad_typeid thrown by typeid bad_function_call
thrown by empty function objects bad_weak_ptr
thrown by shared_ptr when passed a bad weak_ptr • Thông báo lỗi exception description logic_error
error related to the internal logic of the program lOMoAR cPSD| 58833082 runtime_error error detected during runtime Ví dụ sử dụng // bad_allocstandard exception int* foo; #include foo = new(nothrow) int[5]; if (foo == nullptr) { #include
// error assigning memory. Take measures. using namespace std; } intmain () {
try{ int* myarray= new int[1000]; // bad_alloc }
catch (exception& e){ cout << "Standard exception: " << e.what() << endl; } return 0; }
Ví dụ: try – catch8.cpp lOMoAR cPSD| 58833082
void readFloatFile(const string& fileName, float a[12])
{ ifstream istr; int i = 0; istr.open(fileName.c_str()); if (istr.fail()) {
throw exception(); // nen ra ham main() } while (!istr.eof()) { istr>>a[i]; i = i+1;
} // filename = "E:\\\\tincoso4\\\\side\\\\matran\\\\MATRAN.txt"; }
// hằng ký tự {\\backslash (\)} - ngạch ngang “\\” = \ Ví dụ: try_catch9.cpp lOMoAR cPSD| 58833082
Sử dụng I/O manipulators: include
• Hệ thống I/O của C++ là một cách thứ 2 sử dụng để định dạng
tham số của stream. Đây là phương pháp sử dụng các hàm đặc
biệt, được gọi là manipulator Manipulor Purpose Input/output dec
Format numeric data in decimal Input/output hex
Format numeric data in hexadecimal Input/output oct Format numeric data in octal Input/output setbase(int base) Set the number base to base Output setfill(int ch) Set the fill character to ch Output setioflags(long f)
Turn on the flags specified in f Input/output setprecision(int p)
Set the number of digits of precision Output lOMoAR cPSD| 58833082 setw(int w) Set the fied width to w Output ws Skip leading whitespace Input resetiosflags(long f)
Turn off the flags specified in f Input/output
https://www.includehelp.com/cpp-tutorial/cpp-manipulators-endl-
setwsetprecision-setf-cpp-programming-tutorial.aspx • Manipulator Declaration in endl iostream.h setw iomanip.h setprecision iomanip.h setf iomanip.h Cờ định dạng lOMoAR cPSD| 58833082 •
ios::left , ios::right, ios::internal (-**89) căn phải – dấu bên trái • ios::dec , ios::oct, ios::hex •
ios::fixed , ios::scientific ios::showpos •
ios::uppercase ios::showpoint ios::showbase •
Sử dụng trong các câu lệnh • setiosflags(ios::left) • resetiosflags(long f) include
setw(int n) // như cout.width(int n) •
setpecision(int n) // như cout.pecision(int n) •
setfill(char ch) // như cout. fill(char ch) lOMoAR cPSD| 58833082 •
setiosflags(long l) // như cout.setf(long f) •
resetiosflags(long l) // như cout.unsetf(long f) • int i = 5; • //cout<phai • cout.width(10); • cout<• cout<• cout<<123<• cout<• cout<•
cout<<123.45<Tạo hàm riêng manipulatorOutput function: lOMoAR cPSD| 58833082 •
ostream &manip_name(ostream &stream) { // code here return stream; } •
input manipulator function
istream &manip_name(istream &stream) { // code here return stream; }
Biến static – từ khóa static
• Biến kiểu static là một biến vĩnh cửu trong hàm riêng hoặc trong file.
• Nó khác biến toàn cục bởi vì nó bên ngoài hàm hoặc file / 203. lOMoAR cPSD| 58833082
• static: tác động lên các biến cục bộ khác
Biến static cục bộ
• Khai báo : static int count; // giống như const int count = 10;
• static int count = 10; // khởi đầu
• Một biến cục bộ static duy trì giá trị của nó giữa các lần gọi hàm
• Ví dụ: static cục bộ • static toàn cục
Trao đổi – vấn đề
• C++: tạo ra các file .cpp, .h, và .exe.
• .c • Vấn đề: lOMoAR cPSD| 58833082
• Số liệu (hàm, biến) giữa các file có thể liên kết
• Làm thế nào là liên kết giữa các file?
B1. Tạo project – làm việc trên nhiều tệp
• Các bước tạo project lOMoAR cPSD| 58833082 Link: extern (.cpp) lOMoAR cPSD| 58833082
• Từ khóa extern: sử dụng khi một chương trình viết trên nhiều
tệp và các tệp này được dịch độc lập sau đó mới liên kết với nhau
để tạo thành chương trình khả thi (.exe)
• Ví dụ: extern int b_chung;
• Khai báo extern báo cho chương trình dịch biết biến b_chung đã
được định nghĩa ở đâu đó. Do đó, không cần cấp phát bộ nhớ cho nó một lần nữa
• Ví dụ 1: trong trường hợp này trong file: addToprojet9_1.cpp
định nghĩa hàm tích của 2 biến x*y
extern int x, y; // gia trị x, y thay đổi dựa vào hàm main() int func(){ return x*y; }
Vị trí khai báo và phạm vi sử dụng của biến extern lOMoAR cPSD| 58833082 • Ví dụ 2:
Vị trí khai báo extern: Có thể ngoài các hàm
Có thể bên trong một hàm hoặc một khối lệnh.
Phạm vi sử dụng của biến extern (nguyên lý): Dù khai báo ở
đâu thì phạm vi sử dụng của biến extern (trên tệp chứa khai báo
này) được tính từ vị trí khai báo cho đến cuối tệp.
• Do đó: Mảng a có thể sử dụng trên toàn tệp
Biến x khai bao trong disp_xExtern(): chỉ sử dụng trong hàm
• TH1: Kết nối biến tổng thể không là hằng: (cpp) //fileA.cpp
//fileB.cpp (file sử dụng) // declaration and definition
// declaration only same as i in FileA int i = 42; extern int i;