//professional C++ 4th edition p 302
#include
#include
#include
#include
#include <string_view>
#include
#include
using namespace std;
std::vector readIntegerFile(std::string_view fileName){
std::ifstream inputStream(fileName.data());
if(inputStream.fail()){ // be omitted for(被省略了) brevity
// we failed to open the file: throw an exception(); // 为简洁起见省略
// not using " using namespace std; " 2020年05月19日 13时19分08秒
//错误:unable to find string literal operator ‘operator""s’ with ‘const char [21]’, ‘long unsigned int’ arguments
//6109 | const std::string error = "Unable to open file "s + fileName.data();
const std::string error = "Unable to open file "s + fileName.data();
throw std::invalid_argument(error);
}
std::vector<int> integers;
int temp;
while (inputStream >> temp){
integers.push_back (temp);
}
if(!inputStream.eof()) {
const std::string error = "Unable to open file "s + fileName.data();
throw std::runtime_error(error);
}
return integers;
}
class FileError : public exception{ //p303
public:
FileError (std::string_view fileName) : mFileName (fileName) {}
virtual const char* what() const noexcept override{
return mMessage.c_str();
}
std::string_view getFileName() const noexcept { return mFileName; }
protected:
void setMessage(std::string_view message) { mMessage = message; }
private:
std::string mFileName;
std::string mMessage;
};
int main(){
const std::string fileName = “IntegerFile.txt”;
std::vector myInts;
try{
myInts = readIntegerFile(fileName);
// } catch (const std::invalid_argument& e){ //(1)
// std::cout << e.what() << std::endl;
// return 1;
// } catch (const std::runtime_error& e){
// std::cout << e.what() << std::endl;
// return 2;
// }
// } catch (const exception & e){ //这一条替换上面的两条 p302 //(2)
// std::cerr << e.what() << std::endl;
// return 2;
// }
// 正确的做法:catch子句应按限制最多到限制最少的顺序出现.
/*p449
When more than one catch clause is used, the catch clauses are matched in syntactic order as they appear
in your code; the first one that matches, wins. If one catch is more inclusive than a later one, it will
match first, and the more restrictive one, which comes later, will not be executed at all. Therefore,
you should place your catch clauses from most restrictive(来源于拉丁语动词stringo, stringere, strinxi, stricitus(束缚)) to least restrictive in order. For example, suppose that you want to catch invalid_argument from readIntegerFile() explicitly, but you also want to leave the generic exception match for any other exceptions. The correct way to do so is like this:
} catch (const std::invalid_argument& e){ // List the derived class first
} catch (const exception & e){
std::cerr << e.what() << std::endl;
return 2;
}
// // 与上例子的顺序相反.
// } catch (const exception& e) { // 警告:类型为‘std::invalid_argument’的异常将会
// cerr << e.what() << endl;
// return 1;
// } catch (const invalid_argument& e ) {//警告:为‘std::exception’更早的处理者所捕获
// // Take some special action for invalid filenames.
// }
for (const auto& element : myInts) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
/*
#define show_log(tag, fmt, arg…) printf("[%s][%s:%d]: “fmt”\n", tag, func, LINE, ##arg)
C可以编译通过,而C++编译出标题错误。
说是C++11要求,当字符串跟变量连接的时候,必须fmt前后增加一个空格才行。
#define show_log(tag, fmt, arg…) printf("[%s][%s:%d]: " fmt “\n”, tag, func, LINE, ##arg)
//https://blog.csdn.net/fightingTony/article/details/62423217
错误信息最后的[-Wformat=]提醒
Ubuntu官网找到了原因:
NOTE: In Ubuntu 8.10 and later versions this option is enabled by default for C, C++, ObjC, ObjC++. To disable, use -Wformat=0.
然后在编译的时候改成了:gcc test.c -Wformat=0 就没问题了
Ubuntu官网的解释:http://manpages.ubuntu.com/manpages/oneiric/en/man1/gcc.1.html
/
//professional C++ 4th edition p 302
#include
#include
#include
#include
#include <string_view>
#include
#include
#include
using namespace std;
class FileError : public exception{ //p303
public:
FileError (std::string_view fileName) : mFileName (fileName) {}
virtual const char what() const noexcept override{
return mMessage.c_str();
}
std::string_view getFileName() const noexcept { return mFileName; }
protected:
void setMessage(std::string_view message) { mMessage = message; }
private:
std::string mFileName;
std::string mMessage;
};
class FileOpenError : public FileError{ // FileOpneError 打错了!! 要细致, 细心, 细微 锱铢必较
public: //故胜兵若以镒称铢,败兵若以铢称镒。张预注:“二十两为镒,二十四铢为两
FileOpenError(std::string_view fileName) : FileError(fileName){
setMessage("Unable to open "s + fileName.data());
}
};
class FileReadError : public FileError
{
public:
FileReadError(string_view fileName, size_t lineNumber)
: FileError(fileName), mLineNumber(lineNumber)
{
ostringstream ostr;
ostr << "Error reading " << fileName << " at line " << lineNumber;
setMessage(ostr.str());
}
size_t getLineNumber() const noexcept { return mLineNumber; }
private:
size_t mLineNumber;
};
std::vector readIntegerFile(std::string_view fileName){
std::ifstream inputStream(fileName.data());
if(inputStream.fail()){ // be omitted for(被省略了) brevity
throw FileOpenError(fileName);
}
std::vector<int> integers;
size_t lineNumber = 0;
while (!inputStream.eof()) {
string line;
getline(inputStream, line);
++lineNumber;
istringstream lineStream(line);
int temp;
while(lineStream >> temp){
integers.push_back(temp);
}
if(!lineStream.eof()) {
throw FileReadError(fileName, lineNumber);
}
}
return integers;
}
int main(){
const std::string fileName = “IntegerFile.txt”;
std::vector myInts;
try{
myInts = readIntegerFile(fileName);
} catch (const FileError & e){
std::cerr << e.what() << std::endl;
return 2;
}
for (const auto& element : myInts) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
/*
wannian07@wannian07-PC:~$ g++ -std=c++17 -o c17 c17.cpp
wannian07@wannian07-PC:~$ ./c17
3 4 5 6
*/