I’m developing a C program to identify and count chemical elements in formulas. The code was working perfectly fine for handling groups like (SO4)3, but I’m encountering issues with interpreting numeric coefficients before elements or groups, such as 2Fe or 5H2S. I modified the identifyCompound function to try to handle numeric coefficients before compounds or elements, but the result is not correct.
The void function works for the input: Fe + H2SO4 = Fe2(SO4)3 + H2S + H2O
But it fails for the input: 2Fe + 2H2SO4 = 2Fe2(SO4)3 + 2H2S + 2H2O
// 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) {
if (isupper(input[i])) {
// Found an element symbol
char symbol[3] = {input[i], ''}; // Initialize symbol with uppercase letter
int j = i + 1;
// Check for lowercase letters (indicating part of the symbol)
while (j < length && islower(input[j])) {
strncat(symbol, &input[j], 1); // Concatenate lowercase letters to symbol
j++;
}
// Check for a number (atom quantity)
int quantity = 1;
if (j < length && isdigit(input[j])) {
sscanf(&input[j], "%d", &quantity); // Read number as integer
while (j < length && isdigit(input[j])) {
j++; // Move past the number
}
}
// Store the identified element
strcpy(elements[numElements].symbol, symbol);
elements[numElements].quantity = quantity;
numElements++;
i = j - 1; // Update the main index
} 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 coefficient = 1;
if (j < length && isdigit(input[j])) {
sscanf(&input[j], "%d", &coefficient); // Read number as integer
while (j < length && isdigit(input[j])) {
j++; // Move past the number
}
}
// Process the parentheses group
int k = start;
while (k < end) {
if (isupper(input[k])) {
char symbol[3] = {input[k], ''}; // Initialize symbol with uppercase letter
int m = k + 1;
// Check for lowercase letters (indicating part of the symbol)
while (m < end && islower(input[m])) {
strncat(symbol, &input[m], 1); // Concatenate lowercase letters to symbol
m++;
}
// Check if the element has a coefficient
int elementCoefficient = 1;
if (m < end && isdigit(input[m])) {
sscanf(&input[m], "%d", &elementCoefficient); // Read number as integer
while (m < end && isdigit(input[m])) {
m++; // Move past the number
}
}
// Store the element from the group with its quantity multiplied by the group's coefficient
strcpy(elements[numElements].symbol, symbol);
elements[numElements].quantity = coefficient * elementCoefficient;
numElements++;
k = m; // Update index to the next element
} else {
k++; // Move to the next character
}
}
i = j - 1; // Update the main index
}
i++; // Move to the next character
}
// 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: %dn", totalAtoms);
}
So I made some changes to the code to identify whether the compound or element has a numeric coefficient before it.
int currentCoefficient = 1; // Initialize the current coefficient as 1
// Check if the current character is a digit (isdigit(entrada[i])). If it is, this indicates a numeric coefficient is present before the next element or compound.
if (isdigit(entrada[i])) {
// Found a numeric coefficient
sscanf(&entrada[i], "%d", ¤tCoefficient); // Read the number as an integer
// Move past the number to continue reading the formula
while (i < comprimento && isdigit(entrada[i])) {
i++;
}
i--; // Move back an index to continue reading correctly
}
// When an element is identified (an element symbol is found), the code now stores this element along with the currentCoefficient applied.
// Store the identified element with the current coefficient
strcpy(elementos[numElementos].simbolo, symbol);
elementos[numElementos].quantidade = currentCoefficient;
numElementos++;
// When a group in parentheses is identified, the code also checks if there is a numeric coefficient immediately after the group. This coefficient is used to multiply the quantity of each element within that group.
// Process the group in parentheses with its coefficient
int groupCoefficient = 1;
if (j < comprimento && isdigit(entrada[j])) {
sscanf(&entrada[j], "%d", &groupCoefficient); // Read the number as an integer
while (j < comprimento && isdigit(entrada[j])) {
j++; // Move past the number
}
}
// Store the element from the group with its quantity multiplied by the group's coefficient
elementos[numElementos].quantidade = currentCoefficient * groupCoefficient;
For example, 2Fe is an element that has a numeric coefficient of 2 before Fe, but 2H2S is not an element; it’s a compound with a numeric coefficient of 2 before it.
Below is the main code, remember to include the void function
#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 '')
int quantity; // Quantity of atoms of this element in the formula
} Element;
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")] = '';
identifyCompound(input);
return 0;
}
Unsigned Index is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.