array、tuple、string、vector的使用

array

参考https://blog.csdn.net/zhengqijun_/article/details/81566109
array是一个保存N 个 T 类型元素的序列式容器,连续存储且大小固定,内部不保留额外的数据(只有N个T类型对象),跟数组差不多,只是添加了一些成员函数和全局函数。

  • 形参 N 必须是一个常量表达式
  • array容器相比于原始数组的优点:

1.array 容器提供的 at() 成员函数,可以有效防止越界操纵数组的情况,这也就意味着数组容器可以作为参数传给函数,而不再需要单独去指定数组元素的个数。
2.fill() 函数可以实现数组的快速初始化;
3.swap() 函数可以轻松实现两个相同数组(类型相同,大小相同)中元素的互换
4.当两个 array 容器满足大小相同并且保存元素的类型相同时,两个 array 容器可以直接直接做赋值操作,即将一个容器中的元素赋值给另一个容器。
5.当两个 array 容器满足大小相同并且保存元素的类型相同时,如果其保存的元素也支持比较运算符,就可以用任何比较运算符直接比较两个 array 容器

类模板声明

template < class T, size_t N > 
    class array;

头文件

#include< array>

示例

#include<array>
#include<iostream>
using namespace std;
int main(){
    //初始化
    array<int,5> first;
    array<int,5> second={1,2,3,4,5};
    array<int,5> three(second);

    //array大小
    cout << "sizeof(first) = " << sizeof(first) << endl;
    cout << "size of array = " << first.size() << endl;
    cout << "max_size of array = " << first.max_size() << endl;
    //访问
    cout << "three[0] = " << three[0]<< endl;
    cout << "three.at(1) = " << three.at(1) << endl;
    //返回three中第一个元素的地址
    cout<<"& three= "<<three.data()<<endl;
    //遍历
    for(array<int,5>::iterator it=three.begin();it<three.end();it++){
        cout<<*it<<" ";
    }
    cout<<endl;
    for(auto& i:three)
        cout<<i<<" ";
    cout<<endl;
    //修改
    three[0]=2;
    cout<<"three[0]= "<<three[0]<<endl;
    //填充
    array<int,5> four;
    four.fill(6);
    for(auto& j:four)
        cout<<j<<" ";
    cout<<endl;
    //交换两个array
    three.swap(four);
    for(auto& k:three)
        cout<<k<<" ";
    cout<<endl;

    system("pause");
    return 0;
}

在这里插入图片描述

tuple

参考:https://blog.csdn.net/fengbingchun/article/details/72835446
tuple:元组,
tuple是类似pair的模板,只是std::tuple可以有任意数量的成员

关于pair,
头文件为 #include < utility >

https://blog.csdn.net/love20165104027/article/details/81515746?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

头文件

#include <tuple>

类模板声明

template< class... Types >
class tuple;

初始化

  • make_tuple,函数模板,用于构造一个合适的tuple
//初始化
    tuple<int,char,string> first;
    tuple<int,char,string> second(make_tuple(2,'t',"two"));
    tuple<int,char,string> three(3,'t',"three");
    tuple<int,char,string> four(three);

访问

  • get,模板函数,返回tuple中第Ith个元素的引用
template< std::size_t I, class... Types >
typename std::tuple_element<I, tuple<Types...> >::type&
    get( tuple<Types...>& t ) noexcept;
//读取下标0,1,2处的值
    cout<<" three contains: "<<get<0>(three)<<","
        <<get<1>(three)<<","<<get<2>(three)<<endl;

std::tuple_element

tuple_element是一个模板类,其type用于萃取tuple中第Ith个元素的类型

template< std::size_t I, class... Types >
class tuple_element< I, tuple<Types...> >;

示例

auto mytuple = std::make_tuple(10, 'a'); 	
std::tuple_element<0, decltype(mytuple)>::type first =std::get<0>(mytuple);	
std::tuple_element<1, decltype(mytuple)>::type second = std::get<1>(mytuple); 	
std::cout << "mytuple contains: " << first << " and " <<second << '\n';

关于decltype
参考:C++11:类型处理(using、auto、decltype)

decltype与auto关键字一样,用于进行编译时类型推导,不过它与auto还是有一些区别的。decltype的类型推导并不是像auto一样是从变量声明的初始化表达式获得变量的类型,而是总是以一个普通表达式作为参数,返回该表达式的类型,而且decltype并不会对表达式进行求值。

