语句(switch,异常,NDEBUG,assert)

  • while(cin >>xxx) 可以输入后立即判

  • switch
  • default语句,即使没有什么要执行的,也要加上,后面用空语句填上,

    告诉读者这种情况已经考虑到了,只是没有必要执行。

  • case后必须是整型常量
  • 对于 switch 结构,只能在它的最后一个 case 标号或 default 标号后面定义变量:
    回顾变量的作用域,变量从它的定义点开始有效,直到它所在块结束为止。现在
    考虑如果在两个 case 标号之间定义变量会出现什么情况。 该变量会在块结束之
    前一直存在。对于定义该变量的标号后面的其他 case 标号,它们所关联的代码
    都可以使用这个变量。如果 switch 从那些后续 case 标号开始执行,那么这个
    变量可能还未定义就要使用了。

    在这种情况下,如果需要为某个特殊的 case 定义变量,则可以引入块语句,在
    该块语句中定义变量,从而保证这个变量在使用前被定义和初始化。

    加{}后,后序的case再定义该变量时不会出现重定义。
  • 用while和指针赋值数组


  • 编写一个小程序,从标准输入读入一系列 string 对象,
    寻找连续重复出现的单词。程序应该找出满足以下条件的
    单词的输入位置:该单词的后面紧跟着再次出现自己本
    身。跟踪重复次数最多的单词及其重复次数。输出重复次
    数的最大值,若没有单词重复则输出说明信息。例如,如
    果输入是:
    how, now now now brown cow cow
    则输出应表明“now”这个单词出现了三次。

     1 #include <iostream>
     2 using namespace std;
     3 int main()
     4 {
     5     string cur, pre,store;
     6     int cur_cnt = 0, max_cnt = 0;
     7     while (cin >> cur && cur != "exit")
     8     {
     9         if (cur == pre)
    10         {
    11             ++cur_cnt;
    12             if (cur_cnt > max_cnt)
    13             {
    14                 max_cnt = cur_cnt;
    15                 store = cur;
    16             }
    17         }
    18         else
    19         {
    20             cur_cnt = 1;
    21             pre = cur;
    22         }
    23     }
    24     cout << store <<":" << max_cnt;
    25     return 0;
    26 }
    View Code

     

  •  try 块和异常处理
    http://c.biancheng.net/view/422.html

  • throw
    抛出异常
    1 // first check that data is for the same item
    2 if (!item1.same_isbn(item2))
    3 throw runtime_error("Data must refer to same ISBN");
    4 // ok, if we're still here the ISBNs are the same
    5 std::cout << item1 + item2 << std::endl; 
  • try
    处理异常
    try {
    program-statements
    } catch (exception-specifier(异常说明符)) {
    handler-statements
    } catch (exception-specifier) {
    handler-statements
    } //... 

     

  • catch(...)捕捉任何异常,其后面所有的catch都无效了,所以要放在其他catch后面

  •  1 #include <iostream>
     2 using namespace std;
     3 int main()
     4 {
     5     int m,n;
     6     cin >> m >> n;
     7     try
     8     {
     9         if(n == 0)
    10             throw -1;
    11             else
    12                 throw 1.0;
    13     }
    14     catch(int i)
    15     {
    16         cout << " catch(int)" <<endl;
    17     }
    18         catch(...)
    19     {
    20         cout << "catch(...)" <<endl;
    21     }
    22     cout << "finished"<<endl;
    23     return 0;
    24 }


    如果catch(...)放在前面,报错


  •  bad_cast:类型转换不安全时抛出,如从多态基类对象(或引用)到派生类的引用的强制类型转换

     1 #include <iostream>       // std::cout
     2 #include <typeinfo>       // std::bad_cast
     3 
     4 class Base {virtual void member(){}};
     5 class Derived : Base {};
     6 
     7 int main () {
     8   try
     9   {
    10     Base b;
    11     Derived& rd = dynamic_cast<Derived&>(b);
    12   }
    13   catch (std::bad_cast& bc)
    14   {
    15      std::cerr << "bad_cast caught: " << bc.what() << '\n';
    16   }
    17   return 0;
    18 }

     

  • bad_alloc:申请内存空间失败时抛出此类异常
     1 // bad_alloc example
     2 #include <iostream>     // std::cout
     3 #include <new>          // std::bad_alloc
     4 
     5 int main () {
     6   try
     7   {
     8     int* myarray= new int[10000000000000000000000000];
     9   }
    10   catch (std::bad_alloc& ba)
    11   {
    12     std::cerr << "bad_alloc caught: " << ba.what() << '\n';
    13   }
    14   return 0;
    15 }

     

  • out_of_range:下标越界异常
    1 对于vector v;
    2 非空时,v[i]与v.at(i)等价
    3 下标越界时,v.at(i)可抛出out_of_range异常,
     1 #include <iostream>
     2 #include <stdexcept>
     3 #include <vector>
     4 #include <string>
     5 using namespace std;
     6 int main()
     7 {
     8     vector<int> v(10);
     9     try {
    10         v.at(100) = 100;  //拋出 out_of_range 异常
    11     }
    12     catch (out_of_range & e) {
    13         cerr << e.what() << endl;
    14     }
    15     string s = "hello";
    16     try {
    17         char c = s.at(100);  //拋出 out_of_range 异常
    18     }
    19     catch (out_of_range & e) {
    20         cerr << e.what() << endl;
    21     }
    22     return 0;
    23 }

     

     

     

  • <stdexcept> 头文件中定义的标准异常类
  • exception 最常见的问题。  
    runtime_error 运行时错误:仅在运行时才能检测到问题
    range_error 运行时错误:生成的结果超出了有意义的值域范围
    overflow_error 运行时错误:计算上溢
    underflow_error 运行时错误:计算下溢
    logic_error 逻辑错误:可在运行前检测到问题
    domain_error 逻辑错误:参数的结果值不存在
    invalid_argument 逻辑错误:不合适的参数
    length_error 逻辑错误:试图生成一个超出该类型最大长度的对象
    out_of_range 逻辑错误:使用一个超出有效范围的值

  • 异常类型只定义了一个名为 what 的操作。这个函数不需要任何参数,并且
    返回 const char* 类型值。 
    what 函数所返回的指针指向 C 风格字符数组的内容,这个数组的内容依赖
    于异常对象的类型。对于接受 string 初始化式的异常类型,what 函数将返回
    该 string 作为 C 风格字符数组。对于其他异常类型,返回的值则根据编译器
    的变化而不同

     

  • NDEBUG 和 assert()
     1 #include<iostream>
     2 #include <cassert>
     3 using namespace std;
     4 int main()
     5 {
     6 #ifndef NDEBUG
     7     cerr << "starting main" << endl;
     8 #endif
     9     int x, y;
    10     cin >> x >> y;
    11     assert(y != 0);//表达式true,不执行,否则终止
    12 
    13 #ifndef NDEBUG
    14         cerr << "end" << endl;
    15 #endif
    16     return 0;
    17 }

     

  • 定义NDEBUG后,以上assert无效

    1 在开头加#define NDEBUG后

     

     可见assert失效,开头和结尾的语句消失

  • 预处理器还定义了其余四种在调试时非常有用的常量:
    __FILE__ 文件名
    __LINE__ 当前行号
    __TIME__ 文件被编译的时间
    __DATE__ 文件被编译的日期
    可使用这些常量在错误消息中提供更多的信息
     1 #define NDEBUG
     2 #include<iostream>
     3 #include <cassert>
     4 using namespace std;
     5 int main()
     6 {
     7 #ifndef NDEBUG
     8     cerr << "starting main" << endl;
     9 #endif
    10     int x, y;
    11     cin >> x >> y;
    12     if (y == 0)
    13     {
    14         cout << __FILE__ << endl
    15         <<__LINE__<< endl
    16         << __DATE__ << endl
    17         << __TIME__ << endl;
    18     }
    19 
    20 #ifndef NDEBUG
    21         cerr << "end" << endl;
    22 #endif
    23     return 0;
    24 }

     


  •  1 //习题6.26
     2 string s;
     3 while (cin >> s) {
     4 assert(cin);
     5 // process s
     6 }
     7 //习题6.27
     8 string s;
     9 while (cin >> s && s != sought) { } // empty body
    10 assert(cin);
    11 // process S
    如果cin出错while循环就已经退出,执行不到assert


posted @ 2020-06-17 23:16  幻想Elapse  阅读(248)  评论(0编辑  收藏  举报