string
需要注意,为了跟C语言兼容,字符串字面值与string是不同的类型。要使用string,先包含如下的内容:
-
#include <string>
-
using
std::
string;
初始化string的方式:
如果不赋值,就得到空字符。如果使用“=”就是拷贝初始化,否则就是直接初始化。像S4那样的操作,只能使用直接初始化;而S2和S3则直接初始化和拷贝初始化都可以使用。
string操作:
使用cin输入到string对象,会自动忽略开头的空白,值到遇到下一个空白为止,其间的内容才会被放到string对象中,也即是string对象中不会有空白字符。如果想要保留输入的空白字符,可以使用getline()函数,它会将换行符之前的所有内容都放到string对象,注意不包含换行符本身。当然,两者遇到EOF(按Ctrl+z再按Enter)都会退出。
size()返回的类型是string::size_type,它是无符号类型,且足够放下任何string对象的大小。注意size()的返回没有包含字符串最后的空字符(其实是没有空字符),所以"a"这个字符串的size()返回值是1:
-
int main()
-
{
-
string st("a");
-
cout << st.size() <<
endl;
-
return
0;
-
}
这里打印的结果是1。
string对象中的字符可以单独修改。可以通过for来遍历字符:
-
int main()
-
{
-
string s("Hello World");
-
for (
auto a : s) {
-
cout << a <<
endl;
-
}
-
-
return
0;
-
}
也可以修改字符:
-
int main()
-
{
-
string s("Hello World");
-
for (
auto &a : s) {
-
a =
toupper(a);
-
}
-
cout << s <<
endl;
-
-
return
0;
-
}
这里将string对象中的字符都转换成了大写。需要注意跟上一个例子的差异,这里for循环中使用了引用而不是新的变量,否则修改没有意义。
string对象也可以通过[]用下标访问:
-
int main()
-
{
-
string s("Hello World");
-
for (
auto i =
0; i <= s.size(); i++) {
-
s[i] =
toupper(s[i]);
-
}
-
cout << s <<
endl;
-
-
return
0;
-
}
像toupper这样的函数,在C语言也有相同功能和名称的函数,在C++中也可以使用,如下:
还有对C风格字符串的操作(位于<cstring>):
上述函数不能作用于string对象。注意C风格字符串其实是数组,且以空字符结束。C++中最好不要使用它们。
从内置类型转到string可以使用to_string()函数:
-
int main()
-
{
-
int i =
42;
-
// converts the int i to its character representation
-
string s = to_string(i);
-
-
return
0;
-
}
vector
vector表示对象的集合,包含的对象类型需要是相同的,但是不能包括引用(因为引用不是对象)。vector是容器的一种,后面还会介绍其它容器。要使用vector,先包含如下的内容:
-
#include <vector>
-
using
std::
vector;
vector的初始化:
如果未初始化,得到的是空的vector。=是拷贝初始化。如果提供初始元素值,则使用“{}”来初始化。注意跟使用“()”的差别,它是指n个val来初始化vector,val可以是默认值,有对象T本身的类型决定默认值是什么。“{}”可以做“()”能做的初始化,而反过来则不行。
vector的操作:
size()返回的值不是vector::size_type,而是vector<T>::size_type,T是具体的类型,比如int。通过下标可以索引vector,但是不能添加元素,添加元素使用push_back()。
vector的示例:
-
int main()
-
{
-
// list initialization, articles has 3 elements
-
vector<
string> articles = {
"a",
"an",
"the"};
-
-
vector<
string> svec;
// default initialization has no elements
-
vector<
int> ivec;
// ivec holds objects of type int
-
vector<Sales_item> Sales_vec;
// holds Sales_items
-
-
vector<
vector<
string>> file;
// vector whose elements are vectors
-
vector<
vector<
int>> vecOfvec;
// each element is itself a vector
-
-
// all five vectors have size 0
-
cout << svec.size() <<
" " << ivec.size() <<
" "
-
<< Sales_vec.size() <<
" "
-
<< file.size() <<
" " << vecOfvec.size() <<
endl;
-
-
vector<int> ivec2(10);
// ten elements, each initialized to 0
-
vector<int> ivec3(10, -1);
// ten int elements, each initialized to -1
-
vector<string> svec2(10);
// ten elements, each an empty string
-
vector<string> svec3(10, "hi!");
// ten strings; each element is "hi!"
-
cout << ivec2.size() <<
" " << ivec3.size() <<
" "
-
<< svec2.size() <<
" " << svec3.size() <<
endl;
-
-
// 10 is not a string, so cannot be list initialization
-
vector<string> v1(10);
// construct v1 with ten value-initialized elements
-
vector<
string> v2{
10};
// ten elements value-initialized elements
-
vector<string> v3(10, "hi");
// ten elements with value "hi"
-
// again list initialization is not viable, so ordinary construction
-
vector<
string> v4{
10,
"hi"};
// ten elements with values "hi"
-
-
// all four vectors have size ten
-
cout << v1.size() <<
" " << v2.size()
-
<<
" " << v3.size() <<
" " << v4.size() <<
endl;
-
-
vector<
string> vs1{
"hi"};
// list initialization: vs1 has 1 element
-
vector<
string> vs2{
10};
// ten default-initialized elements
-
vector<
string> vs3{
10,
"hi"};
// has ten elements with value "hi"
-
cout << vs1.size() <<
" " << vs2.size() <<
" " << vs3.size() <<
endl;
-
-
vector<int> v5(10, 1);
// ten elements with value 1
-
vector<
int> v6{
10,
1};
// two elements with values 10 and 1
-
cout << v5.size() <<
" " << v6.size() <<
endl;
-
-
// intention is clearer
-
vector<
int> alt_v3 = {
10};
// one element with value 10
-
vector<
int> alt_v4 = {
10,
1};
// two elements with values 10 and 1
-
cout << alt_v3.size() <<
" " << alt_v4.size() <<
endl;
-
for (
auto a : alt_v4) {
-
cout << a <<
endl;
-
}
-
for (
auto i =
0; i < alt_v4.size(); i++) {
-
cout << alt_v4[i] <<
endl;
-
}
-
-
return
0;
-
}
这里需要主要v2和v4,它们都使用了“{}”,但是因为成员是string,所以10不会被解释成string,而是解释成了个数,所以v2是10个空字符串的vector,跟v1一致;v4是包含10个"hi"的vector,跟v3一致。
迭代器
前面使用了for、下标等方式访问string和vector,还可以使用迭代器来遍历string和vector。迭代器跟指针类似,就是通过从头到尾访问元素的方式完成遍历。string和vector,以及后面会介绍的容器,都支持迭代器,它们拥有begin()和end()两个成员用于返回迭代器,前者指向开头,后者指向尾后,即最后一个元素的下一个(不存在的)元素。如果迭代器类型对象本身为空,则begi和end返回的都是尾后。
标准容器迭代器的操作:
而string和vector支持的更多:
n是一个整型数值,但是两个迭代器相减,得到的是类型为difference_type的值,它是带符号整型数。
关于迭代器的示例:
-
int main()
-
{
-
string s("Hello World");
-
for (
auto iter = s.begin(); iter != s.end(); iter++) {
-
*iter =
toupper(*iter);
-
}
-
cout << s <<
endl;
-
-
return
0;
-
}
对于迭代器的类型,一般直接就写auto了,让编译器来决定。不过实际上我们还是可以确定其类型的,比如上面的示例中,iter的类型是string::iterator。begin()和end()返回的迭代器可用于修改值,因为*iter是引用,但是如果想要返回的迭代器只用于读操作,则可以使用其const版本:cbegin()和cend(),它返回的是const_iterator。
vector可以通过push_back()插入元素,此时原本的迭代器就失效了,这需要注意。
数组
数组跟C语言中的没有太大区别。C++中增加了迭代器给数组用,使用begin()和end()函数(它们属于std),并返回成员的指针,也就是说指针成了迭代器,可以使用迭代器的运算操作。两个指针相减得到的是类型为ptrdiff_t的值。在C++中编译器在使用数组的时候会把它转换成指针。
关于数组遍历的示例:
-
int main()
-
{
-
int a[] = {
1,
2,
3,
4};
-
int *pb =
std::begin(a);
-
int *pe =
std::end(a);
-
for (; pb != pe; pb++) {
-
cout << *pb <<
endl;
-
}
-
-
return
0;
-
}
返回的指针也是一个指向数组开头,一个指向数组尾后。
转载:https://blog.csdn.net/jiangwei0512/article/details/116465445