1.string类
string类型和数值的转换
※数值→字符串
to_string函数
//具体做法
int i=1234;
string g=to_string(i);//这样就转成字符串1234了
//下面就是字符串转为数字,类似下面还有stof,stoi,stod
string d = "1289347647";
int j = stoi(d);
cout << j;
string怎样输入输出呢?
如果用scanf就必须要转成字符数组之后再输入
好麻烦而且我一直错
1.字符个数※
/*
就是输入一行英文句子,统计出这一句的单词个数,字母个数,出现次数最多的字母个数
*/
#include<stdio.h>
#include<iostream>
#include<string>
#include<map>
using namespace std;
//int slen(string a)
//{
// int count = 0;
// while()
//}
int main()
{ //如何统计单词个数?前一个字符是空格并且这一个不是,就++
//先输入
//string a;
//cin >> a;//cin不是遇见空格就断吗
//是的,不仅是cin还有scanf也是的,他们都是一次只能输入一个字符
char arr[200] = { 0 };//定义字符数组
fgets(arr, 200, stdin);//通过这样的方式去获取字符串
int i = 0;
//或者可以是cin.getline()
//好,现在输入了
//接下来先统计字母的个数
int count1 = 0; int count2 = 0;//2是记录单词个数,1是记录字母个数
bool isspace=true;//用来记录现在字符前面的一个字符
map<char, int> alphamap;
while (true)
{
if (arr[i] == '\0' || arr[i] == '\n')break;
else if (arr[i] == ' ')
{
isspace = true;
}
else
{
count1++;
if (isspace)count2++;
//转换大小写
if (arr[i] >= 'A' && arr[i] <= 'Z')arr[i] += 32;
++alphamap[arr[i]];//这怎么这样?
isspace = false;
}
i++;
}
cout << count1 << endl;
cout << count2 << endl;
//迭代器便利map
map<char, int>::iterator it;//it->first指的是第一个;it->second指的是第二个,我们要比赛的是第二个
int max = 0;
for (it = alphamap.begin(); it != alphamap.end(); ++it)
{
if (it->second > max)max = it->second;
}
for (it = alphamap.begin(); it != alphamap.end(); it++)
{
if (it->second == max)cout << it->first<<' ';
}
cout << '\n';
cout << max;
//cout << "单词个数是" << count2 << endl;
//cout << "字母个数是" << count1 << endl;
}
2.浮点数相加
/*描述
求2个浮点数相加的和 题目中输入输出中出现浮点数都有如下的形式:
P1P2...Pi.Q1Q2...Qj
对于整数部分,P1P2...Pi是一个非负整数
对于小数部分,Qj不等于0
输入描述:
对于每组案例,每组测试数据占2行,分别是两个加数。
输出描述:
每组案例是n行,每组测试数据有一行输出是相应的和。
输出保证一定是一个小数部分不为0的浮点数*/
//经典高精度计算
//思路:和列竖式一样,先对齐:思路:提取小数,提取整数,把它们做成函数
#include<stdio.h>
#include<iostream>
#include<string>
using namespace std;
string getint(string a)
{
//char b=a[0];
//int i = 0; int j = 0;
//string c[200];
//while (b != '.')
//{
// c[j++] = a[i++];
// b = a[i];
//}
return a.substr(0, a.find('.'));//前面是起始位置,后面是长度
}
string getfraction(string a)//截取字符串的一部分;找到某个字符对应的下标
{
return a.substr(a.find('.')+1, a.size() - a.find('.'));//!!!!!!!!!!!!!!!!!!!!!!!!
}
//使用引用参数,直接返回信息,不用写返回类型这样
void fplus(string& res, int& carry, string fa, string fb)
{
//首先对齐
int size = max(fa.size(), fb.size());//字符串返回而这较大的size//!!!!!!!!!!!!!!!!!!
while (fa.size() < size)//!!!!!!!!!!!!!!!!!!!!!!!
{
fa.push_back('0');
}//!!!!!!!!!!!!!!!!!!!}
while (fb.size() < size)
{fb.push_back('0');}
//开始运算
//开辟空间
res.resize(size);
carry = 0;
for (int i = size - 1; i >= 0; i--)
{
//从右往左便利
//字符0和数字0怎样转换?字符0-‘0’
if (fa[i] + fb[i] +carry- '0' > '9') {//感觉前面是数字呀?为啥和字符比呢
res[i] = fa[i] + fb[i]+carry - '0' - 10;
carry = 1;
}
else
{
res[i] = fa[i] + fb[i]+carry - '0';
carry = 0;
}
}
}
void iplus(string& res, int& carry, int carry1, string ia, string ib)
{
/*int size = max(ia.size(), ib.size());
while (ia.size() < size)ia.append('0');
while (ib.size() < size)ib.push_back('0');
res.resize(size);
carry = 0;
for (int i = size - 1; i >= 0; i -- )
{
if (i == size - 1)
{
if (ia[i] + ib[i] + carry +carry1- '0' > '9')
{
res[i] = ia[i] + ib[i] + carry - '0' - 10;
carry = 1;
}
else
{
res[i] = ia[i] + ib[i] + carry - '0';
}
}
else{
if (ia[i] + ib[i] + carry - '0' > '9')
{
res[i] = ia[i] + ib[i] + carry - '0' - 10;
carry = 1;
}
else
{
res[i] = ia[i] + ib[i] + carry - '0';
carry = 0;
}
}
}*/
res.clear();
for (int i = ia.size() - 1, j = ib.size() - 1; i >= 0 || j >= 0 || carry == 1; i--, j--)
{
if (i == ia.size() - 1 && j == ib.size()-1)
{
if (ia[i] + ib[j] + carry +carry1- '0' > '9')
{
//res[i] = ia[i] + ib[i] + carry - '0' - 10;??这不是吗
res.insert(res.begin(), ia[i] + ib[j] + carry+carry1 - '0' - 10);
carry = 1;
}
else
{
//res[i] = ia[i] + ib[i] + carry - '0';
res.insert(res.begin(), ia[i] + ib[j] + carry +carry1- '0');
carry = 0;
}
}
else {
if (i >= 0 && j >= 0)
{
if (ia[i] + ib[j] + carry - '0' > '9')
{
//res[i] = ia[i] + ib[i] + carry - '0' - 10;??这不是吗
res.insert(res.begin(), ia[i] + ib[j] + carry - '0' - 10);
carry = 1;
}
else
{
//res[i] = ia[i] + ib[i] + carry - '0';
res.insert(res.begin(), ia[i] + ib[j] + carry - '0');
carry = 0;
}
}
else if (i >= 0 && j < 0)
{
if (ia[i] + carry > '9')
{
//res[i] = ia[i] + ib[i] + carry - '0' - 10;??这不是吗
res.insert(res.begin(), ia[i] + carry - 10);
carry = 1;
}
else
{
//res[i] = ia[i] + ib[i] + carry - '0';
res.insert(res.begin(), ia[i] + carry);
carry = 0;
}
}
else if (i < 0 && j >= 0)
{
if (ib[j] + carry > '9')
{
//res[i] = ia[i] + ib[i] + carry - '0' - 10;??这不是吗
res.insert(res.begin(), ib[j] + carry - 10);
carry = 1;
}
else
{
//res[i] = ia[i] + ib[i] + carry - '0';
res.insert(res.begin(), ib[j] + carry);
carry = 0;
}
}
else
{
res.insert(res.begin(), '1');
carry = 0;
}
}
}
}
int main()
{
//string a = "12345.6789";
//string b = "333.33333";
string a; cin >> a;
string b; cin >> b;
string ia = getint(a);
string ib = getint(b);
string fa = getfraction(a);
string fb = getfraction(b);
//先计算小数,在计算整数
string res; int carry;//分别是结果和进位
fplus(res, carry, fa, fb);
string res2;int carry2=0;
iplus(res2, carry2, carry, ia, ib);
cout << res2 << '.' << res << endl;
}
2.queue
操作受限的线性表
c++有现成的队列
#include<queue>
queue<int>myqueue;
队列支持:push,pop,front/back,emp
1.约瑟夫问题
思路:用一个for循环先搞一个队列,然后for循环把p-1个去掉,因为我们从第p个开始数,所以我们希望队头是第p个数;在用一个for循环循环n次,用来把这n个数都排出去;for循环内部,每次丢出去一个,先假装出去m-1个,然后队头留下真正出去的然后真正pop掉;
别忘了这个题是1~n,不是从0开始的
//n个小孩,从p开始报数,报m个,到m这个娃出去,直到全部出去
#include<iostream>
#include<queue>
#include<stdio.h>
using namespace std;
int main()
{
//如何实现循环?pop后push即可
int n, p, m;
cin >> n >> p >> m;
while (n !=0 ||p !=0|| m != 0)
{
int i;
queue<int> cque;
cque = queue<int>();
for (i = 1; i <= n; i++)//题目从0开始的
{
cque.push(i);
}//现在形成了一个队列
for (i = 1; i <= p - 1; i++)//先把p-1个poppush走
{
cque.pop();
cque.push(i);
}//现在把p个都pop+push掉了,现在从队头数
for (int j = 0; j < n;j++)//每一次都要把队列变为空,一次可以去掉一个,也可以是n次
{
//思路:队头才能出去→让m个成为对头
//围成一圈→循环队列
//报数:出队,并转移到另一个队列中,结束之后另一个队列的队尾就是这次要删除的数据
//如何实现循环?报数完之后加回来
for (i = 1; i <=m-1 ; i++)//总之是叫m个数
{
int a = cque.front();//如何将新的数push进去
cque.pop();
cque.push(a);
}
cout << cque.front(); if (j != n - 1)cout << ',';
cque.pop();
}
cout << '\n';
cin >> n >> p >> m;
}
}
3.stack
使用情况:有特权情况,深度优先遍历;表达式解析;递归
#include<stack>
stack<int> mystack;
操作:push(入栈);pop(出栈);top(栈顶元素);empty(判空)。
1.编排字符串
思路:就是栈,用两个栈来进行重复取元素操作
for循环输入m个字符;总体就是先输出,边输出边进入另一个栈,全部输出之后在从另一个栈导过来;
在第一次导入另一个站的过程中输出,两种情况,一种是小于4,那就全部输出,另一种是大于4,只输出4个,剩下的也要导进去,初始栈空了以后,在全部导进来,进行下一次
#include<stdio.h>
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int main()
{
//先输入//准备一个栈,站内元素是string类型,共m个元素
int m; cin >> m;
stack<string> mstack1;
stack<string> mstack2;
string a; int i, j; string b;
for (i = 1; i <= m; i++)
{
cin >> a;
mstack1.push(a);
//现在栈内有几个元素,就输出他们,但是只能假装输出,如何假装输出?
//准备两个栈,一个弹出来之后全部探进另一个,输出结束之后在全部弹回来
//还要和4比较大小
if (i <= 4)//随便输出
{
for(j=1;j<=i;j++)
{
b = mstack1.top();
cout << j << '=' << b<<' ';
mstack2.push(b);
mstack1.pop();
}//这样下来,1里面空了,2里面都是
}
else
{
for (j = 1; j <= 4; j++)
{
b = mstack1.top();
cout << j << '=' << b<<' ';
mstack2.push(b);
mstack1.pop();
}//现在mstack2里面还没要够,如何把剩下的也弄到2里,继续弹出1
for (j = 5; j <= i; j++)
{
b = mstack1.top();
mstack2.push(b);
mstack1.pop();
}
}
//所有的输出结束了,在这里弹回去
for (j = 1; j <= i; j++)
{
b = mstack2.top();
mstack1.push(b);
mstack2.pop();
}
cout << '\n';
}
}
2.括号匹配:
//输入一串括号,判断是否匹配,匹配就返回true
#include<stdio.h>
#include<iostream>
#include<stack>
#include<string>
using namespace std;
bool match(char a, char b)
{
if (a == '<' && b == '>' || a == '{' && b == '}' || a == '(' && b == ')' || a == '[' && b == ']')
return true;
else
return false;
}
int main()
{
//错因:①错误的几种情况没说全:不匹配;到右括号时候栈空;最终栈内还有元素
//②每次no之后都要return,避免no两次
//先输入
string a;
cin >> a;
int b = a.size(); int i;
//思路:碰到左括号就入栈,一直入栈,直到遇到右括号,
//碰到右括号与栈顶元素相比较,匹配就弹出来
stack<char> mstack; char c;
for (i = 0; i < b; i++)
{
if (a[i] == '<' || a[i] == '(' || a[i] == '{' || a[i] == '[')
{
mstack.push(a[i]);
}
if (a[i] == '>' || a[i] == ')' || a[i] == '}' || a[i] == ']')
{
if (empty(mstack)) {
cout << "no";
return 0;
}c = mstack.top();
if (match(c,a[i]))mstack.pop();
else
{
cout << "no";
return 0;
}
}
}
if (!(empty(mstack))) {
cout << "no";
return 0;
}
if (i == b)cout << "yes";
}