c++ primer笔记----字符串、向量和数组

  • using声明
#include <iostream>
using std::cin;
using std::cout; using std::endl;
  • 定义和初始化string
string s1;  //默认初始化,s1是一个空字符串
string s2(s1);
string s2 = s1;
string s3 = "value";
string s3("value");
string s4(n, 'c');
  • 读写string
string s;
cin >> s;  //自动忽略开头的空白(空格、换行符、制表符等),直到遇到下一处空白为止

getline(cin. line);  //每次读取一行,直到遇到换行符。最后换行符被丢弃

line.empty();

auto len = line.size();  //len是类型 `string::size_type`。 unsigned
// 如果一条表达式中已经有了size()函数,就不要再使用int了。
// 自动转换是int-->unsigned int
  • stirng相加:字符串字面值并不是string对象
string s4 =s1 +", ";
string s5 = "hello " + ", ";  //错误: + 的两个运算对象至少一个是string对象
  • 处理或改变每个字符,范围for循环
#include <string>
using std::string;

string s("hello");
decltype(s.size()) punct_cnt = 0;   //类型声明
for(auto c : s)         //若要改变则 auto &c : s 。c的类型是 char
    if(ispunct(c))      //<cctype>
        ++punct_cnt;
  • 下标运算符[]:接收的参数类型是string::size_type。无符号类型的。c++标准库并不要求检测下标的合法性

  • vevtor:类模板,为编译器生成类而编写的一份说明

#include <vector>
using std::vector

vector<int> ivec;   //<对象>  <>里不能是引用,因为引用不是对象
  • 定义和初始化vector
vector<T> v1;  //空vector
vector<T> v2(v1);
vector<T> v2 = v1;
vector<T> v3(n, val);
vector<T> v4(n);  //n个对象,值是默认值
vector<T> v5{a, b, c};
vector<T> v5 = {a, b, c};

vector<string> v6("hi");   //error : {}
vector<string> v7{10};    //等价于 v7(10). 类型不匹配的情况
vector<string> v8{10, "hi"};  //等价于 v8(10, "hi")
  • 实例化:编译器根据模板创建类或函数的过程

  • vector操作

vector<int> v1;
v1.push_back(1);  //添加元素。 如果出现该语句,则不能使用范围for循环
  • 迭代器
auto b = v.begin(), e = v.end();  //如果为空,则都是尾后迭代器
for(auto it = s.begin(); it != s.end(); ++it)  
//!= 标准容器看迭代器都有的定义,  ++it比 it++更高效
  • 迭代器类型
vector<int>::iterator it;
string::iterator it2;

vector<int>::const_iterator it3;
string::const_iterator it4;

vector<int> v;
const vector<int> cv;
auto it1 = v.begin();    //vector<int>::iterator ,由对象是否是常量决定
auto it2 = cv.begin();   //vector<int>::const_iterator

auto it3 = v.cbegin();  //vector<int>::const_iterator
  • 迭代器访问成员
it->mem;
(*it).mem;
  • 凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素

  • constexpr和常量表达式:值不会改变,在编译过程就得到计算结果的表达式。字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式

const int max_files = 20;
const int limit = max_files + 1;
int staff_size = 27;  //不是常量表达式
const int sz = get_size(); //看函数是不是constexpr函数

constexpr int mf =20;
  • 数组初始化
int arr[10];  //[]内是常量表达式

int a2[] = {0, 1, 2};  //大小是3
int a3[5] = {0, 1, 2}; //后面2个元素初始化为0
  • 字符数组特殊性
char a1[] = {'c', 'd'}; //大小是2
char a2[] = {'c', 'd', '\0';} //含有显示的空字符
char a3[] = "c++"; //大小是4,自动添加空字符
const char a4[6] = "daniel"; //error: 大小是7,没有空间存放空字符
  • 复杂的数组声明
int *ptrs[10]; //ptrs是含有10个整型指针的数组。 类型修饰符从右向左依次绑定
int &refs[10]; //error : 不存在引用的数组。 引用不是对象
int (*parray)[10] = &arr; //parray是指针,指向含有10个整数的数组
int (&arrref)[10] = arr;  //arrref是引用,引用含有10个整数的数组

int *(&arry)[10] = ptrs; //arry是引用,引用的是含有10个int指针的数组
  • 指针和数组:数组名和指针几乎相同,且都能进行++,>,*,-等运算。不同在于,num++非法, num++是一个指向数组开头的常量,不能作为左值。
string nums[] = {"1", "2", "3"};
string *p = &nums[0];  //[]里面的索引值是有符号的
  • C风格字符串:是为了表达和使用字符串而形成的一种约定俗称的写法。按此习惯书写的字符串存放在字符数组中并以空字符(null)结束。

  • string对象转换为C风格字符串

char *str = s.c_str(); //调用成员函数。
//如果想一直使用该字符串数组,组好重新拷贝一份
  • 使用数组初始化vector对象
int int_arr[] = {0, 1, 2, 3, 4, 5};
vector<int> ivec(begin(int_arr, end(int_arr))); //<iterator>,返回的指针int* 
  • 多维数组:数组的数组
int ia[3][4] = {{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};//3个元素,每个元素是4元素数组
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
int ia[3][4] = {{1}, {2}, {3}};

int (&row)[4] = ia[1];  //把row绑定到ia的第二个4元素数组上
  • 范围for
size_t cnt = 0;  //数组[]内的类型是size_t
for(auto &row:ia)   //不能是 auto row:ia。这样返回的int[4]数组的指针,
                    //下面循环就不对了。 加上&,返回的是数组
    for(auto &col:row){   //最后一个循环,可以去掉&
        col = cnt;
    }
  • 指针和多维数组:使用数组名字时,自动将其转换成指向数组首元素的指针
int ia[3][4];
int (*p)[4] = ia;  //名字-->指针
p = &ia[2];
int (&row)[4] = ia[1];  //把row绑定到ia的第二个4元素数组上

for(auto p=ia; p!=ia+3; ++p)  //名字-->指针, p是指针,指向含有4个整数的数组
    for(auto q=*p; q!=*p+4; ++q) //*p是数组,*P是数组名,名字-->指针

for(auto p=begin(ia); p!=end(ia);++p)
    for(auto q=begin(*p); q!=end(*p); ++q)
  • 类型别名
using int_array = int[4];
typedef int int_array[4];

猜你喜欢

转载自blog.csdn.net/qq_28038207/article/details/80963418