LGOJ P1022 【计算器的改良 】

依然是自带大常数的\(STL\)

于是乎就有了这个很长的代码

虽然很长但是很傻瓜

但其实就是很傻。

详情看注释

// P1022.cpp: 定义控制台应用程序的入口点。
//

//#include "stdafx.h"
//#include <bits\stdc++.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;
}


posted @ 2019-11-07 22:40  miyasaka  阅读(238)  评论(0)    收藏  举报