std::tuple_size

tuple_size是一个类模板,其成员变量value用于获取tuple中元素的个数
示例

template< class... Types >
class tuple_size< std::tuple<Types...> >
 : public std::integral_constant<std::size_t, sizeof...(Types)> { };
std::tuple<int, char, double> mytuple(10, 'a', 3.14); 	
std::cout << "mytuple has ";	
std::cout << std::tuple_size<decltype(mytuple)>::value;	
std::cout << " elements." << '\n';

string

参考:https://blog.csdn.net/zy2317878/article/details/79056289

类模板声明

template< 
    class CharT, 
    class Traits = std::char_traits<CharT>, 
    class Allocator = std::allocator<CharT>
> class basic_string;
typedef basic_string<char> string; 
typedef basic_string<wchar_t> wstring; 

头文件

#include <string>  

初始化

//默认构造
string ();

//复制构造
string (const string& str);

//范围构造
string (const string& str, size_t pos, size_t len = npos);

//由C风格的 char* 构造
string (const char* s);

//由s的前n个字符组成的字符串构造
string (const char* s, size_t n);

//n个字符c填充
string (size_t n, char c);

//迭代器范围构造
template <class InputIterator>
  string  (InputIterator first, InputIterator last);

//初始化列表构造
string (initializer_list<char> il);

//常量字符串构造
string (string&& str) noexcept;

示例:

// http://www.cplusplus.com/reference/string/string/string/
#include <iostream>
#include <string>

int main ()
{
  std::string s0 ("Initial string");

  // constructors used in the same order as described above:
  std::string s1;
  std::string s2 (s0);
  std::string s3 (s0, 8, 3);
  std::string s4 ("A character sequence");
  std::string s5 ("Another character sequence", 12);
  std::string s6a (10, 'x');
  std::string s6b (10, 42);      // 42 is the ASCII code for '*'
  std::string s7 (s0.begin(), s0.begin()+7);

  std::cout << "s1: " << s1 << "\ns2: " << s2 << "\ns3: " << s3;
  std::cout << "\ns4: " << s4 << "\ns5: " << s5 << "\ns6a: " << s6a;
  std::cout << "\ns6b: " << s6b << "\ns7: " << s7 << '\n';
  return 0;
}

插入

  • append():在字符串末尾附加字符串
  • operator+=:尾部附加字符串
//string (1)	
string& operator+= (const string& str);
//c-string (2)	
string& operator+= (const char* s);
//character (3)	
string& operator+= (char c);
//initializer list (4)	
string& operator+= (initializer_list<char> il);

示例

// string::operator+=
#include <iostream>
#include <string>
int main ()
{
  std::string name ("John");
  std::string family ("Smith");
  name += " K. ";         // c-string
  name += family;         // string
  name += '\n';           // character

  std::cout << name;
  return 0;
}
  • push_back:添加字符到字符串末尾
void push_back (char c);
  • assign():将新的字符串赋值给原字符串

  • operator=:将新的字符串赋值给原字符串

  • insert():在pos指定的位置之前插入字符串

//在pos指定的位置之前插入整个字符串str
string& insert (size_t pos, const string& str);

//在pos指定的位置之前插入字符串str中由subpos sublen指定的子串
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);

//在pos指定的位置之前插入整个const char*表示的C类型字符串
string& insert (size_t pos, const char* s);

//在pos指定的位置之前插入整个const char*表示的C类型字符串s中的前n个字符组成的字符串
string& insert (size_t pos, const char* s, size_t n);

//在指定的位置之前插入n个字符c
string& insert (size_t pos,   size_t n, char c);
iterator insert (const_iterator p, size_t n, char c);
iterator insert (const_iterator p, char c);

//范围插入
template <class InputIterator>
iterator insert (iterator p, InputIterator first, InputIterator last);
string& insert (const_iterator p, initializer_list<char> il);

insert示例:

// inserting into a string
#include <iostream>
#include <string>

