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", ¤tCoefficient); // 跳过数字部分 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,避免影响后续化合物;
- 正确计算原子数量:
- 单个元素:
currentCoefficient * quantity(前置系数 × 原子自身数量); - 基团内元素:
currentCoefficient * groupCoefficient * elementCoefficient(前置系数 × 基团系数 × 原子自身数量);
- 单个元素:
- 跳过无关字符:增加了对
+、=和空格的处理,确保公式中的分隔符不会干扰解析; - 修正索引逻辑:调整了索引更新的方式,避免出现越界或重复处理字符的问题。
内容的提问来源于stack exchange,提问作者Unsigned Index
相关产品推荐
相关产品推荐

