[Essential C++ notes] Chapter 1 C++ 编程基础

原书:Essential C++, Stanley B. Lippman, 电子工业出版社, 2013.
章节:第1章 C++编程基础
环境:CLion + MinGW

写在前面:最近看了《C++ Primer》和《Essential C++》的前几章,就这一小部分内容来说,两者都要求一定的编程语言基础,前者的特点是非常全面且按部就班地介绍C++语法规则,而后者以具体案例引导,迅速介绍了常用的各种基本内容(类与对象、表达式、流程控制、vector对象、文件读写等)

总的来说,《Essential C++》更适合具有C语言基础,并迫切希望迅速上手C++的读者阅读


1.1 如何撰写C++程序
  1. 函数

    (1) 由四部分组成:函数名、返回类型、参数列表、函数体

    (2) main函数返回类型为int,习惯上当程序正确执行时返回0,程序执行出错时返回非零值

    (3) main并非C++定义的关键字,但编译器将从main()函数开始执行程序

  2. (1) 类是用户自定义的数据类型

    (2) 数据的输入输出并非C++程序语言本身定义的一部分,而是由C++的一套面向对象的类层次体系提供支持,并作为C++标准库的一员

    (3) 面向对象的类层次体系定义了整个家族体系的各相关类型,如终端与文件输入设备、终端与文件输出设备

  3. string类

    #include <iostream>
    #include <string>
    using namespace std;
    int main(){
    	string name;
        cin >> name;
        cout << "Hello" << name << endl;
    	return 0;
    }
    
  4. using namespace std

    (1) using和namespace都是C++中的关键字,std是标准库所驻之命名空间的名称,标准库所提供的任何事物都封装在命名空间std内

    (2) 命名空间(namespace)是一种将库名称封装起来的方法,可以避免和应用程序发生命名冲突的问题

1.2 对象的定义与初始化
  1. 构造函数语法

    int num_tries(0);
    // int num_tries = 0;
    

    构造函数初始化语法可用于多指初始化

    #include <complex>
    complex<double> purei(0, 1);	// 定义复数0 + 1i
    
  2. 转义字符

    '\n'	换行符
    '\t'	制表符
    '\0'	null
    '\''	单引号
    '\"'	双引号
    '\\'	反斜线
    
1.3 表达式
  1. 算术运算符:+ - * / %

  2. 条件运算符

    int cnt = 1;
    const int lineSize = 8;
    cout << (cnt % lineSize ? ' ' : '\n');
    // 如果余数运算结果不为零,结果为' ',反之为'\n'
    
  3. 复合赋值运算符:+= -= *= /= %=

  4. 递增运算符和递减运算符:++ –

    (1) 前置形式

    int cnt = 0;
    cout << ++cnt;
    

    原值先递增或递减,再被拿来使用,故输出1

    (2) 后置形式

    int cnt = 0;
    cout << cnt++;
    

    原值先被使用,再递增或递减,故输出0

  5. 关系运算符:== != < > <= >=

  6. 逻辑运算符:|| && !

    服从短路求值法,若表达式的值已确定便不再对剩下的条件表达式求值

    bool condition1 = true, condition2 = false;
    if(condition1 || condition2){
        // 由condition1为真可确定结果为真, 无需对condition2求值
    }
    if(condition2 && condition1){
        // 由condition2非真可确定结果非真, 无需对condition1求值
    }
    
  7. 运算符的优先级(从高到低)

    逻辑运算符NOT

    算术运算符(*, /, %)

    算术运算符(+, -)

    关系运算符(<, >, <=, >=)

    关系运算符(==, !=)

    逻辑运算符AND

    逻辑运算符OR

    赋值运算符

1.4 条件语句和循环语句
  1. switch语句

    switch(num_tries){
    	case 1:
    		cout << "Oops! Nice guess but not quite it" << endl;
    		break;
    	case 2:
    		cout << "Hmm. Sorry. Wrong a second time." << endl;
    		break;
    	case 3:
    		cout << "Ah, this is harder than it looks, isn't it?" << endl;
    		break;
    	default:
    		cout << "It must be getting pretty frustrating by now!" << endl;
    		break;
    }
    

    若某个case标签与表达式值温和,便开始执行case标签之后的语句,若没有break会一直执行到switch语句的最下面,”向下穿越“模式

    switch(next_char){
    	case 'a': case 'A': case 'e': case 'E':
    	case 'i': case 'I': case 'o': case 'O':
    	case 'u': case 'U':
    		++vowel_cnt;	// 若为元音字母,计数值加一
    		break;
        // ...
    }
    
  2. 其他:if-else语句,while循环,continue语句,break语句等

1.5 如何运用Array和Vector

使用可存放连续整数值的容器类型

  1. C++内置的array类

    定义array:指定其元素类型,命名,并指定所能存储的元素个数,其大小必须是个常量表达式

    const int num_months = 12;
    int month[num_months];
    
  2. vector boject

    包含vector头文件,vector为模板类,必须用<>指定其元素类型,并指定其大小,其大小不一定是个常量表达式

    #include <vector>
    int num_months = 12;
    vector<int> month(num_months);	// 定义一个vector object,存储12个int,初始值为0
    
  • vector和array的元素索引都是从0开始的

    month[0] = 1;
    month[1] = 2;
    
  1. array的初始化:使用初始化列表

    int elem_seq[seq_size] = {
    	1, 2, 3, 	// Fibonacci
    	3, 4, 7, 	// Lucas
    	2, 5, 12, 	// Pell
    	3, 6, 10, 	// Triangular
    	4, 9, 16,	// Square
    	5, 12, 22	// Pentagonal
    };
    

    初始化列表的元素个数不能超出array的大小,若小于array的大小,则剩余元素被初始化为0

  2. vector的赋值

    (1) 逐个元素按索引赋值

    (2) 使用已初始化的array初始化vector

    int elem_vals[seq_size] = {
    	1, 2, 3, 	// Fibonacci
    	3, 4, 7, 	// Lucas
    	2, 5, 12, 	// Pell
    	3, 6, 10, 	// Triangular
    	4, 9, 16,	// Square
    	5, 12, 22	// Pentagonal
    };
    vector<int> elem_seq(elem_vals, elem_vals + seq_size);
    // elem_vals和elem_vals + seq_size这两个值都是实际内存位置,标示了用以将vector初始化的元素范围
    
  3. elem_seq.size()返回vector对象的大小