int main ()
{
  std::string str="to be question";
  std::string str2="the ";
  std::string str3="or not to be";
  std::string::iterator it;

  // used in the same order as described above:
  str.insert(6,str2);                 // to be (the )question
  str.insert(6,str3,3,4);             // to be (not )the question
  str.insert(10,"that is cool",8);    // to be not (that is )the question
  str.insert(10,"to be ");            // to be not (to be )that is the question
  str.insert(15,1,':');               // to be not to be(:) that is the question
  it = str.insert(str.begin()+5,','); // to be(,) not to be: that is the question
  str.insert (str.end(),3,'.');       // to be, not to be: that is the question(...)
  str.insert (it+2,str3.begin(),str3.begin()+3); // (or )

  std::cout << str << '\n';
  return 0;
}

遍历

  • 基于迭代器遍历
string str ("Test string");
  for ( string::iterator it=str.begin(); it!=str.end(); ++it)
    cout << *it;
  • 基于for范围遍历
for(auto& i:str)
     cout<<i;

访问

  • 通过 [] 来访问

  • 通过at()访问

  • back()返回最后一个字符的引用

  • front()返回第一个字符的引用

示例

#include <iostream>
#include <string>
using namespace std;
int main ()
{
    string str ("one two three,go!");
    for ( int i=0;i<str.size();i++)
        cout<<str[i];
    cout << '\n';
    //索引越界,at()抛出out_of_range异常
    for(int j=0;j<str.size();j++)
        cout<<str.at(j);
    cout<<endl;
    cout<<str.front()<<endl;
    cout<<str.back()<<endl;
    system("pause");
    return 0;
}

查找

  • find:在字符串中查找内容。在字符串中搜索由其参数指定的字符串序列的第一次出现(需要整个序列完全匹配)。当指定pos时,搜索仅包括位置pos处及之后的字符
    返回值:首次匹配的第一个字符的位置。如果没有找到匹配,返回string :: npos。

https://blog.csdn.net/zy2317878/article/details/79056289

// string::find
#include <iostream>       // std::cout
#include <string>         // std::string

int main ()
{
  std::string str ("There are two needles in this haystack with needles.");
  std::string str2 ("needle");

  // different member versions of find in the same order as above:
  std::size_t found = str.find(str2);
  if (found!=std::string::npos)
    std::cout << "first 'needle' found at: " << found << '\n';

  found=str.find("needles are small",found+1,6);
  if (found!=std::string::npos)
    std::cout << "second 'needle' found at: " << found << '\n';

  found=str.find("haystack");
  if (found!=std::string::npos)
    std::cout << "'haystack' also found at: " << found << '\n';

  found=str.find('.');
  if (found!=std::string::npos)
    std::cout << "Period found at: " << found << '\n';

  // let's replace the first needle:
  str.replace(str.find(str2),str2.length(),"preposition");
  std::cout << str << '\n';

  return 0;
//Output
//first 'needle' found at: 14
//second 'needle' found at: 44
//'haystack' also found at: 30
//Period found at: 51
//There are two prepositions in this haystack with needles
}

  • find_ first_ of:在字符串中查找字符。在字符串中搜索与其参数中指定的任何字符匹配的第一个字符。当指定pos时,搜索仅包括位置pos及之后的字符。请注意,对于序列中的一个字符来说,就足够了(不是全部)
// string::find_first_of
#include <iostream>       // std::cout
#include <string>         // std::string
#include <cstddef>        // std::size_t

int main ()
{
  std::string str ("Please, replace the vowels in this sentence by asterisks.");
  std::size_t found = str.find_first_of("aeiou");
  //下面的循环实现了找到str中,”aeiou“中所有字符:'a''e''i''o''u',并将其都替换为'* '
  while (found!=std::string::npos)
  {
    str[found]='*';
    found=str.find_first_of("aeiou",found+1);
  }

  std::cout << str << '\n';

  return 0;
//Output:
//Pl**s*, r*pl*c* th* v*w*ls *n th*s s*nt*nc* by *st*r*sks.
}

  • find_ first_ not_of:查找字符串中没有字符。在字符串中搜索与其参数中指定的任何字符不匹配的第一个字符。指定pos时,搜索仅包含位置pos及之后的字符。
// string::find_first_not_of
#include <iostream>       // std::cout
#include <string>         // std::string
#include <cstddef>        // std::size_t

