第三章 字符串,向量和数组
3.1 命名空间 using
头文件不应该包含 using 声明,因为会拷贝到其它文件中
命名空间 using 声明 :using namespace::name;
#include<iostream>int main(){ std::cout << "Enter two number" << std::endl; int v1, v2; std::cin >> v1 >> v2; std::cout << "The sum of " << v1 << " and " << v2 << " is " << v1 + v2 << std::endl; return 0; }
#include<iostream>using std::cin; using std::cout; using std::endl; int main(){ cout << "Enter two number" << endl; int v1, v2; cin >> v1 >> v2; cout << "The sum of " << v1 << " and " << v2 << " is " << v1 + v2 << endl; return 0; }
3.2 标准库类型 string
标准库类型 string :长度可变的字符序列,需包含string头文件
#include<iostream>#include<string>using std::string; int main(){ string s1; //空字符串 string s2 = s1; //副本,拷贝构造,等价于 string s2(s1) string s3 ="aaa"; //副本,等价于 string s3("aaa") string s4(3, 'a'); //等价于 aaa return 0; }
string 对象上的操作
string s1, s2; std::cin >> s1 >> s2; std::cout << s1 << s2 << std::endl;
打印结果
Hello World HelloWorld 请按任意键继续. . .
换行被视为字符串的结束符
Hello Hello World World
字面值和string对象相加
C++ 中字符串字面值是 const char*
string s1 ="Hello",s2 ="World"; string s3 = s1 +","+"s2"+"\n"; string s4 = s1 +","; string s5 ="Hello"+"World"; //报错
cctype头文件(ctype.h)中的函数
C++ 将C语言标准库中的内容,命名为cname(不含.h)
cctype 头文件(ctype.h)中的函数
/* 统计标点符号 */ std::string s("HELLO WORLD!!!"); //unsiged decltype(s.size()) count =0; for (auto c : s){ if (ispunct(c)){ ++count; } } std::cout << "The count is " << count << std::endl;
高级 for 循环中,不改变原值,使用 auto;改变容器元素值,使用 auto&
/* 转换大小写 */ std::string s1 = s; for (auto& c : s1){ if (isupper(c)){ c = tolower(c); }else{ c = toupper(c); } } std::cout << s1 << std::endl;
/* 只在空格前,转换大小写 */ std::string s2 = s; decltype(s2.size()) index =0; while (index != s2.size() && !isspace(s2[index])) { if (isupper(s2[index])){ s2[index] = tolower(s2[index]); }else{ s2[index] = toupper(s2[index]); } ++index; } std::cout << s2 << std::endl;
/* (0 -15) 十进制转十六进制 */ const std::string bucket ="0123456789ABCDEF"; std::string result; std::string::size_type number; while (std::cin >> number){ if (number < bucket.size()){ result = bucket[number]; } } std::cout << result << std::endl;
3.3 标准库类型 Vector
标准库类型 vector :对象的集合,不存在包含引用的 vector
初始化 vector 对象的方法
/* 求元素的平方 */ std::vector<int> v1{ 1, 2, 3, 4, 5, 6 }; for (auto& item : v1){ item *= item; }
/* 输入0-100的分数 分段:0-9,10-19 ... 90-99,100 统计各个分段成绩人数 */ std::vector<unsigned> scores(11, 0); // 11 buckets,all initially 0unsigned grade; while (std::cin >> grade) { ++scores[grade / 10]; } for (auto i : scores){ std::cout << i << std::endl; }
3.4 迭代器 Iterator
迭代器介绍
类似指针,使用迭代器可访问某个元素,迭代器也能从一个元素移动到另一个元素
迭代器类型都拥有 begin 和 end 成员
begin:返回指向第一个元素的迭代器
end:尾后迭代器,返回最后一个元素的下一个位置(一个不存在元素的位置)
若容器为空,则 begin 和 end 返回的是同一个迭代器,都是尾后迭代器
尾后迭代器并不指向某一个元素,因此不能对其递增或解引用
/* 大小写转换 */ std::string s("i like c++"); //注意声明迭代器的类型 std::string::iterator it = s.begin(); while (it != s.end()){ *it = toupper(*it); ++it; } /* 第一个空格前,大小写转换 FOR循环会更加简洁,对于以递增变量作为判断循环跳出条件 */ for(auto it = s.begin(); it != s.end() && !isspace(*it) ; ++it){ *it = toupper(*it); }
迭代器类型
迭代器标准类型 iterator 和 const_iterator(和常量指针类似)
// it1 可读写vector<int>的元素 std::vector<int>::iterator it1; // it2 可读写string的字符 std::string::iterator it2; // it3只可读vector<int>的元素,不可写 std::vector<int>::const_iterator it3;
若对象是常量,则 begin 和 end 返回 const_iterator,否则返回 iterator
std::vector<int> v1; const std::vector<int> v2; auto it1 = v1.begin(); //it1的类型是 std::vector<int>::iterator auto it2 = v2.begin(); //it2的类型是 std::vector<int>::const_iterator
对象不是常量仍使用 const_iterator,C++11 引入了 cbegin 和 cend
auto it2 = v1.cbegin(); //it3的类型是 std::vector<int>::const_iterator
结合解引用的成员访问
任何一种可能改变 vector 对象容量的操作,都会使迭代器失效
std::vector<std::string> v; //it的类型 std::vector<std::string>::iterator auto it = v.begin(); //解引用后,返回所指对象的引用,调用string的empty方法 (*it).empty(); //it.empty(); 错误 // ->箭头运算符 等同于把解引用和成员访问两个操作合并 it->empty();
/* 练习 cbegin & cend & -> */ std::vector<std::string> v(3, "HELLO"); for (auto it = v.cbegin(); it != v.cend()&& !it->empty(); ++it){ std::cout << *it << std::endl; }
/* 二分查找 */ std::vector<int> v = { 0,1, 2, 3, 4, 5 }; int target =2; auto beg = v.begin(),end = v.end(); auto mid = beg + (end - beg) / 2;//初识状态下的中间点 while (mid != end && *mid != target) { if (target < *mid) { end = mid -1; } else { beg = mid +1; } mid = beg + (end - beg) / 2; } if (mid != v.end()) { std::cout << "找到了" << std::endl; } else { std::cout << "未找到" << std::endl; }