板凳——————————————————c++(27)

这篇博客探讨了C++中处理文件读取异常的方法,包括自定义异常类FileError、FileOpenError和FileReadError。示例展示了如何从输入文件读取整数并抛出自定义异常,以及如何在main函数中捕获这些异常。
摘要由CSDN通过智能技术生成

//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
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值