int main ()
{
  std::string str ("look for non-alphabetic characters...");

  std::size_t found = str.find_first_not_of("abcdefghijklmnopqrstuvwxyz ");

  //下面的代码就是实现找到str中非小写字母的字符,即'-',并返回'-'的位置。
  if (found!=std::string::npos)
  {
    std::cout << "The first non-alphabetic character is " << str[found];
    std::cout << " at position " << found << '\n';
  }

  return 0;
//Output:
//The first non-alphabetic character is - at position 12
}

  • find_ last_of:从结尾查找字符串。在字符串中搜索与其参数中指定的任何字符匹配的最后一个字符。当pos被指定时,搜索只包含位置pos之前或之前的字符,忽略pos之后的任何可能的事件。
// string::find_last_of
#include <iostream>       // std::cout
#include <string>         // std::string
#include <cstddef>        // std::size_t

void SplitFilename (const std::string& str)
{
  std::cout << "Splitting: " << str << '\n';
  //注意'\\'是反斜杠的转义字符表示,表示一个字符
  std::size_t found = str.find_last_of("/\\");   //在str中搜索与"/\\"中任一个字符匹配的最后一个字符。
  std::cout << " path: " << str.substr(0,found) << '\n';   //pos就是匹配到的位置。0~pos
  std::cout << " file: " << str.substr(found+1) << '\n';   //pos~string结束
}

int main ()
{
  std::string str1 ("/usr/bin/man");
  std::string str2 ("c:\\windows\\winhelp.exe");

  SplitFilename (str1);
  SplitFilename (str2);


// \\Output
// \\Splitting: /usr/bin/man
// \\ path: /usr/bin
// \\ file: man
// \\Splitting: c:\windows\winhelp.exe
// \\ path: c:\windows
// \\ file: winhelp.exe

    system("pause");
    return 0;
}


删除

  • erase:删除pos位置或迭代器处的元素
//删除以下标pos开头的长度为len的子串
string& erase (size_t pos = 0, size_t len = npos);

iterator erase (const_iterator p);
//范围删除
iterator erase (const_iterator first, const_iterator last);
// string::erase
#include <iostream>
#include <string>

int main ()
{
  std::string str ("This is an example sentence.");
  std::cout << str << '\n';
 // "This is an example sentence."
  str.erase (10,8);   //            ^^^^^^^^
  std::cout << str << '\n';
// "This is an sentence."
  str.erase (str.begin()+9);  //           ^
  std::cout << str << '\n';
// "This is a sentence."
  str.erase (str.begin()+5, str.end()-9); //       ^^^^^
  std::cout << str << '\n';
// "This sentence."
  return 0;
}
  • pop_back:删除最后一个字符
void pop_back();
  • clear:清空字符串
void clear();

反转字符串

反转字符串
注意:string类本身并没有提供用于反转的成员函数
要实现字符串反转得使用algorithm中的reverse函数

template <class BidirectionalIterator>
  void reverse (BidirectionalIterator first, BidirectionalIterator last);


功能:
反转区间[first,last)的元素,注意是左闭右开区间

使用示例

#include <iostream>
#include <string> //string
#include<cstring> // strlen
#include <algorithm>//reverse
using namespace std;
 
int main()
{
    //反转string
    string s1 = "hello world";
    reverse(s1.begin(),s1.end());
    cout<<"reverse string: "<<s1<<endl;
    
    //char *s2="I am a char array,not a char pointer";不能反转字符指针指向的字符串(字符串常量)
    //反转字符数组
    char s2[]="I am a char array,not a char pointer";
    reverse(s2,s2+strlen(s2));
    cout<<"reverse char array: "<<s2<<endl;
    
    system("pause");
    return 0;
}

std::getline()从流中获取一行字符串

std::getline用于从流stream中获取一行字符串,赋值给string。记住,这是一个很好用的函数,特别适合从键盘输入流或者文件流中去获取多行数据。
http://www.cplusplus.com/reference/string/string/getline/?kw=getline

//getline的两种用法如下
istream& getline (istream& is, string& str, char delim);
istream& getline (istream& is, string& str);
// extract to string
#include <iostream>
#include <string>

int main ()
{
  std::string name;

  std::cout << "Please, enter your full name: ";
  std::getline (std::cin,name);
  std::cout << "Hello, " << name << "!\n";

  return 0;
}

其他

const char* c_str() const noexcept;

注意const char* 不能用于初始化char *类型的实体.

如下代码会提示错误
const char *str;
char *p=str;
提示错误:

指向const的指针不能被赋给指向非const的指针,所以应该用strcpy,也就是另开一块内存,把字符一个个复制过去

