首页 新闻 搜索 专区 学院

C#化学公式解析

0
悬赏园豆:10 [已解决问题] 解决于 2021-06-18 17:16

给定一个用字符串展示的化学公式,计算每种元素的个数(求C#答案)。
规则如下:
元素命名采用驼峰命名,例如 Mg
() 代表内部的基团,代表阴离子团
[] 代表模内部链节通过化学键的连接,并聚合
例如:H2O => H2O1 Mg(OH)2 => H2Mg1O2

输入:

  • 化学公式的字符串表达式,例如:K4[ON(SO3)2]2 。
    输出:
  • 元素名称及个数:K4N2O14S4,并且按照元素名称升序排列。
    示例:

输入:K4[ON(SO3)2]2
输出:K4N2O14S4

天然白的主页 天然白 | 初学一级 | 园豆:4
提问于:2021-06-09 18:14
< >
分享
最佳答案
1

//左到右遇到元素 数量 左括号 入栈
//遇到右括号 获取(基团/聚合)数量 出栈增加括号内元素的数量 然后再入栈
public static string Parse(string expression)
{
var stack = new Stack<string>();
var index = 0;
while (index < expression.Length)
{
if (char.IsLetter(expression[index]))
{
var e = GetNextElement(expression, index);
stack.Push(e);
index += e.Length;
if (index < expression.Length && char.IsNumber(expression[index]))
{
var n = GetNextNumber(expression, index);
stack.Push(n);
index += n.Length;
}
else
{
stack.Push("1");
}
}
else if (expression[index] == '[' || expression[index] == '(')
{
stack.Push(expression[index].ToString());
index++;
}
else
{
var c = 1;
if (index + 1 < expression.Length && char.IsNumber(expression[index + 1]))
{
var n = GetNextNumber(expression, index + 1);
index += n.Length + 1;
c = int.Parse(n);
}
else
{
index++;
}
var st = new Stack<string>();
while (stack.Peek() != "[" && stack.Peek() != "(")
{
var e = stack.Pop();
if (int.TryParse(e, out var t))
{
st.Push((t * c).ToString());
}
else
{
st.Push(e);
}
}
stack.Pop();
while (st.Count > 0)
{
stack.Push(st.Pop());
}
}
}

        var dic = new Dictionary<string, int>();
        while (stack.Count > 0)
        {
            var c = int.Parse(stack.Pop());
            var e = stack.Pop();
            if (dic.TryGetValue(e, out var t))
            {
                dic[e] = t + c;
            }
            else
            {
                dic[e] = c;
            }
        }

        var es = dic.Keys.OrderBy(k => k);
        var re = new StringBuilder();
        foreach (var e in es)
        {
            re.Append($"{e}{dic[e]}");
        }
        return re.ToString();
    }

    public static string GetNextElement(string txt, int startIndex)
    {
        var len = 1;
        while (startIndex + len < txt.Length && char.IsLower(txt[startIndex + len]))
        {
            len++;
        }
        return txt.Substring(startIndex, len);
    }

    public static string GetNextNumber(string txt, int startIndex)
    {
        var len = 1;
        while (startIndex + len < txt.Length && char.IsNumber(txt[startIndex + len]))
        {
            len++;
        }
        return txt.Substring(startIndex, len);
    }

收获园豆:10
彭小立 | 小虾三级 |园豆:511 | 2021-06-10 10:31
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册