c# - 从 C# 中的字符串解析化学式?

标签 c# parsing chemistry

<分区>

我正在尝试解析化学式(格式为,例如:Al2O3O3CC11H22O12 ) 在 C# 中来自一个字符串。它工作正常,除非特定元素只有一个原子(例如 H2O 中的氧原子)。我该如何解决这个问题,此外,是否有比我现在更好的解析化学式字符串的方法?

ChemicalElement 是表示化学元素的类。它具有属性 AtomicNumber (int)、Name (string)、Symbol (string)。 ChemicalFormulaComponent 是一个表示化学元素和原子数(例如,公式的一部分)的类。它具有元素 (ChemicalElement)、AtomCount (int) 属性。

其余的应该足够清楚,可以理解(我希望),但如果我能澄清任何事情,请在您回答之前通过评论告诉我。

这是我当前的代码:

    /// <summary>
    /// Parses a chemical formula from a string.
    /// </summary>
    /// <param name="chemicalFormula">The string to parse.</param>
    /// <exception cref="FormatException">The chemical formula was in an invalid format.</exception>
    public static Collection<ChemicalFormulaComponent> FormulaFromString(string chemicalFormula)
    {
        Collection<ChemicalFormulaComponent> formula = new Collection<ChemicalFormulaComponent>();

        string nameBuffer = string.Empty;
        int countBuffer = 0;

        for (int i = 0; i < chemicalFormula.Length; i++)
        {
            char c = chemicalFormula[i];

            if (!char.IsLetterOrDigit(c) || !char.IsUpper(chemicalFormula, 0))
            {
                throw new FormatException("Input string was in an incorrect format.");
            }
            else if (char.IsUpper(c))
            {
                // Add the chemical element and its atom count
                if (countBuffer > 0)
                {
                    formula.Add(new ChemicalFormulaComponent(ChemicalElement.ElementFromSymbol(nameBuffer), countBuffer));

                    // Reset
                    nameBuffer = string.Empty;
                    countBuffer = 0;
                }

                nameBuffer += c;
            }
            else if (char.IsLower(c))
            {
                nameBuffer += c;
            }
            else if (char.IsDigit(c))
            {
                if (countBuffer == 0)
                {
                    countBuffer = c - '0';
                }
                else
                {
                    countBuffer = (countBuffer * 10) + (c - '0');
                }
            }
        }

        return formula;
    }

最佳答案

我使用正则表达式重写了您的解析器。正则表达式非常适合您正在做的事情。希望这会有所帮助。

public static void Main(string[] args)
{
    var testCases = new List<string>
    {
        "C11H22O12",
        "Al2O3",
        "O3",
        "C",
        "H2O"
    };

    foreach (string testCase in testCases)
    {
        Console.WriteLine("Testing {0}", testCase);

        var formula = FormulaFromString(testCase);

        foreach (var element in formula)
        {
            Console.WriteLine("{0} : {1}", element.Element, element.Count);
        }
        Console.WriteLine();
    }

    /* Produced the following output

    Testing C11H22O12
    C : 11
    H : 22
    O : 12

    Testing Al2O3
    Al : 2
    O : 3

    Testing O3
    O : 3

    Testing C
    C : 1

    Testing H2O
    H : 2
    O : 1
        */
}

private static Collection<ChemicalFormulaComponent> FormulaFromString(string chemicalFormula)
{
    Collection<ChemicalFormulaComponent> formula = new Collection<ChemicalFormulaComponent>();
    string elementRegex = "([A-Z][a-z]*)([0-9]*)";
    string validateRegex = "^(" + elementRegex + ")+$";

    if (!Regex.IsMatch(chemicalFormula, validateRegex))
        throw new FormatException("Input string was in an incorrect format.");

    foreach (Match match in Regex.Matches(chemicalFormula, elementRegex))
    {
        string name = match.Groups[1].Value;

        int count =
            match.Groups[2].Value != "" ?
            int.Parse(match.Groups[2].Value) :
            1;

        formula.Add(new ChemicalFormulaComponent(ChemicalElement.ElementFromSymbol(name), count));
    }

    return formula;
}

关于c# - 从 C# 中的字符串解析化学式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4116786/

相关文章:

javascript - 如何在 Asp.net MVC 中向外部 js 文件添加本地化?

python - 通过python计算文本文件中的单词

ios - 无法将类型 '[String : Any]' 的值转换为预期的参数类型 'String'

chemistry - 使用 RDKit 寻找手性

python - 生成小配体的构象异构体但保留正确的芳香性

c# - 使用 OpenFileDialog 作为目录,而不是 FolderBrowserDialog

c# - 为什么人们使用 ProjectData

c# - 使用 ADO.NET 从 SQL Server 获取数据

php - 在 PHP 中获取部分 URL

python - 使用 Python 从蛋白质数据库下载特定的 .pdb 文件