LGOJ P1022 计算器的改良
Posted kion
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LGOJ P1022 计算器的改良 相关的知识,希望对你有一定的参考价值。
依然是自带大常数的(STL)
于是乎就有了这个很长的代码
虽然很长但是很傻瓜
但其实就是很傻。
详情看注释
// P1022.cpp: 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
//#include <bitsstdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <list>
#include <cmath>
#include <cctype>
#include <cstdlib>
using namespace std;
list<char> L, L1, L2;
double unk = 0;//未知数的系数
c = 0;//常数项
char unkw;//未知数的字母,因为本题的字母不确定所以要单独记录
int yes = 1;//↑跟unkw有关的一个参数
void intial()//初始化
{
if (L.front() != '+' && L.front() != '-')
{
L.push_front('+');//为了整齐划一所以要加‘+’
}
int flag = 0;
//↓要十分注意,在我们的习惯中未知数的系数如果是1的话是可以省略的
//↓这是本题一个坑点
for (list<char>::iterator it = L.begin(); it != L.end(); it++)
if (*it >= 'a'&&*it <= 'z')
{
it--;
if (*it<'0' || *it>'9')
{
it++;
L.insert(it, '1');
it--;
}
it++;
}
//↓把等号左右两边的东西分开放更加直观而方便
for (list<char>::iterator it = L.begin(); it != L.end(); it++)
{
if (*it == '=')
{
flag = 1;
it++;
if (*it != '+' && *it != '-')
{
L.insert(it, '+');
//为所有的正数加个‘+’,判断更加方便
}
it--;
}
if (flag == 0)
{
L1.push_back(*it);
//左边的东西放L1
}
if (flag == 1)
{
L2.push_back(*it);
//右边的东西放L2
}
}
L1.push_back('+');
L2.push_back('+');
//判断的时候是取两个符号之间的数的,所以要在末尾补上符号
}
void debug()//这个只是用来调试的
{
cout << "left:";
for (list<char>::iterator it = L1.begin(); it != L1.end(); it++)
cout << *it;
cout << endl << "right:";
for (list<char>::iterator it = L2.begin(); it != L2.end(); it++)
cout << *it;
cout << endl;
}
int ltoi(list<char> tlist)//从list到int的函数
{
int ans = 0;
int i = 1;
int minus = 0;
if (tlist.front() == '-')minus = 1;//判断数字正负
tlist.reverse();//反转过来计算更方便
for (list<char>::iterator it = tlist.begin(); it != tlist.end(); it++)
{
if (*it >= '0'&&*it <= '9')
{
ans += ((*it) - '0')*i;
i *= 10;//累加
}
}
return minus ? (-ans) : (ans);
}
void deal(list<char> tlist)//分离未知数和常数
{
if (tlist.back() >= '0'&&tlist.back() <= '9')
{
c += ltoi(tlist);//这个项是常数,加到c里面
}
else
{
unk += ltoi(tlist);//这个项含有未知数,累加到未知数里面
if (yes)
{
unkw = tlist.back();
yes = 0;
//记得把未知数是啥记录下来
}
}
}
void judge()//处理等号左边的东西
{
int cnt = 0;//萌萌哒计数器
list<char> curr;//记录当前项
list<char>::iterator left, right;//区间左右地址记录
for (list<char>::iterator it = L1.begin(); it != L1.end(); it++)
{
if (*it == '+' || *it == '-')
{
cnt++;
if (cnt == 1)//左边有符号,记录
{
left = it;
}
if (cnt == 2)//右边有符号,记录
{
right = it--; //it++;
curr.assign(left, right);//于是我们得到了一项
cnt = 0;
deal(curr);//处理项
curr.clear();//清零
}
}
}
}
void judge2()//对于右边东西的判定,大体与judge()相同
{
int cnt = 0;
list<char> curr;
list<char>::iterator left, right;
for (list<char>::iterator it = L2.begin(); it != L2.end(); it++)
{
if (*it == '+' || *it == '-')
{
cnt++;
if (cnt == 1)
{
left = it;
}
if (cnt == 2)
{
right = it--; //it++;
curr.assign(left, right);
if (curr.front() == '+')//这里开始↓
{
curr.pop_front();//
curr.push_front('-');//
}
else
{
curr.pop_front();//
curr.push_front('+');//↑到这里,是移项
}
cnt = 0;
deal(curr);
curr.clear();
}
}
}
}
int main()
{
string str;
cin >> str;//字符串读入就懒得写个循环了
for (int i = 0; i < str.length(); i++)
{
L.push_back(str[i]);//然而还是要循环....
}
intial();
//debug();
judge();
judge2();
double x = 0;
x = -(c / unk);
if (x == 0)x = abs(x);//注意对-0.000特殊处理,坑点!
cout << c << ' ' << unk << endl;
cout << unkw << '=';
printf("%.3f", x);//保留三位
return 0;
}
以上是关于LGOJ P1022 计算器的改良 的主要内容,如果未能解决你的问题,请参考以下文章