[C++]stringvector和数组
Posted jiangwei0512
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C++]stringvector和数组相关的知识,希望对你有一定的参考价值。
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;
}
返回的指针也是一个指向数组开头,一个指向数组尾后。
以上是关于[C++]stringvector和数组的主要内容,如果未能解决你的问题,请参考以下文章