C + + STD: : invalid_argument application

  • 2020-04-01 21:29:07
  • OfStack

First of all, say that an invalid_argument is a class (class invalid_argument;) , its inheritance relationship is as follows

Exception -- -- -- -- -- -- -- -- > Logic_error -- -- -- -- -- -- -- -- -- > invalid_argument

Invalid_argument prototype is
 
class invalid_argument:public logic_error { 
public: 
explicit invalid_argument (const string& what_arg); 
}; 

It's in the stdexcept header file, in the STD namespace. Here's an example to use it
 
#include <iostream> 
#include <stdexcept> 

int main(int argc,char ** argv) 
{ 
try 
{ 
bool errorArgument; 
errorArgument=true; 
if(errorArgument) 
{ 
throw std::invalid_argument("occur error!"); 
} 
} 
catch(std::invalid_argument &ia) 
{ 
//What () inherits the function of the exception class for invalid_argument
std::cerr<<" Invalid_argument "<< ia.what()<<std::endl; 
} 

return 0; 
} 

The running result is:

Invalid_argument occur error! So this is the simplest application. Invalid_argument just as its name implies refers to the invalid parameters, this should be applied in checking parameter is invalid, general inspection parameters used for specific functions and classes, so it should be to the member variables of the class assignment or a function parameter assignment, the validity of inspection of the value assigned to them, for example, have a class (people, there are three member variable name, age, height), then we know that people aged between 0 ~ 150 (ps: if the programmer can direct definition of 0 ~ 75). Height 0~300cm, the length of the name will not exceed 20. If they exceed these ranges, they are considered invalid. This class can be defined as follows:
 
#include <stdexcept> 
#include <iostream> 
#include <string> 

class People 
{ 
public: 
People(const std::string& n,const int& a,const int& h) 
:name(n),age(a),height(h) 
{} 

inline void set(const std::string& n,const int& a,const int& h) 
{ 
if(!valid(n,a,h)) 
{ 
throw std::invalid_argument("People's argument is error"); 
} 
name = n; 
age = a; 
height = h; 
} 

inline bool valid(const std::string& n, const int& a, const int& h) 
{ 
return ( n.length() == 0 ||n.length() > 20 )&& a >= 0 && a< 150 && h > 0 && h < 300 ; 
} 
private: 
std::string name; 
int age; 
int height; 

}; 

int main(int argc, char** argv) 
{ 
People p("Li San", 20 , 170); 
try 
{ 
p.set("Li San" , 20 ,1700); 
} 
catch (std::invalid_argument & ia) 
{ 
std::cerr << "Error: " << ia.what() << std::endl; 
} 
return 0; 
} 

The operation result is as follows:

As long as the program above inputs invalid data, it will output an Error. But this is not enough, we can not locate the invalid parameters in which file with which line or in which function, if the printing error with the information output believe that the location problem is much more convenient. So it's a lot clearer when we're reporting an error message that we're attaching to it.
 
#include <stdexcept> 
#include <iostream> 
#include <string> 
#define TOSTRING(x) #x 

//class ErrorInfo 
//{ 
// public: 
// ErrorInfo(const std::string& f,const std::string& l,const std::string& fun) 
// : file(f), line(l), func(fun) 
// {} 
// 
// inline const std::string getFile() const 
// { 
// return this->file; 
// } 
// 
// inline const std::string getLine() const 
// { 
// return this->line; 
// } 
// 
// inline const std::string getFunc() const 
// { 
// return this->func; 
// } 
// 
// private: 
// const std::string file; 
// const std::string line; 
// const std::string func; 
//}; 

class ErrorInfo 
{ 
public: 
ErrorInfo(const char * f, const char * l, const char * fun) 
:file(f), line(l), func(fun) 
{} 

inline std::string getFile() const 
{ 
return this->file; 
} 

inline std::string getLine() const 
{ 
return this->line; 
} 

inline std::string getFunc() const 
{ 
return this->func; 
} 
private: 
const char* file; 
const char* line; 
const char* func; 
}; 

std::string operator +(const std::string & str, const ErrorInfo& ei) 
{ 
std::string strTemp(ei.getFile() + ":" + ei.getLine() + ":" + ei.getFunc()); 
strTemp +=str; 
return strTemp; 
//return str::string(ei.getFile() + ":" + ei.getLine() + ":" + ei.getFunc() += str ); 
} 

class InvalidPeople:public std::invalid_argument 
{ 
public: 
InvalidPeople(ErrorInfo & ei) 
: std::invalid_argument( "Invalid People " + ei ) 
{} 
~InvalidPeople() throw() 
{} 
}; 

class People 
{ 
public: 
People(const std::string& n,const int& a,const int& h) 
:name(n),age(a),height(h) 
{} 

inline void set(const std::string& n,const int& a,const int& h) 
{ 
if(!valid(n,a,h)) 
{ 
ErrorInfo ei(__FILE__,TOSTRING(__LINE__),__PRETTY_FUNCTION__); 
// ErrorInfo ei(__FILE__,#__LINE__,__PRETTY_FUNCTION__); 
throw InvalidPeople(ei); 
// throw InvalidPeople(ErrorInfo(__FILE__,TOSTRING(__LINE__),__PRETTY_FUNCTION__)); 
} 
name = n; 
age = a; 
height = h; 
} 

inline bool valid(const std::string& n, const int& a, const int& h) 
{ 
return ( n.length() == 0 ||n.length() > 20 )&& a >= 0 && a< 150 && h > 0 && h < 300 ; 
} 
private: 
std::string name; 
int age; 
int height; 

}; 

int main(int argc, char** argv) 
{ 
People p("Li San", 20 , 170); 
try 
{ 
p.set("Li San" , 20 ,1700); 
} 
catch (std::invalid_argument & ia) 
{ 
std::cerr << "Error: " << ia.what() << std::endl; 
} 
return 0; 
} 

The operation result is as follows:

Invalid People::set(const STD ::string&, const int&, const int&)
(1) the #define TOSTRING(x) #x above converts int to const char *.
(2) s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s
You can see that the trip number is not shown here because the compiler directly converts s/s to the string "s/s/s/s/s/s/s. I tried a lot of methods, and finally found out, we can in the #define once, can be normal reality. The following code
 
#include <stdexcept> 
#include <iostream> 
#include <string> 
#define TTOSTRING(x) #x 
#define TOSTRING(x) TTOSTRING(x) 
... 
... 
//The code is the same as above

The operation result is as follows:

TestError: invalid_a.cpp:91:void People::set(const STD ::string&, const int&, const int&)Invalid People
As for the inside principle, why it is possible to convert the number of s/s represented by s/s to const char* "71" twice instead of "s/s/s "const char* * * instead of s/s/s s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s/s.

Related articles: