C++Primer第6章学习笔记

1. 空块,用一对内部没有语句的花括号实现:

while(cin>>s&&s!=sought){} //empty block

2. 对于在控制语句中定义的变量,限制其作用域的一个好处是,这些变量名可以重复使用而不必担心他们的当前值在每一次使用时是否正确。

vector<int>::size_type index = 0;
for(; index != vec.size(); ++index)
//as before
    if(index != vec.size()) //ok:now index is in scope
//as before

3.一个类类型能否用在条件表达式中取决于类本身。 在所有用过的类型中,IO类型可以用作条件,但vector类型和string类型一般不可用做条件。

4.对于switch结构,只能在它的最后一个case标号或default标号后面定义变量:

case true:
   //error:declaration precedes a case label
    string file_name = get_file_name();//该变量会在整switch块内一直存在
                                       //如果语句跳过true执行后面
                                        //的语句则file_name就出现未定义就使用的情况。
    break;
case false:
   file_name;
   break;
制定这个规则是为了避免出现代码跳出变量的定义和初始化的情况。

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

5.将一个数组的内容复制到另一个数组中:

//arr1 is array of ints
int *source = arr1;
size_t sz = sizeof(arr1) / sizeof(*arr1);
int *dest = new int[sz];
while(source != arr1 + sz)
    *dest++ = *source++;
6.do while语句

任何在循环条件中引用的变量都必须在do语句之前就已经存在。不可采用如下方式定义变量:

do
{
    cal(foo); //foo在循环体外就不存在了
}
while(int foo == val());
string rsp;//在do语句之前定义
do
{
    cout << "please enter two values:"
         int val1, val2;
    cin >> val1 >> val2;
    cout << val1 + val2 << "\n\n"
         << "More?[yes][no]";
    cin >> rsp;
}
while(!rsp.empty() && rsp[0] != '\n');
7. tyr块和异常处理(这一块不懂)

在通信交换机和路由器这类长期运行的交互式必须将90%的程序代码用于实现错误检测和错误处理。

C++异常处理包括以下几不部分:

* throw表达式,错误检测部分使用这种表达式来说明遇到了不可处理的错误。

*try块,错误处理部分使用它来处理异常。try语句块以try关键字开始,并以一个或多个catch子句结束。在try块中执行的代码所抛出的异常,通常会被其中一个catch子句处理。

*异常类,用来在throw和相应的catch之间传递有关的错误信息。

//throw
Sales_item item1, item2;
cin >> item1 >> item2;
if(item1.same_isbn(item2))
{
    cout << item1 + item2 << endl;
    return 0;
}
else
{
    cerr << "Data must refer to same ISBN" << endl;
    return -1;
}

修改部分:

if(!item1.same_isbn(item2))
    throw runtime_error("Data must refer to same ISBN");
cout << item1 + item2 << endl;
//编写try块处理代码,与用户交互的部分处理所捕获的异常:

while(cin >> item1 >> item2)
{
    try
    {
        //execute code that will add the two Sales_itmes
        //if the addition fails,the code throws a runtime_error exception
    }
    catch(runtime_error err)
        //remind the user that ISBN must match and prompt for another pair
    {
        cout << err.what()
             << "\nTyr again?Enter y ro n" << endl;
        char c;
        cin >> c
            if(cin && c == 'n')
                break;
    }
}
what是runtime_error类的一个成员函数,这个函数不需要参数,返回C风格字符串。 在出现runtime_error的情况下,what返回的C风格字符串,是用于初始化runtime_error的string对象的副本。(?)
如果不存在处理异常的catch子句,程序的运行就要跳转到名为terminate的标准库函数,该函数在exception头文件中定义。

8.标准异常