const char *expr = “abcd”;
char *buf = new char[strlen(expr)+1];
strcpy(buf, expr);

示例

// strings and c-strings
#include <iostream>
#include <cstring>
#include <string>

int main ()
{
  std::string str ("Please split this sentence into tokens");

  char * cstr = new char [str.length()+1];
  std::strcpy (cstr, str.c_str());

  // cstr now contains a c-string copy of str

  char * p = std::strtok (cstr," ");
  while (p!=0)
  {
    std::cout << p << '\n';
    p = std::strtok(NULL," ");
  }

  delete[] cstr;
  return 0;
}
  • copy:从字符串复制字符序列
  • replace:替换字符串的一部分。将以pos开头的长度为len的字符串部分(或[i1,i2之间的范围内的字符串部分)替换成新的字符串
// replacing in a string
#include <iostream>
#include <string>

int main ()
{
  std::string base="this is a test string.";
  std::string str2="n example";
  std::string str3="sample phrase";
  std::string str4="useful.";

  // replace signatures used in the same order as described above:

  // Using positions:                 0123456789*123456789*12345
  std::string str=base;           // "this is a test string."
  str.replace(9,5,str2);          // "this is an example string." (1)
  str.replace(19,6,str3,7,6);     // "this is an example phrase." (2)
  str.replace(8,10,"just a");     // "this is just a phrase."     (3)
  str.replace(8,6,"a shorty",7);  // "this is a short phrase."    (4)
  str.replace(22,1,3,'!');        // "this is a short phrase!!!"  (5)

  // Using iterators:                                               0123456789*123456789*
  str.replace(str.begin(),str.end()-3,str3);                    // "sample phrase!!!"      (1)
  str.replace(str.begin(),str.begin()+6,"replace");             // "replace phrase!!!"     (3)
  str.replace(str.begin()+8,str.begin()+14,"is coolness",7);    // "replace is cool!!!"    (4)
  str.replace(str.begin()+12,str.end()-4,4,'o');                // "replace is cooool!!!"  (5)
  str.replace(str.begin()+11,str.end(),str4.begin(),str4.end());// "replace is useful."    (6)
  std::cout << str << '\n';
  return 0;
}
  • substr:生成子字符串
// string::substr
#include <iostream>
#include <string>

int main ()
{
  std::string str="We think in generalities, but we live in details.";
                                           // (quoting Alfred N. Whitehead)

  std::string str2 = str.substr (3,5);     // "think"

  std::size_t pos = str.find("live");      // position of "live" in str 返回pos类型size_t

  std::string str3 = str.substr (pos);     // get from "live" to the end

  std::cout << str2 << ' ' << str3 << '\n';

  return 0;
//Output:
//think live in details.
}
  • compare:比较字符串
// comparing apples with apples
#include <iostream>
#include <string>

int main ()
{
  std::string str1 ("green apple");
  std::string str2 ("red apple");

  if (str1.compare(str2) != 0)         //!=0成立
    std::cout << str1 << " is not " << str2 << '\n';

  if (str1.compare(6,5,"apple") == 0)       //==0成立
    std::cout << "still, " << str1 << " is an apple\n";

  if (str2.compare(str2.size()-5,5,"apple") == 0)    //==0成立
    std::cout << "and " << str2 << " is also an apple\n";

  if (str1.compare(6,5,str2,4,5) == 0)   //==0成立
    std::cout << "therefore, both are apples\n";

  return 0;
}

数字和字符串之间转换

来自http://c.biancheng.net/view/1527.html
http://www.cplusplus.com/reference/string/
C++ 11 提供了若干 to_string(T value) 函数来将 T 类型的数字值转换为字符串形式。
以下是几个 to_string() 函数的列表:

头文件

<string>

http://www.cplusplus.com/reference/string/to_string/?kw=to_string

string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);

字符串到数字的转换可以通过 stoX() 系列函数来执行。该系列函数的成员可以将字符串转换为 int、long、float 和 double 类型的数字。具体语法如下所示:

int stoi(const strings str, size_t* pos = 0, int base = 10)
long stol(const strings str, size_t* pos = 0, int base = 10)
float stof(const strings str, size_t* pos = 0)
double stod(const strings str, size_t* pos = 0)

