《C++ Primer》学习笔记1

基础知识回顾

输入输出流

iostream库包含两个基础类型istream和ostream,分别表示输入流输出流,cout和输出运算符实现向流写入数据,cin和输入运算符实现从流读取数据。

注释

C++程序中的注释有单行注释(//开头)和多行注释(/* */)两种,多行注释的注释界定符不能嵌套。

数量不定的输入数据的读取

C++提供多种不同的控制流语句,如顺序语句、循环语句和条件语句,输入流结合while循环可以实现数量不定的输入数据的读取,如下:

#include<iostream>
using namespace std;
int main()
{
	int sum=0,value=0;
	while(cin >> value)
		sum+=value;
	cout << "Sum is: " << sum << endl;
	return 0;
}

while循环判断的条件是istream对象是否有效,当遇到文件结束符(end-of-file,该例中是Ctrl+Z)或遇到一个无效的输入(如该例中读入的值不是要给整数)时,istream对象的状态会变为无效,处于无效状态的istream会使条件变为假。

变量

C++中的变量要先声明类型,变量类型决定了存储该变量所需要的内存空间,可以通过sizeof运算符获取存储所需的内存空间。
有符号类型的第一个位是符号位,无符号类型的所有比特都用来存储值。

类型转换

  1. 非布尔类型转换为布尔类型
  2. 布尔类型转换为非布尔类型
  3. 浮点类型转换为整型
  4. 整型转换为浮点类型

标识符

由字母、数字、下划线组成,必须以字母或下划线开头,不能以数字开头。

作用域

  1. 全局作用域
  2. 块作用域

作用域嵌套的情况

  1. 内层作用域:局部变量
  2. 内层作用域以外的外层作用域:全局变量

引用(reference)

引用为对象起了另外一个名字,引用必须被初始化,一旦初始化完成,引用将和它的初始值变量一直绑定在一起,无法重新绑定。

int ival=1024;
int &refVal=ival;

refVal是指向int类型变量ival的引用。

int (&arrRef)[10]=arr;

arrRef是指向包含10个元素的数组的引用

指针

指针可以先后指向不同的对象
指针存放指向对象的地址
解引用获得指针指向的对象的值

指向指针的指针

int ival=1024;
int *pi=&ival;
int **ppi=&pi;

pi是指向int类型变量的指针
ppi是指向int类型指针的指针

指向指针的引用

int i=42;
int *p;
int *&r=p;

r是对指针p的引用

string对象

  1. 赋值:直接初始化和拷贝初始化
  2. empty()
  3. size()
  4. 下标访问
  5. 连接
  6. 判断相等
  7. 判断不相等
  8. 比较大小
  9. 处理字符串中的字符(大小写、数字等)

vector对象

可变长度的数组,每个元素的类型必须相同,可以是由向量组成的向量。
向vector中添加元素push_back

string word;
vector<string> text;
while(cin >> word)
{
	text.push_back(word);
}

常用操作:

  1. v.empty() 是否为空
  2. v.size() 元素的个数
  3. v.push_back 向尾端添加元素
  4. v[n] 下标访问
  5. 判断相等和不相等
  6. 判断大小

迭代器iterator

所有标准库容器都可以使用迭代器,只有少数几种才同时支持下标访问。严格来说,string对象不属于容器类型,但string支持很多与容器类型类似的操作。
迭代器类似于指针类型,提供了对对象的间接访问,可以进行解引用操作,可以进行++和–操作,也可以+n或者-n,也可以判断是否相等。
begin成员指向第一个元素,end成员指向最后一个元素的下一位置。

auto b=v.begin(),e=v.end();

将string对象的字符变为大写

for(auto it=s.begin();it!=s.end()&&!isspace(*it);++it)
	*it=toupper(*it);

C++定义了迭代器的减法运算,两个迭代器相减的结果表示它们之间的距离,C++没有定义迭代器的加法运算,所以二分搜索程序中用的是mid=beg+(end-beg)/2而不是mid=(begin+end)/2
所有标准库容器的迭代器都定义了==和!=,但是它们中的大多数都没有定义<运算符。
const_iterator和常量指针差不多,只能读不能修改指向的元素。

读入一个整数并把它们存入一个vector对象,将每队相邻整数的和输出,使用迭代器实现:

#include<iostream>
#include<vector>
using namespace std;
int main()
{
	int value;
	vector<int> vec;
	while(cin >> value)
	{
		vec.push_back(value);
	}
	for(vector<int>::iterator it=vec.begin();it!=vec.end()-1;++it)
	{
		cout << *it << "+" << *(it+1) << "=" << *it+*(it+1) << endl;
	}
	return 0;
}

数组

数组不允许拷贝赋值
复杂的数组声明:

int *ptrs[10];	//由指针组成的数组
int (*parray)[10]=&arr; //指向包含十个元素的数组的指针
int (&arrRef)[10]=arr; //指向包含是个元素的数组的引用

数组可以通过下标和指针来访问,指针也是迭代器。

函数

每个C++函数都包括一个或多个函数,其中一个必须是main函数,操作系统通过调用main来运行C++程序。
一个函数的定义包括四部分:

  1. 返回类型return type
  2. 函数名function name
  3. 形参列表parameter list
  4. 函数体function body

main函数的返回类型必须为int。

形参和函数体内部定义的变量统称为局部变量,仅在函数的作用域内可见。
要想让局部变量的生命周期贯穿函数调用及之后的时间,可以将局部变量定义成static类型。
参数的类型:

  1. 值作为参数
  2. 指针作为参数
  3. 引用作为参数
  4. const型的形参

熟悉C的程序员常常用指针类型的形参访问函数外部的对象,C++中建议使用引用类型的形参代替指针。

顺序容器

vector和array相比,前者可变大小,后者固定大小,后者不能添加或删除元素。
vector和string非常相似,后者专门用于保存字符。
vector和deque相比,后者是双端队列,后者在头尾插入/删除的速度很快,前者在尾部以外插入和删除的速度可能很慢。
list是双向链表,只支持双向顺序访问,在任何位置进行插入/删除的速度都很快。
forward_list是单向链表,只支持单向顺序访问,在任何位置进行插入/删除的速度都很快。

类型访问方式插入/删除速度快
vector快速随机访问尾部
array快速随机访问不能插入和删除
string快速随机访问尾部
deque快速随机访问头部和尾部
list双向顺序访问任何位置
forward_list前向顺序访问任何位置

使用vector是最好的选择,除非有其他理由。
如果要求在中间插入/删除元素,选择list或forward_list。
如果要求在头尾插入/删除元素,选择deque。

  • 顺序容器的构造
  • 顺序容器的插入元素
  • 顺序容器的删除元素

关联容器map

map是映射,从key到value的映射,字典是map的一个典型实例。
编写一个能对文章内每个字眼的出现次数加以分析的程序,可以建立一个map,带有string key和int value:

map<string,int> words;
//输入key/value最简单的方式
words["vermeer"]=1;

对于字符统计程序,可以采用以下方式

string tword;
while(cin >> tword)
	words[tword]++;

其中的表达式words[tword]会取出与tword相应的value。如果tword不在map内,它会直接被放到map内,并获得默认值0,稍后出现的increment运算符会将其值加1。
map对象的成员first对应key,second对应value,以下的for循环使用迭代器的间接访问打印所有字符串及其出现次数。

map<string,int>::iterator it=words.begin();
for(;it!=words.end();++it)
	cout << "key: " << it->first
		 << "value: " << it->second << endl;

关联容器set

set由一群key组成(无重复)。如果我们想知道某值是否存在于某个集合内,就可以使用set。例如在图遍历算法中,可以使set存储每个遍历过的节点,在移到下一节点前,可以先查阅set,判断该节点是否已经遍历过。在字符统计程序中,如果不想统计某些词汇的出现次数,可以设计一个用来排除字符串的set。

#include<set>
#include<string>
set<string> word_exclusion;
while(cin >> tword)
{
	if(word_exclusion.count(tword))
		continue;
	words[tword]++;
}

泛型算法(未完待续)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值