#include <iostream>
#include <cctype>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
int main() {
//迭代器iterator也可以访问string对象的字符或vector对象的元素
//所有标准库容器都可以使用迭代器,但是其中只有少数几种才同时支持小标运算符
//严格来说string不属于容器类型,但string支持很多与容器类型类似的操作
//类似于指针类型,迭代器体统对对象的间接访问
//迭代器有有效和无效之分,有效的迭代器或者指向某个元素,或者指向容器中尾元素的下一位置
//其他所有情况都属于无效
/****和指针不同的是,获取迭代器不使用地址符***/
vector<int> v;
auto b = v.begin(), e = v.end(); //b和e的类型相同
//b表示v的第一个元素,e表示v尾元素的下一位置
//end成员返回的迭代器常被称作尾后迭代器off-the-end iterator 或尾迭代器 end iterator
//它没有什么实际含义,仅是一个标记,表示我们已经处理完了容器中的所有元素
/*****如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器****/
//如果两个迭代器指向的元素相同或者是同一个容器的尾后迭代器,则它们相等
//否则着两个迭代器不相等
//标准容器迭代运算符
/* *iter 返回迭代器iter所指元素的引用
* iter->man 解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
* ++iter 令iter指示容器中的下一个元素
* --iter 令iter指示容器中的上一个元素
* iter1==iter2 判断两者迭代器是否相等(不相等),如果两个迭代器指示的是同一个元素
* iter1!=iter2 或者它们是同一个容器的尾后迭代器,则相等;反之,不相等
*/
string s("some string");
if (s.begin() != s.end()) { //确保s非空
auto it = s.begin(); //it表示s的第一个字符
*it = toupper(*it); //将当前字符改成大写形式
}
cout << s << endl;
//把string对象中的第一个单词改为大写
//依次处理s的字符直至我们处理完全部字符或者遇到空白
for (auto it1 = s.begin(); !isspace(*it1) && it1 != s.end(); ++it1) {
*it1 = toupper(*it1); //将当前大写字符改成大写形式
}
cout << s << endl;
//
/****所有标准库容器的迭代器都定义了==和!=,但是它们中的大多数都没有定义<运算符***/
/****只要养成使用迭代器和!=的习惯,就不用太在意用的到底是哪种容器类型*****/
//标准库的类型使用iterator和const_iterator来表示迭代器的类型
vector<int>::iterator it9; //it能读写vector<int>的元素
string::iterator it2; //it2能读写string的元素
vector<int>::const_iterator it3; //it3只能读元素,不能写元素
string::const_iterator it4; //it4只能读字符,不能写字符
vector<int> v1;
const vector<int> cv;
auto it5 = v1.begin(); //it5的类型是vector<int>::iterator
auto it6 = cv.begin(); //it6的类型是vector<int>::const_iterator
//为了得到const_iterator类型的返回值,C++11引入了cbegin和cend
auto it7 = v.cbegin(); //it7的类型是vector<int>::const_iterator
/*
*l例 it->empty(); 表示先对it解引用,然后解引用的结果再执行点运算符
*/
//依次输出text的每一行直至遇到第一个空白行为止
vector<string> text;
for (auto it8 = text.cbegin(); it8 != text.cend() && !it8->empty(); ++it8)
cout << *it9 << endl;
//??????设置vector text时不明白怎么设置空白行元素,几次尝试,依然执行出错
//???????
//***注意:任何一种可能改变vector对象容量的操作,如push_back,都会使其迭代器失效
//***************谨记:但凡使用了迭代器的循环体,都不要向迭代器所属的容器添加元素
/*
//练习重做3.3.3节第一个练习,可是我就是讨厌这个练习咋办,在3.3.3我都选择把它跳过了
//hate这种事,藏在灵魂里,再劝说也没用。耽误了30分钟后我终于找到了折中的办法——copy the answer
vector<int> v1;
vector<int> v2(10);
vector<int> v3(10,42);
vector<int> v4{10};
vector<int> v5{10,42};
vector<string> v6{10};
vector<string> v7{ 10,"hi" };
cout<<"v1的元素个数是: "<<v1.size()<<endl;
if(v1.cbegin() != v1.cend()) //当vector含有元素时逐个输出
{
cout<<"v1的元素分别是: "<<endl;
for(auto it=v1.cbegin();it!=v1.cend();++it)
{
cout<<*it<<" ";
}
cout<<endl;
}
cout<<"v2的元素个数是: "<<v2.size()<<endl;
if(v2.cbegin()!=v2.cend())
{
cout<<"v2的元素分别是:"<<endl;
for(auto it=v2.cbegin();it!=v2.cend();++it)
cout<<*it<<" ";
cout<<endl;
}
cout<<"v3的元素个数是:"<<v3.size()<<endl;
if(v3.cbegin()!=v3.cend())
{
cout<<"v3的元素分别是: "<<endl;
for(auto it=v3.cbegin();it!=v3.cend();++it)
cout<<*it<<" ";
cout<<endl;
}
*/
//oh,有7个,但是它们有什么区别呢,抄作业已抄够,我决定放过自己,next
//修改之前那个输出text第一段的程序,首先把text的第一段全都改称大写形式,然后再输出它
//我的尝试:
cout << "接下来请输入一篇文章或一段文字:" << endl;
string line;
vector<string> text1;
while (getline(cin, line)) {
text1.push_back(line);
}
if (text1.begin() != text1.end()) {
for (auto it = text1.begin(); it != text1.end() && !it->empty(); ++it) {
auto a = (*it);
for (auto& b : a) {
b = toupper(b);
}
*it = a;
cout << *it;
}
}
cout << endl;
cin.clear();
//????存在问题,出现换行,换行符会被忽略——暂时没想出解决方法
//课本答案:
vector<string> text2;
string s1;
while (getline(cin, s1))
text2.push_back(s1);
for (auto it = text2.begin(); it != text2.end() && !it->empty(); ++it)
{
for (auto it2 = it->begin(); it2 != it->end(); it2++)
*it2 = toupper(*it2);
cout << *it << endl;
}
cin.clear();
//编写一段程序,创建一个含有10个整数的vector对象,然后使用迭代器将所有元素的值都编程原来的两倍
//输出vector对象的内容,检验程序是否正确
cout << "接下来请输入10个整数:" << endl;
vector<int> obj;
int ten;
for (int a = 0; cin >> ten && a < 10; ++a) {
obj.push_back(ten);
}
for (auto it = obj.begin(); it != obj.end(); ++it) {
(*it) *= *it; //呕吼,应该是乘2,我怎么搞成了平方!!!
cout << *it << " ";
}
cout << endl;
cin.clear();
//课本答案
vector<int> vInt;
srand((unsigned)time(NULL)); //生成随机数种子 ?????啥玩意?还没学到啊,一脸懵逼就是我
for (int i = 0; i < 10; i++) //循环十次
{
//每次循环生成一个1000以内的随机数并添加到vInt中
vInt.push_back(rand() % 1000); //????这是在降维打击我不懂???!!
}
cout << "随机生成的10个数字是: " << endl;
for (auto it = vInt.cbegin(); it != vInt.cend(); it++)
{
cout << *it << " ";
}
cout << endl;
cout << "翻倍后的10个数字是: " << endl;
for (auto it = vInt.begin(); it != vInt.end(); it++)
{
*it *= 2;
cout << *it << " ";
}
cout << endl;
//迭代器运算 iterator arithmetic
/* iter+n 迭代器上加一个整数仍得一个迭代器,迭代器指示的新位置与原来相比向前移动
* 若干个元素。结果迭代器指示容器内的一个元素,或者指示容器尾元素的下一位置
* iter-n 迭代器减去一个整数仍得一个迭代器,迭代器指示的新位置与原来相比向后移动
* 若干个元素。结果迭代器指示容器内的一个元素,或者指示容器尾元素的下一位置
* iter1 += n 迭代器加法的复合赋值语句,将iter1加n的结果赋给iter1
* iter1 =+ n 迭代器剑法的复合赋值语句,将iter1减n的结果赋给iter1
* iter1-iter2 两个迭代器相减的结果是它们之间的距离,也就是说,将运算符右侧的迭代器向前
* 移动差值个元素后将得到左侧的迭代器。参与运算的两个迭代器必须指向的是同一个容器中的元素
* 或者尾元素的下一位置
* > >= < <= 迭代器的关系运算符,如果某迭代器指向的容器位置在另一个迭代器所指位置之
* 前,则说前者小于后者。参与运算的两个迭代器必须指向的是同一个容器中的元素或者尾元素的下
* 一位置
*/
//auto mid = vInt.begin() + vInt.size() / 2;
//得到最接近vInt中间元素的一个迭代器
//if (it < mid)
//处理vInt前半部分的元素
//只要两个迭代器指向的是同一个容器中的元素或者尾元素的下一位置,就能将其相减
//得到的结果是两个迭代器的距离,其类型名是defference_type的带符号整数型
//string和vector都定义了difference_type,因为该距离可正可负,所以是带符号类型
/*******使用迭代器运算的一个经典算法是二分搜索********/
//text2必须是有序的
//beg和end表示我们搜索的范围
vector<int> text3 = { 1,3,5,7,9,11,13,15,17,19 };
auto beg = text3.begin(), end1 = text3.end();
auto mid = text3.begin() + (end1 - beg) / 2;
int sought = 5;
while (mid != end1 && *mid != sought) {
if (sought < *mid)
end1 = mid;
else
beg = mid + 1;
mid = beg + (end1 - beg) / 2;
}
/// ???????这一块不太懂
//用迭代器。 读入一组整数并把它们存入一个vector对象,将每对相邻整数的和输出出来。
cout << "请输入一些数字: " << endl;
cin.clear();
vector<int> some_numb1;
int numbs1 = 0;
while (cin >> numbs1)
{
some_numb1.push_back(numbs1);
}
cout << "你输入的数分别是 : " << endl;
for (auto it = some_numb1.begin(); it != some_numb1.end(); it++)
{
cout << *it << " ";
}
cout << endl;
cout << "相邻两个数的和分别是: " << endl;
for (auto it = some_numb1.begin(); it < some_numb1.end(); it = it + 2)
{
cout << *it + *(it + 1) << " ";
}
cout << endl;
/*????????????????*/
/*???????不知道为什么下面这行检查语句正确,运行时出错
if (some_numb1.size() % 2!=0)
cout <<some_numb1[some_numb1.size()-1] << endl;
*/
cin.clear();
cout << endl;
//改写你的程序,这次要求先输出第一个会最后一个元素的和,接着输出第2个和倒数第2个元素的和。so on
cout << "请再次输入一些数字:" << endl;
vector<int> some_numb2;
int numb3;
while (cin >> numb3) {
some_numb2.push_back(numb3);
}
cout << "你输入的数分别是: " << endl;
for (auto it = some_numb2.cbegin(); it != some_numb2.end(); ++it)
cout << *it << " ";
cout << endl;
auto start = some_numb2.begin(), end3 = some_numb2.end();
auto mid2 = start + (end3 - start) / 2;
auto some = start;
for (auto gogo = some_numb2.begin(), back = some_numb2.end() - 1; gogo < mid2; gogo++, back--)
{
cout << *gogo + *back << " ";
}
cout << endl;
if (some_numb2.size() % 2 != 0)
cout << *mid << endl; //好神奇,恰好是中间值
//我的疑惑是begin是几,end又是几呢
cin.clear();
cout << endl;
//以10分为一个分数段,要求统计各个分数段各有多少个乘积
cout << "请输入一些分数值(0-100): " << endl;
vector<int> scores;
int score;
while (cin >> score)
scores.push_back(score);
cout << "其中0-9分为J ,10-19分为I ,20-29为H ,30-39为G ,40-49为F "
<< ",50-59为E ,60-69为D ,70-79为C ,80-89为B ,90-99为A ,100为 Perfect 。" << endl;
vector<int> how_many(11, 0);
auto x = how_many.begin();
auto z = how_many.begin();
for (auto it = scores.begin(); it != scores.end(); it++)
{
int y;
y = *it / 10;
z = x + y;
*z+=1;
}
cout << "获得各等级的人数分别为: " << endl;
for (auto it = how_many.begin(); it != how_many.end(); it++)
cout << *it << " ";
cin.clear();
cout << endl;
//课本答案
//相邻两项和
vector<int> vInt1;
int iVal1;
cout << "请输入一组数字: " << endl;
while (cin >> iVal1)
vInt1.push_back(iVal1);
if (vInt1.cbegin() == vInt1.cend())
{
cout << "没有任何元素" << endl;
}
cout << "相邻两项的和依次是: " << endl;
for (auto it = vInt1.cbegin(); it != vInt.cend() - 1; it++)
{
cout << (*it + *(++it)) << " ";
if ((it - vInt1.cbegin() + 1) % 10 == 0) //书上说这是每行输出5个数字,我咋觉得是10个捏????
cout << endl;
}
if (vInt1.size() % 2 != 0)
cout << *(vInt.cend() - 1);
cin.clear();
cout << endl;
//求首尾元素和
vector<int> vInt2;
int iVal2;
cout << " 请输入一组数字:" << endl;
while (cin >> iVal2)
vInt2.push_back(iVal2);
if (vInt2.cbegin() == vInt2.cend())
{
cout << "没有任何元素" << endl;
}
cout << "首尾两项的和依次是:" << endl;
auto beg2 = vInt2.begin();
auto end2 = vInt2.end();
for (auto it = beg2; it != beg2 + (end2 - beg2) / 2; it++)
{
cout << (*it + *(beg2 + (end2 - it) - 1)) << " "; //???是否可以把beg2 去掉?
if ((it - beg2 + 1) % 5 == 0) //每行输出5个数字
cout << endl;
}
if (vInt2.size() % 2 != 0)
cout << *(beg2 + (end2 - beg2) / 2);
//成绩分段统计
vector<unsigned> vUS(11);
auto it11 = vUS.begin();
int iVal3;
cout << "请输入一组成绩(0-100):" << endl;
while (cin >> iVal3)
if (iVal3 < 101)
++*(it11+ iVal3/10); //****利用迭代器定位到对应元素,加1
cout << " 您总计输入了 " << vUS.size() << "个成绩" << endl;
cout << " 各分数段的人数分布是(成绩从低到高):" << endl;
for (auto it = vUS.begin(); it != vUS.end(); it++)
{
cout << *it << " ";
}
cout << endl;
/*********注意:c++中没有定义两个迭代器的加法运算,实际上把两个迭代器相加是没有意义的****/
/*****c++定义了迭代器的减法运算,所以表示中间值时mid=(beg+end)/2不合法******/
/******建议使用 mid=beg+(end-beg)/2 ********/
/*其含义是,先计算end-beg的值得到容器中的元素个数,然后控制迭代器右移二分之一容器长度*/
//从而定位到容器正中间的元素。
return 0;
}