第3章 字符串、向量和数组

3.1 命名空间using声明

命名空间中的名称使用:

  • 使用using引入
// 全部引入
using namespace::std;
// 部分引入
using std::cin;
using std::cout;
...
  • 显示调用
int main()
{
    ...
    std::cout<<...;
    ...
}

头文件不应包含using声明,避免产生冲突

3.2 标准库类型string

#include <string>
using std::string;
直接初始化和拷贝初始化
string s1 = "hello";    // 拷贝初始化
string s2("hello");     // 直接初始化
string s3(10, 'c')      // 直接初始化,s3='cccccccccc'

string s4 = string(10, 'c')     // 拷贝初始化,出现利用临时变量拷贝
// 等价于
string temp(10, 'c');
string s4 = temp;

string对象自动忽略开头的空白(空格符、换行符、制表符),遇到空白停止。

getline 遇到换行符停止,读取换行符但不保存

字符串字面值和string对象相加时,必须确保每个加法运算符(+)的两侧运算对象至少有一个是string

string s = "hello"+","+s1;  // 错误
string s = "hello"+s1+",";  // 正确

string字符操作

函数操作
isalnum字母或数字
isalpha子母
iscntrl控制字符
isdigit数字
isgraph不是空格但可以打印出来
islower小写字母
isprint可打印字符
ispunct标点符号(非控制字符、数字、子母)
isspace空白(空格、制表符、回车、换行符等)
isupper大写字母
isxdigit十六进制数字
tolower大写转小写
toupper小写转大写
基于范围的for循环

使用范围for循环处理多维数组,除了最内层的循环其他循环控制变量都应该是引用类型。

for(declartion:expression)
    statement

逐字符输出

string srt("some string");
for(auto c:str)
    cout<<c<<endl;

统计string对象中标点符号个数

string s("hello world!!!");
decltype(s.size()) punct_cnt = 0;
for(auto c:s)
    if(ispunct(c))
        ++punct_cnt;
cout<<punct_cnt<<endl;

改变字符串中字符

strig s("hello world!!!");
for(auto &c:s)  // & 改变字符
    c = toupper(c);
cout << s << endl;

3.3 vector

对象的集合,所有对象的类型都相同。集合中的每个对象都有一个与之对应的索引,索引用于访问对象。亦称做容器

vector类模板并非类型

引用外,大多数内置类型和类都可以为vector对象的元素,包括vector。

注意

早期版本C++中元素是vector的向量模板定义稍有不同

// C++11 之前
vector<vector<int> >
// C++11
vector<vector<int>>
定义和初始化
语句初始化方式
vector v1v1空vector,潜在元素是T类型,执行默认初始化
vector v2(v1)v2中包含有v1的所有元素的副本
vector v2=v1等价于v2(v1)
vector v3(n, val)v3包含n个重复的元素,每个元素都是val
vector v4(n)v4包含n个重复执行了值初始化的对象
vector v5{a,b,c…}v5包含了初始值个数的元素,每个元素被赋予乡相应的初始值
vector v5={a,b,c…}等价于v5{a,b,c…}

值初始化

初始化时,可以只提供vector对象容纳的元素数量,此时库会创建一个值初始化的元素初值,并将其赋给容器中所有元素。这个初始值由vector对象中元素的内置类型决定。

如果vector元素是内置类型,比如int,则元素初始值自动设为0;如果是类类型,如string,则元素由类默认初始化。

vector<int> ivec(10) // 10个初始化为0的int
vector<int> svec(10) // 10个初始化为空的string
添加元素

直接初始化三种情形:

  • 数量少
  • 副本
  • 类型、值一致

当数量较大或其他情况时,更适合向vector中添加元素而不是直接初始化

不能用下标形式添加元素,只能对已存在的元素执行下标操作

vector<int> v1;
for (int i = 0; i !=100; ++i) {
    v1.push_back(i);
}

3.4 迭代器

end迭代器(尾迭代器)指向尾元素的下一个位置,不存在的元素。容器为空,begin和end相同。

如果对象是常量,只能使用const_iterator迭代器。

迭代器运算符

运算符含义
*iter返回迭代器iter所指元素的引用
iter->mem获取iter指向元素的mem成员,等价于(*iter).获取iter指向元素的mem成员
++iter指向容器中的下一个元素
–iter指向容器中的上一个元素
iter1 ==/!= iter2迭代器是否相等

对尾迭代器(end)解引用、递增(++)是非法的,因为end没有指向的存在的元素

迭代器失效

  • 不能在for循环中想vector对象添加元素
  • 可能改变vector对象容量的操作,如push_back,使其迭代器失效
迭代器运算

经典算法:二分搜索。

auto beg = text.begin(), end = text.end();
auto mid = text.begin() + (end-beg)/2;

while(mid != end && *mid != sought){
    if(sought < *mid)
        end = mid;
    else
        beg = mid + 1;
    mid = beg + (end - beg)/2
}

3.5 数组

定义和初始化

定义数组必须指定类型,不允许使用auto关键字,不存在引用的数组。

数组维度必须是常量表达式

unsigned cnt = 42;
int arr[cnt];       // 错误
constexpr unsigned sz = 42;
int arr[sz];        // 正确

数组的指针和数组的引用

int (*parray)[10] = &arr;
int (&arrref)[10] = arr;

由内向外解释声明含义,()中表明parray是一个指针,指向大小为[10]的数组,且数组中元素是int;同理arrref是一个引用,引用对象是一个大小为[10]的数组,且元素类型是int。

int * (&arry)[10] = ptrs;

arry是一个大小为10的数组的引用,并且元素的类型是int指针(int *),即arry是一个含有10个int型指针的数组的引用。

指针和数组

很多对数组的操作实际是对指针的操作,数组名就是指向数组第一个元素的指针。

string nums[] = {"one", "two", "three"};
string *p = &nums[0];
// 等价
string *p = nums;

使用auto关键字时,得到的变量的类型是指针而非数组

int ia[] = {0,1,2,3,4,5};
auto ia2(ia);
// 等价于
auto ia2(&ia[0]);   // ia2: int *

使用decltype关键字时,保持不变,返回类型是数组

decltype(ia) ia3 = {0,1,2,3,4,5};   // ia3是数组
ia3[2] = 6;
指针和迭代器

利用标准库函数beginend,定义在iterator头文件中。

int ia[] = {1,2,3,4,5};
int *beg = begin(ia);
int *last = end(ia);
C风格字符串

头文件cstring或者string.h

C风格字符串需要以空字符(’\0’)结尾,才能判断字符串的尾部,进行下一步操作。

建议任何出现字符串字面值的地方都可以用以空字符结束的字符数组来替代

string对象初始化C风格字符串

const char *str = s.c_str();

如果后续的操作改变了s的值,则之前的返回的字符数组将失效,最好将其重新拷贝一份

使用数组初始化vector对象

int int_arr[] = {1,2,3,4};
vector<int> ivec(begin(int_arr), end(int_arr)); // 全部一样
vector<int> svec(int_arr+1, int_arr+3); // 从int_arr[1]~[3]一样

3.6 多维数组

初始化

int ia[3][4] = {
    {0,1,2},
    {4,5,6},
    {7,8,9}
};
// 等价
int ia[3][4] = {1,2,3,4,5,6,7,8,9};

使用范围for循环处理多维数组,除了最内层的循环其他循环控制变量都应该是引用类型。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值