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

如何修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:12:32