标准库异常类只提供了很少的操作,包括创建、复制异常类型对象以及异常类型对象的赋值。exception、bad_alloc以及bad_cast类型只定义了默认构造函数。无法在创建这些类型的对象时为它们提供初值。其他的异常类型则只定义了一个使用string初始化式的构造函数。当需要定义这些异常类型的对象时,必须提供一个string参数。string初始化式用于为所发生的错误提供更多的信息。
异常类型只定义了一个名为what的操作。这个函数不需要任何参数,并且返回const char*类型的值。它返回的指针指向一个C风格字符串;使用C风格字符串的目的是为所抛出的异常提供更详尽的文字描述。
what函数所返回的指针指向C风格字符数组的内容,这个数组的内容依赖于异常对象的类型。对于接受string初始化的异常类型,what函数将返回string作为C风格字符数组。对于其他异常类型,返回值则根据编译器不同而不同。

例:

#include <iostream>
#include <exception>
#include <stdexcept>
#include <new>
using namespace std;
//=============================
int main()
{
    int int_arr[3] = {1, 2, 3};
    try
    {
        for(int i = 0; i <= 5; i++)
        {
            if(i < 0 || i > (sizeof(int_arr) / sizeof(int)))
                throw out_of_range("下标越界了");
            int_arr[i] = i * i;
            cout << "this element is " << int_arr[i] << endl;
        }
    }
    catch(range_error error)
    {
        cout << "this is a range_error: " << error.what() << endl;
    }
    catch(out_of_range error)
    {
        cout << "this is a out_of_range: " << error.what() << endl;
    }
    return 1;
}
9.使用预处理器进行调试
1)C++使用NDEBUG预处理变量实现有条件的调试代码:

int main()
{
      #ifdef NDEBUG
      cerr<<"starting main"<<endl;
      #endif
      //.......
}
如果NDEBUG未定义程序就会将错误信息写到cerro中,如果NDEBUG已定义,程序运行时将会跳过#ifndef和#endif。
默认情况下NDEBUG未定义,也就意味着#ifndef,#endif之间的代码必须执行。开发完成后,要将程序交给客户时,可通过定义NDEBUG预处理变量,有效的删除这些调试语句。

/************************摘抄*********不是很明白
这里要将NDEBUG与vc中的_DEBUG区别开。VC定义_DEBUG有其用途, 它控制其它宏比如 _ASSERT的行为, 但与assert 无关。assert是ANSI C标准的断言宏,_ASSERT是VC提供的众多断言相关的宏中的一个。虽然做Windows下开发的会注意到VC编译选项Release版都有一个NDEBUG宏, 但这个宏的引入不是微软特定的。而是在ANSI C中定义的。在vs中使用debug模式,默认情况下将定义_DEBUG。使用release模式,默认情况下将定义NDEBUG。
*********************************************/

2)预处理器还定义了四种在调试时非常有用的常量:

_ _FILE_ _ 文件名
_ _LINE_ _ 当前行号
_ _TIME_ _ 文件被编译的时间
_ _DATE_ _ 文件被编译的日期
if (word.size() < treshold)
cerr << "Error: " << _ _FILE_ _ 
<< " : line " <<_ _LINE_ _  << endl;
<< "Compliled on " << _ _DATE_ _
<< " at " << _ _TIME_ _ << endl
<< " Word read was " << word
<< " : Length too short" << endl;
3)另一个常见的调试技术是使用NDEBUG预处理变量以及assert预处理宏。assert宏是在cassert头文件中定义。
assert(expr)// 只要NDEBUG未定义,就求解expr,为非零值时,assert不做任何操作
            //为false时,assert输出信息并且终止程序的执行
与异常不同(异常用于处理程序执行时预期要发生的错误),程序员使用assert来测试“不可能发生”的条件。例如,对于处理输入文本的程序,可以预测全部 给出的单词都比指定的阈值长。那么程序可以包含这样一个语句:assert(word.size() > threshold);
在成品代码中,assert语句不做任何工作,因此没有任何运行时代价。assert仅用于检查确实不可能的条件,这只对程序调试有帮组,但不能用来的替代运行时的逻辑检查,也不能代替对程序可能产生的错误的预测。

部分习题:
/***********************************************
时间:2013-7-31
题目:
编写一个小程序,从标准输入读入一系列string对象,寻找连续重复出现的单词。程序应该找出满足以下条件的单词的输入位置:该单词的后面紧跟着再次出现自己本身,
跟 踪重复次数量多的单词及其重复次数.输出重复次数的最大值,
例如.如果输入是:
how now now now brown cow cow
则输出表明now这个单词出现了三次
**************************************************/