1.6 指针带来弹性
  1. 一个未指向任何对象的指针,其地址值为0,称为null指针

    int *pi = 0;	// 定义int指针pi,初始化为null指针
    
  2. 对null指针进行提领操作,会导致未知的执行结果,可在提领操作前先检验该指针是否null指针

    if(pi && *pi != 1024)
    	*pi = 1024;
    
  3. rand()与srand()是C语言标准库提供的伪随机数生成器,srand()的参数是随机数生成器种子,每次调用rand()将返回介于0和"int所能表示的最大整数"之间的一个整数

    # include <cstdlib>
    srand(seq_cnt);
    seq_index = rand() % seq_cnt;  // seq_index为[0, seq_cnt)之间的一个整数
    
  4. class object指针

    #include <iostream>
    #include <vector>
    #include <cstdlib>
    using namespace std;
    int main(){
        int vals[] = {1, 1, 2};
        vector<int> fibonacci(vals, vals + 3);
        vector<int> lucas(vals, vals + 3);
        vector<int> pell(vals, vals + 3);
        vector<int> triangular(vals, vals + 3);
        vector<int> square(vals, vals + 3);
        vector<int> pentagonal(vals, vals + 3);
        const int seq_int = 6;
        vector<int>* seq_addrs[seq_int] = { 
            // seq_addrs是个array,存放元素类型为vector<int> *
            &fibonacci, &lucas, &pell,
            &triangular, &square, &pentagonal
        };
        srand(seq_int);
        int seq_index = rand() % seq_int;
        vector<int> *current_vec = seq_addrs[seq_index];
        // if(!fibonacci.empty() && fibonacci[1] == 1)
        //     cout << fibonacci[1];
        if(current_vec && !current_vec->empty() && (*current_vec)[1] == 1)
            cout << (*current_vec)[1];
        return 0;
    }
    

    (1) 通过名字fibonacci访问vector对象的成员时,通过dot成员选择运算符.进行;通过指针时,必须改用arrow成员选择运算符->

    (2) 使用下标运算符时,必须先提领指针,即(*current_vec)[1]

1.7 文件的读写
  1. 对文件进行操作需要包含fstream头文件

    #include <fstream>
    
  2. ofstream对象为供输出用的file stream对象

    ofstream outfile("seq_data.txt");
    // 若文件不存在则创建,若存在则打开并用于输出,且原数据会被丢弃
    ofstream outfile("seq_data.txt", ios_base::app);
    // 以追加模式(append mode)打开文件,新数据会被追加到文件末尾
    if(!outfile){
        // 检查文件是否成功打开,若不成功则输出错误信息
        cerr << "Oops! Unable to save session data!\n";
    }else{
        // 打开成功,将数据写入outfile
        outfile << user_name << ' ' << num_tries << ' ' << num_right << endl;
    }
    

    endl是iostream library定义的操作符,它会插入一个换行符,并清除输出缓冲区的内容

  3. ifstream对象为供输入用的file stream对象

    ifstream infile("seq_data.txt");	
    // 以读取模式打开infile, 若不能成功打开则ifstream为false,若成功则读取位置设置为文件起始处
    int num_tries = 0, num_right = 0;
    if(!infile){
    	// 文件打开不成功,输出错误信息
    	cerr << "Cannot open the file!\n";
    }else{
    	string name;
        int nt, nr;
        while(infile >> name){		// 一旦读到文件尾,则退出循环
            infile >> nt >> nr;
            if(name == user_name){
                cout << "Welcome back, " << user_name << endl;
                cout << "Your current score is " << nr << " out of " << nt << endl;
                cout << "Good Luck!" << endl;
                num_tries = nt;
                num_right = nr;
            }
        }
    }
    
  4. fstream对象进行同时读写一个文件

    fstream iofile("seq_data.txt", ios_base::in|ios_base::app);
    if(!iofile){
    	cerr << "Cannot open the file!\n";
    }else{
    	iofile.seekg(0);			// 将文件重新定位至起始处
    	string name;
        int nt, nr;
        while(iofile >> name){		// 一旦读到文件尾,则退出循环
            iofile >> nt >> nr;
            if(name == user_name){
                cout << "Welcome back, " << user_name << endl;
                cout << "Your current score is " << nr << " out of " << nt << endl;
                cout << "Good Luck!" << endl;
                num_tries = nt;
                num_right = nr;
                break;
            }
        }
        num_tries++;
        num_right++;
        iofile << user_name << ' ' << num_tries << ' ' << num_right << endl;
    }
    

    以追加模式打开文件时,会定位至文件末尾,应使用iofile.seekg(0);将文件重新定位至起始处

1.8 配套练习题解答

https://blog.csdn.net/young_cr7/article/details/105148768

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值