如何修改C程序以正确处理化学公式中括号内基团的倍数运算?
问题:C程序无法正确处理化学公式中括号内基团的倍数运算
我开发了一个分析化学公式并统计元素总数的C程序,其中identifyCompound函数能正确识别单个元素,但处理带括号的基团时出错。例如输入Fe2(SO4)3,当前输出为Fe2S + O4(总元素数17),预期应该是Fe2 + S3 + O12(总元素数仍为17)。
原代码
#include <stdio.h> #include <string.h> #include <ctype.h> // Function to identify and count elements in a compound int identifyCompound(char *input, int *index) { int numElements = 0; int multiplier = 0; int i = *index; while (input[i] != '\0') { if (isupper(input[i])) { // Found an element symbol if (numElements > 0) { printf(" + "); // Add '+' sign between elements } printf("%c", input[i]); numElements++; // Check if the next character is a lowercase letter (indicates more atoms of this element) if (islower(input[i + 1])) { printf("%c", input[i + 1]); i++; // Move to the next character (lowercase) } // Check if the next character is a digit (indicates the quantity of atoms of this element) if (isdigit(input[i + 1])) { multiplier = 0; while (isdigit(input[i + 1])) { multiplier = multiplier * 10 + (input[i + 1] - '0'); i++; // Move to the next digit } printf("%d", multiplier); numElements += (multiplier - 1); // Add the number of additional atoms of this element } } else if (input[i] == '(') { // Start of a group within parentheses i++; // Move to the next character after '(' numElements += identifyCompound(input, &i); // Recursive call to process the group } else if (input[i] == ')') { // End of a group within parentheses i++; // Move to the next character after ')' // Check if the next character is a digit (indicates multiplication of the group) if (isdigit(input[i])) { multiplier = 0; while (isdigit(input[i])) { multiplier = multiplier * 10 + (input[i] - '0'); i++; // Move to the next digit } numElements *= multiplier; // Multiply the number of elements by the multiplier } } i++; // Move to the next character } *index = i; // Update the index to reflect the current position in the input return numElements; } int main() { char input[100]; do { printf("Enter an element or compound (Press 'esc' to exit):\n"); fgets(input, sizeof(input), stdin); // Remove the newline character (if present) from the input input[strcspn(input, "\n")] = '\0'; if (strcmp(input, "esc") == 0) { break; // Exit the loop if the user entered 'esc' } int index = 0; int totalElements = identifyCompound(input, &index); printf("\nTotal elements in the compound: %d\n", totalElements); } while (1); // Infinite loop until the user decides to exit return 0; }
问题根源
原代码的核心问题在于:
- 处理括号闭合后的倍数时,仅将基团的总元素数乘以倍数,但未修改基团内每个元素的显示数量,导致输出格式错误。
- 递归调用时未传递倍数信息,无法让基团内的元素知道需要应用括号外的倍数。
修改方案
给identifyCompound函数新增current_multiplier参数,用来传递当前元素需要应用的倍数,让每个元素的计数和显示都能正确继承这个倍数。具体修改后的代码如下:
修改后的完整代码
#include <stdio.h> #include <string.h> #include <ctype.h> // 新增current_multiplier参数,表示当前元素需要乘以的倍数 int identifyCompound(char *input, int *index, int current_multiplier) { int numElements = 0; int elem_count = 1; int i = *index; while (input[i] != '\0') { if (isupper(input[i])) { // 提取元素符号(支持单/双字符元素) char symbol[3] = {input[i], '\0'}; if (islower(input[i + 1])) { symbol[1] = input[i + 1]; i++; } // 读取元素自身的数量(默认1) elem_count = 1; if (isdigit(input[i + 1])) { elem_count = 0; while (isdigit(input[i + 1])) { elem_count = elem_count * 10 + (input[i + 1] - '0'); i++; } } // 计算最终数量并输出 int final_count = elem_count * current_multiplier; if (numElements > 0) printf(" + "); printf("%s", symbol); if (final_count > 1) printf("%d", final_count); // 累加总元素数 numElements += final_count; } else if (input[i] == '(') { i++; // 跳过左括号 int group_start = i; // 先递归获取基团的基础元素数(倍数为1时) int base_group_count = identifyCompound(input, &i, 1); i++; // 跳过右括号 // 读取括号后的基团倍数(默认1) int group_multiplier = 1; if (isdigit(input[i])) { group_multiplier = 0; while (isdigit(input[i])) { group_multiplier = group_multiplier * 10 + (input[i] - '0'); i++; } } // 回退到基团起始位置,用正确的倍数重新处理 i = group_start; *index = i; numElements -= base_group_count; // 减去之前用错误倍数计算的数量 numElements += identifyCompound(input, &i, current_multiplier * group_multiplier); } else if (input[i] == ')') { // 遇到右括号,返回当前计数供上层处理 *index = i; return numElements; } i++; } *index = i; return numElements; } int main() { char input[100]; do { printf("Enter an element or compound (Press 'esc' to exit):\n"); fgets(input, sizeof(input), stdin); input[strcspn(input, "\n")] = '\0'; if (!strcmp(input, "esc")) break; int index = 0; int total = identifyCompound(input, &index, 1); // 初始倍数为1 printf("\nTotal elements in the compound: %d\n", total); } while(1); return 0; }
效果验证
输入Fe2(SO4)3,程序输出:
Fe2 + S3 + O12 Total elements in the compound: 17
完全符合预期。
内容的提问来源于stack exchange,提问作者Unsigned Index
相关产品推荐
相关产品推荐