#include <iostream>
#include <vector>
#include <string>
using namespace std;
int find_max(vector<int>&ivec);

int main()
{
    vector<string> svec;
    vector<int> ivec; //保存重复单词出现的次数
    vector<string>::iterator iter;
    vector<int>::size_type ix = 0;
    string s;
    int s_ct = 0; //相同单词的数目
    bool flag = true; //标记相等的单词

    cout << "enter string:(ctrl+z to quit)" << endl;
    while(cin >> s)
        svec.push_back(s);

    iter = svec.begin();
    while(iter != svec.end())
    {
        flag = true;
        if((*iter == *(iter + 1)) && flag) //越界问题
        {
            flag = true;
            s_ct++;
        }
        else
        {
            flag = false;
            ivec[ix++] = s_ct + 1;  //?
            s_ct = 0;
        }
        iter++;
    }
	int x=find_max(ivec);
    cout << "重复次数最多的单词的次数:" << x << endl;

    return 0;
}
int find_max(vector<int>&ivec)
{
    vector<int>::size_type ix = 0;
    int max_ct = ivec[0];

    for(ix = 1; ix != ivec.size(); ++ix)
        if(ivec[ix] > max_ct)
            max_ct = ivec[ix];
    return max_ct;
}
下面是参考答案,string没有必要用vector存着,而且次数也不用容器存储,但是如果出现相同次数的单词,这个答案就有问题了

int main()
{
    string preWord, currWord; //当前输入的单词及其前一单词
    string repWord;//重复次数最多的单词
    //当前单词的重复次数及单词重复次数的最大值
    int currCnt = 0, maxCnt = 1;

    cout << "enter some words(Ctrl+z to ene):" << endl;
    while(cin >> currWord)
    {
        if(currWord == preWord) //当前单词是重复出现
            ++currCnt;
        else  //当前单词不是前一单词的重复出现
        {
            if(currCnt > maxCnt)
            {
                maxCnt = currCnt;
                repWord = preWord;
            }
            currCnt = 1;
        }
        preWord = currWord; //修改对前一单词的记录
    }
    if(maxCnt != 1) //有单词重复
        cout << '"' << repWord << '"'
             << "repeated for " << maxCnt
             << "times." << endl;
    else
        cout << "there is no repeated word." << endl;
    return 0;
}
/*******************************************
时间:2013-8-1
习题:给出2个int型的vector对象,编写程序判断一个对象是否是另一个对象的前缀。如果两个vector对象的长度不相同,假设较短的vector对象长度为n,则只对两个对象的前面n个元素做比较。例如,对于{0,1,1,2}和{0,1,1,2,3,5,8}这两个vector,你的程序应该返回ture.
****************************************************/

#include <iostream>
#include <vector>
using namespace std;
bool Comp_Vect(vector<int>ivec1, vector<int>ivec2);

int main()
{
    vector<int>ivec1;
    vector<int>ivec2;
    vector<int>::size_type ix;
    int ival;

     //不要用ctrl+z结束输入,第二次循环时要将流cin恢复为有效状态(使用cin.clear())
    cout << "enter numbers of ivec1:(ctrl+z to end):" << endl;
    while(cin >> ival)
        ivec1.push_back(ival);
    cout << "enter numbers of ivec2:(ctrl+z to end):" << endl;
    cin.clear();//add 将流恢复有效状态
    while(cin >> ival)
        ivec2.push_back(ival);
//    cout << "enter numbers of ivec1:"<<endl;
//    for(ix=0;ix!=4;++ix)
//    {
//          cin>>ival;
//          ivec1.push_back(ival);
//    }
//    cout << "enter numbers of ivec2:"<<endl;
//    for(ix=0;ix!=7;++ix)
//    {
//          cin>>ival;
//          ivec2.push_back(ival);
//    }
    if(Comp_Vect(ivec1, ivec2))
        cout << "一个对象是另一个对象的前缀" << endl;
    else
        cout << "一个对象不是另一个对象的前缀" << endl;

    return 0;
}
bool Comp_Vect(vector<int>ivec1, vector<int>ivec2)
{
    vector<int>::size_type ix = 0;

    for(; ix != ivec1.size() || ix != ivec2.size(); ++ix)
        if(ivec1[ix] == ivec2[ix])
            continue;
        else
            break;
    if(ix == ivec1.size() || ix == ivec2.size())
        return true;

    return false;
}
注:在用while()循环输入第二个容器的元素时,程序会死掉,需要将流cin恢复为有效状态(使用cin.clear())(具体原因暂未知)。

