C++知识点摘录二

字符串,向量和数组

标准库类型string

1.string如果使用等号初始化一个变量,实际上执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中。
2.如果不使用等号,,则执行的是直接初始化

using std::string;
string s5  = "hiya";//拷贝初始化
string s6("hiya");//直接初始化
string s7(5,"c");//直接初始化,s7的内容是ccccc
//读取未知数量的string对象
int main
{
	string word ;
	while(cin >> word)
		cout<<word<<endl;
	return 0;
}
//getline,读取一行,只要一遇到换行符就是结束读取操作并返回结果
	string s2;
    while (getline(cin, s2)) {
        cout << s2 <<endl;
    }
//empty函数根据string对象是否为空返回一个对应的布尔值
while(getline(cin,line))
if(!line.empty())
	cout << line << endl;
//size函数返回string对象的长度
while(getline(cin,line))
if(line.size() > 80)
	cout << line << endl;
//对string对象使用+运算符的结果是一个新的对象
	string s1 = "hello",s2 = "word \n"
	string s3 = s1+s2;//内容是helloword\n
	s1+=s2;	//等价于s1 = s1+s2;
//当把string对象和字符字面值及字符串字面值混在一条语句使用时,
//必须确保每个加发运算符的两侧的运算对象至少有一个是string
	string s6 = s1 + ", "+"world";//正确
	string s7 = "hello"+" , "+s2;//错误,不能把字面值直接相加。

字符串字面值与string是不同的类型

处理string对象中的字符

使用cctype头文件
C++知识点摘录二_第1张图片

//使用for循环改变字符串中的字符
string s("hello word !!!!");
for(auto &c: s )
{
c = toupper(c);//c是引用,因此赋值语句将改变s中字符的值
}
cout << s <<endl;

//out:HELLO WORD!!!!