第一个形参 str 是一个字符串(例如 “-342” 或 “3.48” 等),它将被转换为恰当的数字形式。这些函数可以将 str 可能的最长前缀转换为数字,并返回一个整数地址 pos,pos 中保存了 str 无法被转换的第一个字符的索引。类型 size_t 是在标准库中定义的,常用于表示无符号整数的大小或数组、矢量、字符串中的一个索引。

例如,如果试图转换字符串 “-34iseven”,则将成功返回整数 -34,而无法转换的第一个字符的位置 pos 则被设置为 3。base 形参仅适用于整数转换,指示用于转换的进制。pos 和 base 形参都是可选的,所以它们可以被忽略。如果 pos 被忽略,则不会存储停止字符的索引。如果 base 被忽略,则默认为十进制。如果字符串 str 包含一个无效值,例如 “is-34 even?”,则不会进行转换,函数将抛出一个 invalid_argument 异常。

vector

参考:http://www.cplusplus.com/reference/vector/vector/
vector是一个能够存放任意类型的动态数组,它也适用于标准库中的多种算法。

类模板声明

template<
    class T,
    class Allocator = std::allocator<T>
> class vector;

头文件

#include<vector>

初始化


//默认无参构造
explicit vector (const allocator_type& alloc = allocator_type());
//有参构造,用n个0填充
explicit vector (size_type n);
//有参构造,用n个val填充
vector (size_type n, const value_type& val,
        const allocator_type& alloc = allocator_type());
//迭代器范围构造,左闭右开区间[first,last)
template <class InputIterator>
  vector (InputIterator first, InputIterator last,
          const allocator_type& alloc = allocator_type());
//复制构造
vector (const vector& x);
vector (const vector& x, const allocator_type& alloc);
//移动复制构造
vector (vector&& x);
vector (vector&& x, const allocator_type& alloc);
//初始化列表	
vector (initializer_list<value_type> il,
       const allocator_type& alloc = allocator_type());

示例

//默认无参构造
vector<int> first;
//
vector<int> second(4);

vector<int> three(4,1);

//迭代器范围构造
vector<int> four(three.begin(),three.end());

//复制构造
vector<int> five(three);

//初始化列表构造
vector<int> six({1,2,3,4});

插入

  • insert
//在pos位置前插入value
iterator insert( iterator pos, const T& value );
//在pos前插入count个value
void insert( iterator pos, size_type count, const T& value );
//在pos前插入范围[first,last]的值
template< class InputIt >
void insert( iterator pos, InputIt first, InputIt last);
#include <iostream>
#include <vector>
 
void print_vec(const std::vector<int>& vec)
{
    for (auto x: vec) {
         std::cout << ' ' << x;
    }
    std::cout << '\n';
}
 
int main ()
{
    std::vector<int> vec(3,100);
    print_vec(vec);
 
    auto it = vec.begin();
    it = vec.insert(it, 200);
    print_vec(vec);
 
    vec.insert(it,2,300);
    print_vec(vec);
 
    // "it" no longer valid, get a new one:
    it = vec.begin();
 
    std::vector<int> vec2(2,400);
    vec.insert(it+2, vec2.begin(), vec2.end());
    print_vec(vec);
 
    int arr[] = { 501,502,503 };
    vec.insert(vec.begin(), arr, arr+3);
    print_vec(vec);
}
  • push_back,尾部插入
void push_back( const T& value );
#include <vector>
#include <iostream>
#include <iomanip>
 
int main()
{
    std::vector<std::string> numbers;
 
    numbers.push_back("abc");
    std::string s = "def";
    numbers.push_back(std::move(s));
 
    std::cout << "vector holds: ";
    for (auto&& i : numbers) std::cout << std::quoted(i) << ' ';
    std::cout << "\nMoved-from string holds " << std::quoted(s) << '\n';
}

遍历

  • 基于迭代器遍历
vector<string> first={"one","two","three","four"};
     for(int i=0;i<first.size();i++)
         cout<<first[i]<<" ";
  • 基于for范围遍历
for(auto& i:first){
         cout<<i<<" ";
     }

访问

  • 通过 [] 访问
vector<string> first={"one","two","three","four"};
cout<<first[0]<<endl;
  • 通过at()访问
cout<<first.at(0)<<endl;
  • front:返回第一个元素的引用
reference front();
const_reference front() const;
  • back():返回最后一个元素的引用
 reference back();
const_reference back() const;

获取vector中元素的地址