建议用下列方法输入:

for(ix=0;ix!=4;++ix)
 {
         cin>>ival;
         ivec1.push_back(ival);
 }
答案中写的比较好的地方:

//比较两个vector对象
vector<int>::size_type size1, size2;
size1 = ivec1.size();
size2 = ivec2.size();
bool result = true;
for(vector<int>::size_type ix = 0;
        ix != (size1 > size2 ? size2 : size1); ++ix)
    if(ivec1[ix] != ivec2[ix])
    {
        result = false;
        break;
    }
    
if(result)
{
    //输出结果........
}
/*******************************************
时间:2013-8-1
习题:编写一个小程序,由用户输入两个 string 对象,然后报告哪个 string 对象按字母排列次序而言比较小也就是说,哪个的字典序靠前)。继续要求用户输入,直到用户请求退出为止。请使用 string 类型、string 类型的小于操作符以及 do while 循环实现。
Q1:退出条件?while()
定义一个字符串,存储提示信息。
while(s3[0]!='n'&&s3[0]!='N')
****************************************************/

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string s1, s2, s3;

    do
    {
        cout << "enter string:" << endl;
        cin >> s1 >> s2;
        cout << (s1 > s2 ? "string s2 is smaller" : "string s1 is smaller") << endl;
        cout << "More?[yes][no]" ;
        cin >> s3;
    }
    while(s3[0] != 'n' && s3[0] != 'N');

    return 0;
}

/*****************************************
时间:2013-8-1
题目:编写程序从标准输入读入一系列 string 对象,直到同一个单词连续出现两次,
或者所有的单词都已读完,才结束读取。
请使用 while 循环,每次循环读入一个单词。
如果连续出现相同的单词,便以 break 语句结束循环,
此时,请输出这个重复出现的单词;
否则输出没有任何单词连续重复出现的信息。
Q1:
输入:a
      b
      c
输出:the repeated is:c(error)?
while循环最后把currword的值赋给preword,所以
preword==currword输出c?
currword=' ';//修改部分
***************************************************/
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    string preword, currword;
    //int w_ct = 0;

    cout << "enter string:" << endl;
    while(cin >> currword)
    {
        if(preword == currword)
        {
           // ++w_ct;
           // if(2 == w_ct) //不用计数
                break;
        }
        else
            //w_ct =1;
        preword = currword;
        currword=' ';//修改部分
    }
    if(preword==currword)
     cout<<"the repeated word is:"<<currword<<endl;
     else
     cout<<"there is no repeatd word."<<endl;

    return 0;
}

/*********************************
时间:2013-8-1
修改第 6.11 节习题所编写的程序,使其可以有条件地输出运行时的信息。
例如,可以输出每一个读入的单词,用来判断循环是否正确地找到第一个连续出现的以大写字母开头的单词。
分别在打开和关闭调试器的情况下编译和运行这个程序。
注:这题没太明白?
****************************************/
#include <iostream>
#include <cstring>
using namespace std;

int main()
{
    string preword, currword;
    cout << "enter some words:(ctrl+z to end):" << endl;
    while(cin >> currword)
    {
        //若未定义NDEBUG,则输出读入的单词
#ifndef NDEBUG
        cout << currword << " ";
#endif
        if(!isupper(currword[0])) //单词不是以大写字母开头
            continue;
        if(currword == preword)
            break;
        else
            preword = currword;
        currword = ' '; //修改部分
    }
    if(currword == preword && !currword.empty())
        cout << "the repeated word:" << currword << endl;
    else
        cout << "there is no repeated word." << endl;


    return 0;
}

这道题没太明白。




























































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值