//处理一个字符
const string hexdigits = "0123456789ABCDEF";
cout << "enter a series of numbers between 0 and 15"<<"separated by spaces.Hit Enter when finished:"<<endl;
string result;
string::size_type n;
while(cin >> n )
{
if(n<hexdigits.size()){
result+=hexdigits[n];
} 
cout<<"your hex number is :"<< result<<endl;
//如果输入的内容是12 0 5 15 8 15
//那么输出的结果就是:result = CO5F8F


下标运算符([ ])接收的输入参数是string::size_type类型的值,这个参数表示要访问的字符的位置;返回值是该位置上字符的引用。
注意⚠️:
string对象的下标必须大于等于0而小于s.size()

标准库类型vector

vector初始化

vector<string>v1{"a","b","c"};//列表初始化
//创建指定数量的元素
vector<int>ivec(10,-1);//10个int类型的元素,每个都被初始化为-1
vector<string>svec(10,"hi!");//10个string类型的元素,每个都被初始化为“hi”
vector<int>ivec(10);//10个元素,每个都初始化为0
vector<string>svec(10);//10个元素,每个都是空string对象

向vector对象中添加元素

vector<int>v2;//空vector对象
for(int i = 0 ;i! = 100;++i)
{
v2.push_back(i);//依次把整数值放到v2尾端
}

其他的vector操作:
C++知识点摘录二_第2张图片

std::vector<int>v1{1,2,3,4,5,6,7,8,9};
    for(auto &i : v1)
        i *= i;
    for(auto i:v1)
        cout<< i <<endl;

第一个循环把控制变量i定义成引用类型,这样就能通过i给v的元素赋值,其中i的类型由auto关键字指定,第二个循环输出所有的元素。

//以10分	为一个分数段统计成绩的数量:0-9,10-19。。。。90-99,100
vector<unsigned>socres{11,0};
unsigned grade;
while(cin >> grade)
{
if(grade <=100)
{
++socres[gradle/10]//将对应分数段的计数值+1
}
}
//如果输入42,65,95,100,39,67,95,76,88,76,83,92,76,93
//0 0 0 1 1 0 2 3 2 4 1

//不能用下标的形式添加元素
vector<int>ivec;//空对象
for(decltype(ivec.size()) ix = 0;ix!=10;++ix)
{
ivec[ix] = ix;//验证错误:ivec不包含任何元素
}
//ivec是一个空的vector,根本不包含任何元素,当然也不能通过下标去访问任何元素

for(decltype(ivec.size()) ix = 0;ix!=10;++ix)
{
ivec.push_back(ix);//正确:添加一个新元素,该元素的值是ix
}

注意通过下标去访问不存在的元素,会引发很严重的后果。

迭代器介绍

使用迭代器

//由编译器决定b和e的类型
//b表示v的第一个元素,e表示v尾元素的下一位置
auto b = v.begin(),e = v.end;

C++知识点摘录二_第3张图片

	string s("some string");
    if(s.begin()!=s.end()){//确保s非空
        auto it = s.begin();//it表示s的第一个字符
        *it = toupper(*it);//将当前字符改写成大写形式
    }
    //Some string


//依次处理s的字符直至我们处理完全部字符或者遇到空白
for(auto it = s.begin();it!=s.end()&&!isspace(*it);++it)
	*it = toupper(*it);    

//循环首先用s.begin的返回值来初始化it,意味着it指示的是s中的第一个字符。条件部分检
//查是否已到达s的尾部,如果尚未到达,则将it解引用的结果传入isspace函数检查是否遇
//到了空白。每次迭代的最后,执行++it令迭代器前移一个位置以访问s的下一个字符。	
//循环体内部先解引用it,然后将结果传入toupper函数得到该字母对应的大写形式,再把
//这个大写字母重新赋值给it所指示的字符

迭代器类型

拥有迭代器的标准库类型使用iterator和const_iterator来表示迭代去的类型。

begin和end返回的具体类型由对象是否是常量决定,如果对象是常量begin和end返回const_iterator,不是常量则返回iterator。

 vector<int>::iterator it;
 string::iterator it2;
 vector<int>::const_iterator it3;//只读不能写
 string::const_iterator it4;//只读不能写

c++11引入了两个新函数,分别是cbegin 和 cend;这两个新函数分别返回容器第一个元素或最后元素下一位置的迭代器。不论vector对象本身是否是变量,返回值都是const_iterator。

解引用迭代器可获得迭代器所指的对象,如果该对象类型恰好是类,就有可能访问它的成员。例如(*it).empty();该表达式的含义是先对it解引用,然后解引用的结果再执行点运算符。

为了简化上面的表达式:

c++定义了箭头运算符。(->)箭头运算符把解引用和成员访问两个操作结合在一起。

for(auto it = text.cbegin();it!=text.cend()&&!it -> empty();++it)
        cout<<*it<< endl;
    return 0;

注意⚠️:
但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。

迭代器运算

迭代器的递增运算令迭代器 每次移动一个元素,所有的标准库容器都有支持递增运算的迭代器。

std::vector<unsigned>socres{42,65,95,100,39,67,95,76,88,76,83,92,76,93};
    std::vector<unsigned>socre_level(11,0);
    for (auto beg = socres.begin();beg!=socres.end();++beg)
        ++socre_level[*beg/10];
    for(auto beg = socre_level.begin();beg!=socre_level.end();++beg)
        cout<<*beg<< endl;

//

数组

定义和初始化内置数组

定义数组的时候必须指定数组的类型,不允许使用auto关键字由初始值的列表推断类型。另外和vector一样,数组的元素应为对象,所以不存在引用的数组。

const unsigned sz =3;
int ial[sz] = {0,1,2};
int a2[] = {0,1,2};
string a4[3] = {"hi","bye"};//等价于a4[] = {"hi","byte",""};

使用字符串字面值对数组初始化,一定要注意字符串字面值的结尾处还有一个空字符,这个空字符也会像字符串的其他字符一样被拷贝到字符数组里面去。

//错误的,这样没有空间来存放空字符了
const char a4[6] = "dainel"

char a1[] = {'a','b','c'};//列表初始化,没有空字符
char a2[] = {'a','b','c','\0'};//列表初始化,含有显示的空字符
char a3[] = {"c++"};//自动添加表示空字符串的空字符。

不允许将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值.

关于复杂数组的解读:
1.

	//从右向左读:首先定义的是一个大小为10的数组,它的名字是ptrs
    //然后知道数组中存放的是指向int的指针
    int *ptr[10];
    //数组由内向外阅读,首先是圆扣号括起来的部分,*parray意味着parray是一个指针
    //观察右边,parray是个指向大小为10的数组的指针
    int (*parray)[10] = &aar;
    //arrRef是一个引用,它引用的对象是一个大小为10的数组
	    int (&arrRef)[10] = arr;
    //arry是一个引用,然后观察右边知道,arry引用的对象的是一个大小为10的数组。
    //数组的元素类型是指向int的指针。这样,arry就是一个含有10个int型指针的数组的引用。
    int *(&arry)[10] = ptrs;

访问数组元素

使用数组下标的时候,通常定义size_t类型。下标应该大于等于0而且小于数组的大小。

//size_t无符号类型
    constexpr size_t array_size = 11;
    int ia[array_size];
    for(size_t ix = 0;ix!=array_size;++ix){
        ia[ix] = ix;
         cout<< "ix = "<<ix<<endl;
    }
    for(auto i:ia)
        cout<< "-->"<<i<<endl;

指针和数组

使用数组的时候编译器一般会把它转换成指针。
通常情况下,使用取地址符来获取指向某个对象的指针,取地址符可以用于任何对象。数组的元素也是对象,对数组使用下标运算符来得到该数组指定位置的元素。因此对数组的元素使用去地址符就能得到指向该元素的指针。

	string nums[] = {"one","two","three"};
	string *p = &num[0];//p指向nums的第一个元素
	string *p2 = nums;//等价于 *p2 = &nums[0]

 int arr[] = {0,1,2,3,4,5,6,7,8,9};
    int *ptr1 = arr;//ptr1指向arr的第一个元素
    ++ptr1;//ptr1指向arr第二个元素
    
    //寻找arr中第一个负数
    int * pbeg = std::begin(arr);
    int * pend = std::end(arr);
//    while(pbeg!=pend && *pbeg>=0)
//        pbeg++;
    //两个指针相减的结果的类型是一种名为ptrdiff_t的标准库类型
    //和size_t一样,ptrdiff_t也是一种定义在cstddeff头文件的机器的相关类型
    //因为差值可能是负数,所以ptrdiff_t是一个带符号类型的
    auto n = pbeg - pend;
    
    //指针加上一个整数得到的结果还是一个指针
    //假设结果指针指向了一个元素,则允许解引用该结果的指针
    int ia1[] = {0,1,2,3,6};
    int last = *(ia1+4);//把last初始化成6,也就是ia1[4]
    
    while (pbeg!=pend ) {
        *pbeg = 1;
        pbeg++;
    }
    for(auto i :arr)
     cout<< "答案:"<<arr[i]<<endl;

在大多数表达式中,使用数组类型的对象其实就是使用一个指向该数组首元素的指针。

c风格字符串

C++知识点摘录二_第4张图片
使用数组初始化vector,要实现这一个目的,只需要拷贝区域的首元素地址和尾后地址就可以了。

//全部拷贝
int int_arr[] = {0,1,2,3,4,5,6};
vector<int>ivec(begin(int_arr),end(int_arr));
//初始化vector对象的值也可能是数组的一部分
vector<int>subVec(int_arr+1,int_arr+4);

你可能感兴趣的:(c++)