You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C程序化学公式识别问题:无法处理元素/基团前置数字系数

问题描述

我正在开发一个识别和统计化学公式元素的C程序,它能正确处理(SO4)3这类基团,但解析元素/基团前的数字系数(如2Fe、5H2S)时异常。当前可正确处理输入:

Fe + H2SO4 = Fe2(SO4)3 + H2S + H2O

但无法处理带前置系数的输入:

2Fe + 2H2SO4 = 2Fe2(SO4)3 + 2H2S + 2H2O

我尝试修改identifyCompound函数支持前置系数,但结果仍不正确,现寻求修正方案。


问题分析

原代码的核心缺陷是未处理化合物/元素前的全局系数,且你修改的代码存在以下问题:

  • 变量名不统一(比如用了entrada而非原代码的input,comprimento而非length),导致逻辑无法正确执行;
  • currentCoefficient没有在处理完一个化合物后重置为1,会导致后续化合物错误继承前一个的系数;
  • 元素的数量计算错误——应该是currentCoefficient * quantity(原元素数量乘以全局系数),而非直接赋值currentCoefficient。

修正后的完整代码

以下是修复后的完整程序,包含主函数和修正后的identifyCompound函数:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

// Structure to represent a chemical element with atom count
typedef struct {
    char symbol[3]; // Element symbol (up to 2 characters for symbol + 1 for '\0')
    int quantity;   // Quantity of atoms of this element in the formula
} Element;

// Function to identify and count elements in a compound
void identifyCompound(char *input) {
    int length = strlen(input);
    int i = 0;
    Element elements[100]; // Array to store identified elements
    int numElements = 0;

    while (i < length) {
        // Skip non-formula characters like '+' and '='
        if (input[i] == '+' || input[i] == '=' || isspace(input[i])) {
            i++;
            continue;
        }

        int currentCoefficient = 1; // 全局前置系数,默认值为1

        // 读取化合物/元素前的数字系数
        if (isdigit(input[i])) {
            sscanf(&input[i], "%d", &currentCoefficient);
            // 跳过数字部分
            while (i < length && isdigit(input[i])) {
                i++;
            }
            // 若当前字符不是元素符号或括号,直接跳过
            if (i >= length || !isupper(input[i]) && input[i] != '(') {
                i++;
                continue;
            }
        }

        if (isupper(input[i])) {
            // Found an element symbol
            char symbol[3] = {input[i], '\0'};
            int j = i + 1;

            // Check for lowercase letters (indicating part of the symbol)
            while (j < length && islower(input[j])) {
                strncat(symbol, &input[j], 1);
                j++;
            }

            // Check for a number (atom quantity)
            int quantity = 1;
            if (j < length && isdigit(input[j])) {
                sscanf(&input[j], "%d", &quantity);
                while (j < length && isdigit(input[j])) {
                    j++;
                }
            }

            // 存储元素:全局系数 × 原子自身数量
            strcpy(elements[numElements].symbol, symbol);
            elements[numElements].quantity = currentCoefficient * quantity;
            numElements++;

            i = j; // 更新索引
        } else if (input[i] == '(') {
            // Beginning of a group enclosed in parentheses
            int j = i + 1;
            int start = j;

            // Find the end of the parentheses group (支持嵌套括号)
            int depth = 1;
            while (j < length && depth > 0) {
                if (input[j] == '(') {
                    depth++;
                } else if (input[j] == ')') {
                    depth--;
                }
                j++;
            }

            int end = j - 1;

            // Check for a number (coefficient) after the parentheses group
            int groupCoefficient = 1;
            if (j < length && isdigit(input[j])) {
                sscanf(&input[j], "%d", &groupCoefficient);
                while (j < length && isdigit(input[j])) {
                    j++;
                }
            }

            // Process the parentheses group
            int k = start;
            while (k < end) {
                if (isupper(input[k])) {
                    char symbol[3] = {input[k], '\0'};
                    int m = k + 1;

                    // Check for lowercase letters (indicating part of the symbol)
                    while (m < end && islower(input[m])) {
                        strncat(symbol, &input[m], 1);
                        m++;
                    }

                    // Check if the element has a coefficient
                    int elementCoefficient = 1;
                    if (m < end && isdigit(input[m])) {
                        sscanf(&input[m], "%d", &elementCoefficient);
                        while (m < end && isdigit(input[m])) {
                            m++;
                        }
                    }

                    // 存储元素:全局系数 × 基团系数 × 原子自身数量
                    strcpy(elements[numElements].symbol, symbol);
                    elements[numElements].quantity = currentCoefficient * groupCoefficient * elementCoefficient;
                    numElements++;

                    k = m; // Update index to the next element
                } else {
                    k++; // Move to the next character
                }
            }

            i = j; // 更新索引
        } else {
            // 跳过其他未知字符
            i++;
        }
    }

    // Build and display the identified elements
    printf("Identified elements:\n");
    int totalAtoms = 0;
    for (int k = 0; k < numElements; k++) {
        if (elements[k].quantity > 1) {
            printf("%s%d", elements[k].symbol, elements[k].quantity);
        } else {
            printf("%s", elements[k].symbol);
        }
        if (k < numElements - 1) {
            printf(" + ");
        }
        totalAtoms += elements[k].quantity;
    }
    printf("\nTotal atoms in the formula: %d\n", totalAtoms);
}

int main() {
    char input[100];

    printf("Enter an element or compound:\n");
    fgets(input, sizeof(input), stdin);

    // Remove newline character (if present) from the input
    input[strcspn(input, "\n")] = '\0';

    identifyCompound(input);

    return 0;
}

关键修改说明
  1. 统一变量名:修正了你修改代码中变量名不一致的问题,确保和原代码逻辑兼容;
  2. 处理全局前置系数:在每次处理元素/基团前读取前置数字系数,且该系数会在下一次循环中自动重置为1,避免影响后续化合物;
  3. 正确计算原子数量:
    • 单个元素:currentCoefficient * quantity(前置系数 × 原子自身数量);
    • 基团内元素:currentCoefficient * groupCoefficient * elementCoefficient(前置系数 × 基团系数 × 原子自身数量);
  4. 跳过无关字符:增加了对+、=和空格的处理,确保公式中的分隔符不会干扰解析;
  5. 修正索引逻辑:调整了索引更新的方式,避免出现越界或重复处理字符的问题。

内容的提问来源于stack exchange,提问作者Unsigned Index

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 23:45:00