假设容器中至少有一个元素,则可以通过下面的方法获取容器的初始元素的地址。

std::vector<int> vec(3,100);
&vec[0]
//或者
&vec.front()
//或者
& *vec.begin()

在C ++ 11中,一个新的成员函数被添加到 std :: vector :data()。这个成员函数返回容器中初始元素的地址,等价于&vec.front()。这个成员函数的优点是即使容器是空的也可以调用它。

value_type* data() noexcept;
const value_type* data() const noexcept;
// vector::data
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector (5);
  int* p = myvector.data();

  *p = 10;
  ++p;
  *p = 20;
  p[2] = 100;

  std::cout << "myvector contains:";
  for (unsigned i=0; i<myvector.size(); ++i)
    std::cout << ' ' << myvector[i];
  std::cout << '\n';
  
  return 0;
}

查找

vector没有提供用于查找的成员函数,所以需要用标准库中的算法来实现查找
参考:
https://www.cnblogs.com/Braveliu/p/13019377.html

  • vector中的元素为内置数据类型
#include <iostream>
#include <vector>
#include <string>

// 为了便于示例,声明全局容器
std::vector<std::string> strVec;

void methods(const std::string& target)
{
    // 方法一:遍历容器,查找相等元素判断是否存在
    {
        for (const auto& item : strVec)
        {
            if (item == target)
            {
                std::cout << "method1: find " << target << " exists." << std::endl;
                break;
            }
        }
    }
    // 方法二:获取元素个数,通过个数判断是否存在
    {
        int nCount = std::count(strVec.begin(), strVec.end(), target);
        if (nCount > 0)
        {
            std::cout << "method2: find " << target << " exists." << std::endl;
        }
    }
    // 方法三:查询元素迭代器,通过迭代器有效性判断是否存在
    {
        auto iter = std::find(strVec.begin(), strVec.end(), target);
        if (iter != strVec.end())
        {
            std::cout << "method3: find " << target << " exists." << std::endl;
        }
    }
    // 方法四:查询相等元素的迭代器,通过迭代器有效性判断是否存在
    {
        auto iter = std::find_if(strVec.begin(), strVec.end(), [&](const std::string& item)->bool
            { return (item == target); });
        if (iter != strVec.end())
        {
            std::cout << "method4: find " << target << " exists." << std::endl;
        }
    }
}

int main()
{
    strVec = { "C", "C++", "Java", "Python", "Lua", "Sql" };
    // 场景1:查找Ruby
    std::cout << "Find Ruby" << std::endl;
    methods("Ruby");
    // 场景2:查找C++
    std::cout << "Find C++" << std::endl;
    methods("C++");

    system("pause");
    return 0;
}

// result
/*
Find Ruby
Find C++
method1: find C++ exists.
method2: find C++ exists.
method3: find C++ exists.
method4: find C++ exists.
*/
  • vector中的元素为自定义数据类型
    需要在类型中重载bool operator==()函数
#include <iostream>
#include <map>
#include <string>
#include <vector>

struct Student
{
    std::string code;  // 学号(唯一性标识)
    int grade;         // 年级
    std::map<std::string, double> scores; // <科目,成绩>

    bool operator==(const Student& obj) const
    {
        return obj.code == code; // 只要学号相同即可
    }
};

// 为了便于示例,声明全局容器
std::vector<Student> vecStu;

void methods(const Student& target)
{
    // 方法一:遍历容器,查找相等元素判断是否存在
    {
        for (const auto& item : vecStu)
        {
            if (item == target)
            {
                std::cout << "method1: find exists." << std::endl;
                break;
            }
        }
    }
    // 方法二:获取元素个数,通过个数判断是否存在
    {
        int nCount = std::count(vecStu.begin(), vecStu.end(), target);
        if (nCount > 0)
        {
            std::cout << "method2: find exists." << std::endl;
        }
    }
    // 方法三:查询元素迭代器,通过迭代器有效性判断是否存在
    {
        auto iter = std::find(vecStu.begin(), vecStu.end(), target);
        if (iter != vecStu.end())
        {
            std::cout << "method3: find exists." << std::endl;
        }
    }
    // 方法四:查询相等元素的迭代器,通过迭代器有效性判断是否存在
    {
        if (std::find_if(vecStu.begin(), vecStu.end(), [&](const Student& obj)->bool
            { return (obj == target); }) != vecStu.end())
        {
            std::cout << "method4: find exists." << std::endl;
        }
    }
}

