1.vector的相关应用
首先,vector是c++中的向量类型,可以容纳不同数据类型的数据,被称为容器。也因此,vector在平常做题的使用中,可以作为动态数组来进行数据的处理。
注意使用vector和调用操作vector的函数时需要头文件#include <vector>
例如以下问题:
描述
处于某种原因,一点都不懂编程的某某系小迅老师竟然成功跳槽到计算机系来教大一新生如何编程。
看着这位在台上胡言乱语,水平比同学小华弱太多的老师,小鲁简直不忍直视。
那学期的期中考试,小讯老师出的题目竟然是:“请写一个排序算法给数组排序,结果按照升序输出。”
经过NQ49斩的小鲁分分钟就完成了代码。小讯老师一看,哎呀不得了,得提高期中考试难度。
他立刻把题目改为:“给定任意T组整数,每组整数都要按升序输出。”
小鲁笑了笑,原来这类题已经难不倒他了,原来他早就超过了大一上小讯老师的水平了!
小鲁水平进阶了,你做得到吗?
输入
第一行是整数T,表示一共有T组数据。
接下来T行,每行有N+1个数,第一个整数表示该行有N个待排序的数字。
整数N(1<=N<=1000000),T(1<=T<=100)。
输出
对于每组整数,按照升序输出排序结果,每个结果占一行。
输入样例 1
3 4 412 120 5560 3760 5 576 66 35 99 88 4 127 100 510 380
输出样例 1
120 412 3760 5560 35 66 88 99 576 100 127 380 510
对于本题,如果尝试去定义二维数组对输入数据进行排序,最后一起输出的话,会发现它的输入格式比较受限。题目要求先要输入一个整数T,代表共有T组数据。然后下面T行,第一个数输入该组共有多少个数据,然后需要对每一组数据进行排序操作。因此,如果在循环内定义二维数组的话,在循环外无法访问到,也就无法输出最终结果,所以这里可以考虑使用vector进行动态数组的定义,对于每个动态数组进行分别排序输出。
代码如下:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n, a, i;
cin >> n;
vector<int> nums; //定义一个vector动态数组
for (i = 0; i < n; i++) {
cin >> a;
nums.push_back(a); //将输入元素存入vector数组nums中
}
sort(nums.begin(), nums.end()); //end()返回最后一个元素的后一个地址
for (i = 0; i < n; i++) {
if (i == 0)
cout << nums[i];
else
cout << " " << nums[i];
}
cout << endl;
}
return 0;
}
再比如另外一题:
描述
小鲁在某一场比赛中做出5道题后不幸打铁,于是一气之下与数字5杠上了。
当小鲁拿到一行数字,他会首先把这行数字中所有的5换成空格,以达到眼不见心不烦的效果。
进行完这项操作后,一串数字被拆成若干个新的数字(忽略整数开头的0;每个位都是0的数输出0)。
最后对分割后得到的数字从小到大的排序。
输入
输入包含多组测试用例,每组输入数据只有一行数字(数字之间没有空格),这行数字的长度不大于1000。
输入数据保证:分割得到的非负整数不会大于100000000;输入数据不可能全由‘5’组成。
输出
对于每个测试用例,输出分割得到的整数排序的结果,相邻的两个整数之间用一个空格分开,每组输出占一行。
输入样例 1
0551223532050775
输出样例 1
0 77 320 1223
对于本题,由于每组输入并没有指定长度,因此也可以使用vector作为动态数组来存放输入,再进行相应的处理。但此题并不只有vector动态数组的应用,还有其他C++STL的影子,先看以下代码:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
int main() {
string str, number;
vector<int> ans;
getline(cin, str); //读入一行字符串
if (str.back() != '5')
str += '5'; //若字符的最后一个不是'5',在字符串末尾增加5代表空格结束
for (auto c : str) { //此段是遍历字符串,auto会根据str的类型来定义c的类型
if (c != '5')
number += c; //如果读入字符串过程中未遇到空格,则将其复制到number中
else if (!number.empty()) { //若遇到了'5',则判断number是否为空,再将该数字存入vector中
while (number.size() > 1 && number[0] == '0')//主要是判断number数组中是否还存在前导零
number = number.substr(1); //去掉前导零
ans.push_back(stoi(number)); //将该数字存入vector中
number.clear(); //清楚number数组
}
}
sort (ans.begin(), ans.end());
for (auto s : ans) //遍历ans数组
cout << s << " ";
cout << endl;
return 0;
}
2.for (auto c : str)的用法
观察上一题的题解代码,发现它并没有使用传统的for循环去对每组输入进行遍历操作,而是使用了for (auto c : str)来遍历字符串。
在for(auto a : b)中,b是一个容器,效果是利用a遍历b容器中的每一个值,但是a无法影响到b容器中的元素。
因此,在程序第一个出现for(auto c : str)的位置,意思是在for循环中,将str字符串中每一个字符依次赋值给c,再由c在for循环中对其进行处理,但是不会影响到str原来的值。对于本题,c只是用来判断字符串中那个位置出现了字符5,即确定空格的位置。在读到空格之前,把不是字符5的字符赋值给number字符串,后面再进行处理。
3.STL中string库函数的使用
在上一题的程序中,用到了不少C++STL中string里的库函数,代码中number.empty()用来判断number字符数组是否为空,number.size()返回number字符数组的长度,number.substr(1)用来截取number字符数组从第二个字符开始往后的字符,stoi用来转换字符类型到整形等等。
4.代码io流的进制转换
先看以下题目:
描述
与喜欢争强好胜的小鲁不同,小华从来就不屑与人竞争。
他所求的不是赢,他所求的乃是突破。在数字领域,小华的创意总是层出不穷。
在小华构造的数字世界里,十进制只是P进制的一个具体实例,同样的十六进制也是P进制的具体实例。
在精通十进制加减法之后,小鲁开始得意洋洋不思进取,为了帮助小鲁进一步成长,小华给小鲁出了一道题:
把十进制加法改为十六进制加法,要求有两点:
1.用大写字母表示十六进制
2.如果遇到负数,即便是十六进制也要加上负号"-".
面对手足无措的小鲁,你能再帮帮他吗?
输入
输入数据有若干行,每行有两个十六进制数。
数据范围:
-10^9 < 输入数据 < 10^9
输出
输出数据有若干行,每行对应输入数据的两数之和。
输入样例 1
+A -A +1A -B 1ABCD -2020 -1FEDF777 -FFAEC8
输出样例 1
0 F 18BAD -20EDA63F
如果用传统的模拟做法去做,需要自己手搓十六进制加法。我们在自己写十进制高精度加法时就感觉到这种方法会有些麻烦,因此这里提供一个C++新的处理进制的方法,代码如下:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
long long a, b;
cin >> setbase(16);
cout << setiosflags(ios::uppercase)<<setbase(16);
while (cin >> a >> b) {
long long ans = a + b;
if (ans < 0)
cout << "-" << -(ans) << endl;
else
cout << ans << endl;
}
return 0;
}
此处使用了C++中iomanip命名空间的函数,可以直接改变当前程序io流的进制。
代码第二行
cin >> setbase(16);
是iomanip库中的setbase函数,可以改变cin输入数据的进制,因此在此代码之后再输入的数据就是十六进制的数据。而下一行代码中的setiosflags是C++命名空间iomanip的操作符,该操作符后面的参数如下:
ios::skipws 在输入中跳过空白。
ios::left 左对齐值,用填充字符填充右边。
ios::right 右对齐值;用填充字符填充左边(缺省对齐方式)。
ios::internal 在指定任何引导标记或基之后增加填充字符。
ios::dec 以基10(十进制)格式化数值(缺省进制)。
ios::oct 以基8(八进制)格式化数值。
ios::hex 以基16(十六进制)格式化数值。
ios::showbase 以C++编译器能读的格式显示数值常量。
ios::showpoint 对浮点数值显示小数点和尾部的0。
ios::uppercase 对于十六进制数值显示大写字母A到F,对于科学格式显示大写字母E。
ios::showpos 对于正数显示正号(+)。
ios::scientific 以科学格式显示浮点数值。
ios::fixed 以定点格式显示浮点数值。
ios::unitbuf 导致在每次插入之后ostream::osfx刷新该流。缺省地,cerr是缓冲的单元。
ios::stdio 导致在每次插入之后ostream::osfx刷新该流的stdout和stderr
代码中的ios::uppercase保证了十六进制数值显示大写。