using声明
标准库类型string
#include <string>
using std::string
定义和初始化string对象
string s1
string s2(s1)
string s2 = s1
string s3("value")
string s3 = "value"
string s4(n,'c')
直接初始化和拷贝初始化
string s5 = "yiya";
string s6("yiya");
string s7(10,'c');
string s8 = string(10,'c');
string对象上的操作
os << s
is >> s
getline(is, s)
s.empty()
s.size()
s[n]
s1+s2
s1=s2
s1==s2
s1!=s2
<, <=, >, >=
int main(){
string s;
cin >> s;
cout << s << endl;
return 0;
}
#include <string>
#include <iostream>
using namespace std;
int main(){
string word;
while(cin>>word){
cout<<word<<endl;
}
return 0;
}
int main(){
string line;
while(getline(cin,line)){
cout<<line<<endl;
}
return 0;
}
string::size_type类型
- string.size() 的返回类型 是无符号类型的值
- 可通过auto,decltype推断变量的类型:auto len = line.size()那么len的类型就是string::size_type
- 表达式中有了size()函数就不要在使用int,可避免混用int和unsigned可能带来的问题。
字面值与string相加
- 加法运算符的两侧的运算对象至少有一个是string
string s5 = s1 + "," + "hello";
string s6 = "hello" + "," + s2;
处理string对象中的字符
- ctype.h VS cctype :C++修改了C标准库,名称去掉.h,前面加c
- cctype头文件定义了一组标准函数
isalnum(c)
isalpha(c)
iscntrl(c)
isdigit(c)
isgraph(c)
islower(c)
isprint(c)
ispunct(c)
isspace(c)
isupper(c)
isxdigit(c)
tolower(c)
toupper(c)
string str("some string");
for(auto c : str){
cout << c << endl;
}
string s("hello world!!!");
decltype(s.size()) punct_cnt = 0;
for(auto c:s){
if(ispunct(c)):
punct_cnt += 1;
}
cout<<punct_cnt<<"punctuation characters in"<<s<<endl;
string s("hello");
for(auto &c : s):
c = toupper(c);
cout<<s<<endl;
string s("some string");
if(!s.empty())
s[0] = toupper(s[0])
for(decltype(s.size()) index = 0;index != s.size() && !isspace(s[index]);++index)
s[index] = toupper(s[index])
const string hexdigits = "0123456789ABCDEF";
string result;
string::size_type n;
while(cin>>n)
if(n<hexdigits.size())
result += hexdigits[n];
cout<<result<<endl;
标准库类型vector
#include <vector>
using std::vector;
- 容器包含其他对象。类模板本事不是类,但可以实例化出一个类。vector是一个模板,vector<>是一个类型。
vector<int> ivec;
vector<Sales_item> Sales_vec;
vector<string> file;
vector<vector<string>> file;
vector<T> v1
vector<T> v2(v1)
vector<T> v2 = v1
vector<T> v3(n, val)
vector<T> v4(n)
vector<T> v5{a, b, c...}
vector<T> v5={a, b, c...}
vector<string> articles = {"a","an","the"};
vector<string> articles{"a","an","the"};
- 值初始化 int型默认初始值自动设为0,string,默认初始值设为空string对象
- 注意 () {} 的区别
vector<int> v1(10);
vector<int> v2{10};
vector<string> v3{"hi"};
vector<string> v4("hi");
vector<string> v5{10};
vector<string> v6{10,"hi"};
向vector对象中添加元素
vector<int> v2;
for(int i=0;i!=100;i++)
v2.push_back(i);
string word;
vector<string> text;
while(cin>>word){
text.push_back(word);
}
- 若循环体内部包含有向vector对象添加元素的语句,则不能使用范围for循环,原因见5.4.3
其他vector操作
v.emtpy()
v.size()
v.push_back(t)
v[n]
v1 = v2
v1 = {a,b,c...}
v1 == v2
v1 != v2
<,<=,>, >=
vector<int> v{ 1,2,3,4,5,6,7,8,9 };
for (auto& c : v)
c *= c;
for (auto c : v)
cout << c << endl;
vector<int>::size_type;
vector::size_type;
计算vector内对象的索引
vector<unsigned> scores(11,0);
unsigned grade;
while(cin>>grade){
if(grade<=100)
++scores[grade/10];
}
不能用下标形式添加元素 因为刚开始vector是不包含任何元素的,也就无下标一说。正确方式为push_back
vector<int> ivec;
for(decltype(ivec.size()) index = 0;index!=10;++index)
ivex.push_back(index);
迭代器iterator
- 所有标准库容器都可以使用迭代器。
- 类似于指针类型,迭代器也提供了对对象的间接访问。
使用迭代器
auto b = v.begin(),e = v.end();
- 如果容器为空, begin()和 end()返回的是同一个迭代器,都是尾后迭代器。
- 使用解引用符*访问迭代器指向的元素。
- 养成使用迭代器和!=的习惯(泛型编程)。
- 容器:可以包含其他对象;但所有的对象必须类型相同。
- 迭代器(iterator):每种标准容器都有自己的迭代器。C++倾向于用迭代器而不是下标遍历元素。
- const_iterator:只能读取容器内元素不能改变。
- 箭头运算符: 解引用 + 成员访问,it->mem等价于 (*it).mem‘
- 谨记:但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。
*iter
iter->mem
++iter
--iter
iter1 == iter2
string s("some string");
if(s.begin() != s.end())
auto it = s.begin();
*it = toupper(*it);
for(auto it = s.begin();it != s.end() && !isspace(*it);++it)
*it = toupper(*it);
迭代器类型:iterator,const_iterator
vector<int>::iterator it;
string::iterator it2;
vector<int>::const_iterator it3;
string::const_iterator it4;
begin和end运算符
vector<int> v;
const vector<int> cv;
auto it1 = v.begin();
auto it2 = cv.begin();
- 为便于专门得到const_iterator类型的返回值,引入cbegin,cend
auto it3 = v.cbegin();
结合解引用和成员访问操作
(*it).empty();
it->item;
for(auto it=text.cbegin();it!=text.cend() && !it->empty();++it)
cout<<*it<<endl;
- 迭代器失效的情况:不能在范围for循环中向vector对象添加元素;push_back会使该vector对象的迭代器失效。见9.3.6
迭代器运算
iter + n
iter - n
iter1 += n
iter1 -= n
iter1 - iter2
>、>=、<、<=
auto mid = vi.begin() + vi.size()/2;
if(it<mid)
- difference_type类型是带符号整型数,表迭代器间距离
使用迭代器进行二分搜索
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;
}
数组(大小固定)
- 初始化:char input_buffer[buffer_size];,长度必须是const表达式,或者不写,让编译器自己推断。
- 显式初始化,初始化字符数组时注意空字符。
- 数组不允许直接赋值给另一个数组。也不允许使用一个数组初始化另一个数组。
int (*Parray)[10] = &arr;
int (&arrRef)[10] = arr;
int *(&array)[10] = ptrs;
访问数组元素
- 数组下标的类型:size_t 。
- 字符数组的特殊性:结尾处有一个空字符,如 char a[] = "hello";
- 用数组初始化 vector: int a[] = {1,2,3,4,5}; vector v(begin(a), end(a)); 。
数组和指针
int ia[] = {0,1,2,3,4,5,6,7,8,9};
auto ia2(ia);
int *e = &arr[10];
for(int *b=arr;b!=e;++b)
cout<<*b<<endl;
int ia[] = {0,1,2,3,4,5,6,7,8,9};
int *beg = begin(ia);
int *last = end(ia);
int ia[] = {0,2,4,6,8};
int *p = &ia[2];
int j = p[1];
int k = p[-2];
C风格字符串
- 用于c风格字符串的函数,在头文件cstring中。即C中string.h
strlen(p)
strcmp(p1, p2)
strcat(p1, p2)
strcpy(p1, p2)
char ca[] = {'C','b','c'};
cout<<strlen(ca)<<endl;
- 比较字符串 不能跟string对象比,需要用到strcmp函数
const char ca1[] = "";
const char ca2[] = "";
if(ca1<ca2)
if(strcmp(ca1,ca2)<0)
strcpy(largeStr,ca1);
strcat(largeStr," ");
strcat(largeStr,ca2);
混用string对象和c风格字符串
string s("hello");
char *str = s;
const char *str = s.c_str();
使用数组初始化vector对象
int int_arr[] = {0,1,2,3,4,5};
vector<int> ivec(begin(int_arr),end(int_arr));
vector<int> subVec(int_arr + 1,int_arr + 4);
多维数组
- 即数组的数组,一个维度表示数组本身大小,另外一个维度表示其元素大小。
int (&row)[4] = ia[1];
constexpr size_t rowCnt=3,colCnt=4;
int ia[rowCnt][colCnt];
for(size_t i=0;i!=rowCnt;++i){
for(size_t j=0;j!=colCnt;++j){
ia[i][j] = i*colCnt+j;
}
}
size_t cnt = 0;
for(auto &row : ia)
for(auto &col : row){
col = cnt;
++cnt;
}
for(const auto &row : ia)
for(auto col : row)
cout<<col<<endl;
- 使用范围for语句时,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。
指针与多维数组
int ia[3][4];
int (*p)[4] = ia;
p = &ia[2];
for(auto p = ia;p!=ia+3;++p)
for(auto q = *p;q!=*p+4;++q)
cout<<*q<<' ';
cout<<endl;
for(auto p =begin(ia);p!=end(ia);++p){
for(auto q=begin(*p);q!=end(*p);++q)
cout<<*q<<' ';
cout<<endl;
}
类型别名简化多维数组的指针
using int_array = int[4];
typedef int int_array[4];
for(int_array *p = ia;p!=ia+3;++p){
for(int *q = *p; q!=*p+4;++q)
cout<<*q<<' ';
cout<<endl;
}