int main()
{
    vecStu.push_back({ "080605109", 6, { {"English", 100}, {"China", 100} } });
    vecStu.push_back({ "080605110", 7, { {"English", 99}, {"China", 70} } });
    vecStu.push_back({ "080605111", 8, { {"English", 98}, {"China", 69} } });
    vecStu.push_back({ "080605112", 6, { {"English", 97}, {"China", 68} } });
    vecStu.push_back({ "080605113", 7, { {"English", 96}, {"China", 67} } });
    Student obj = { "080605114", 8, { {"English", 95}, {"China", 66} } };
    vecStu.push_back(obj);

    // 场景1:查找学号为[0806005109]的学生,我们暂不关注成绩
    std::cout << "Find code: 0806005108" << std::endl;
    methods(Student{ "0806005108", {} });
    // 场景2:查找学号为[0806005114]的学生,我们暂不关注成绩
    std::cout << "Find code: 0806005114" << std::endl;
    methods(obj);
    // 场景3:不想通过学号,只想查找六年级,是否存在英语和语文全为满分的学生
    auto iter = std::find_if(vecStu.begin(), vecStu.end(), [&](const Student& obj)->bool
        { return (obj.grade == 6 &&
            obj.scores.find("English")->second == 100 &&
            obj.scores.find("China")->second == 100); });
    if (iter != vecStu.end())
    {
        std::cout << "method: find 100 exists." << std::endl;
    }

    return 0;
}

// result
/*
Find code: 0806005108
Find code: 0806005114
method1: find exists.
method2: find exists.
method3: find exists.
method4: find exists.
method: find 100 exists.
*/

删除

  • erase:删除迭代器position位置的元素
iterator erase (const_iterator position);
iterator erase (const_iterator first, const_iterator last);
//删除pos指向的元素
iterator erase( iterator pos );
//范围删除
iterator erase( iterator first, iterator last );
  • pop_back:删除尾部的一个元素

  • clear:清空vector元素,不能访问后面的数据,但没有释放空间

  • 如果需要释放内存,可以使用swap函数,用法如下:

std::vector<T>().swap(X);//先构造匿名vector,然后交换
作用相当于:
{ 
  std::vector<T> temp;//1.构造空的临时vector
  temp.swap(X); //2.和X交换后,X为空
}
//临时变量离开作用域就调用析构函数释放内存。

其他

  • resize:重置vector容器的容量
void resize( size_type count, T value = T() );
void resize( size_type count );
void resize( size_type count, const value_type& value );

resize()做的操作是直接修改了容量大小,让我不能访问后面的数据,而不是释放空间。重新指定大小后,后面有空间就浪费掉了(因为他们存在,但不能使用)
swap()可以解决这个问题
参考连接

vector<int>(v).swap(v);	//v是容器名

也就是说通过该语句,可以将v中空闲的空间释放掉。

这条语句可以分为两个部分:
vector(v).swap(v) 两部分

第一部分vector(v)
这条语句,通过 拷贝构造函数 创建了一个 匿名对象 ,这个匿名对象拥有v的全部数据,但是,没有空闲的空间,也就是说,这个匿名对象的容量和存储的数据量是相等的。经过 vector(v) 创建出来的匿名对象是没有空闲空间的。
第二部分 .swap(v) 调用该匿名类的swap()方法,交换v与匿名类的内容,结果如下
在这里插入图片描述
最后,该行语句指向完毕,匿名类被析构,空间被释放。
最终结果就是,原容器中的空位被释放

resize使用示例

#include <iostream>
#include <vector>
int main()
{
    std::vector<int> c = {1, 2, 3};
    std::cout << "The vector holds: ";
    for(auto& el: c) std::cout << el << ' ';
    std::cout << '\n';
    c.resize(5);
    std::cout << "After resize up to 5: ";
    for(auto& el: c) std::cout << el << ' ';
    std::cout << '\n';
    c.resize(2);
    std::cout << "After resize down to 2: ";
    for(auto& el: c) std::cout << el << ' ';
    std::cout << '\n';
}
//Output:
//The vector holds: 1 2 3
//After resize up to 5: 1 2 3 0 0
//After resize down to 2: 1 2

二维vector

转到https://blog.csdn.net/qq_35987777/article/details/105905452

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值