Как использовать строку или символ-вектор (содержащий любой химический состав и соответственно формулу) и рассчитать его молярную массу?
Я пытаюсь написать простое консольное приложение на C++, которое может прочитать любую химическую формулу, а затем вычислить ее молярную массу, например:
- Na2CO3 или что-то вроде:
- La0,6Sr0,4CoO3 или в скобках:
- Fe (NO3) 3
Проблема в том, что я не знаю подробно, как я могу справиться с потоком ввода. Я думаю, что чтение входных данных и их сохранение в символьном векторе может быть в этом случае лучшей идеей, чем использование обычной строки.
Моей самой первой идеей было проверить все элементы (хранящиеся в символе вектора), шаг за шагом: когда после заглавной буквы нет строчных букв, я нашел, например, такой элемент, как Carbon 'C' вместо "Co" (Cobalt). или "медь" (медь). В основном я пытался использовать методы isupper (...), islower (...) или isalpha (...).
// first idea, but it seems to be definitely the wrong way
// read input characters from char vector
// check if element contains only one or two letters
// ... and convert them to a string, store them into a new vector
// ... finally, compute the molar mass elsewhere
// but how to deal with the numbers... ?
for (unsigned int i = 0; i < char_vec.size()-1; i++)
{
if (islower(char_vec[i]))
{
char arr[] = { char_vec[i - 1], char_vec[i] };
string temp_arr(arr, sizeof(arr));
element.push_back(temp_arr);
}
else if (isupper(char_vec[i]) && !islower(char_vec[i+1]))
{
char arrSec[] = { char_vec[i] };
string temp_arrSec(arrSec, sizeof(arrSec));
element.push_back(temp_arrSec);
}
else if (!isalpha(char_vec[i]) || char_vec[i] == '.')
{
char arrNum[] = { char_vec[i] };
string temp_arrNum(arrNum, sizeof(arrNum));
stoechiometr_num.push_back(temp_arrNum);
}
}
Мне нужен простой алгоритм, который может работать с буквами и цифрами. Также может быть возможность работы с указателем, но в настоящее время я не очень знаком с этой техникой. В любом случае, я открыт для понимания, если кто-то захочет объяснить мне, как я могу использовать их здесь.
Я был бы очень признателен за любую поддержку и, конечно, некоторые фрагменты кода, касающиеся этой проблемы, поскольку я много дней думаю об этом без прогресса... Пожалуйста, имейте в виду, что я скорее новичок, чем промежуточный.
1 ответ
Эта проблема, конечно, не для начинающих, но я постараюсь дать вам некоторое представление о том, как вы можете это сделать.
Предположение: я не рассматриваю случай изотопов, в котором атомная масса может быть разной с одним и тем же атомным номером.
Смоделируйте это с реальным миром.
Как вы решите это в реальной жизни?
Скажите, если я дам вам химическую формулу:
Fe(NO3)3
Что вы будете делать:Преобразуйте это во что-то вроде этого:
Total Mass => [1 of Fe] + [3 of NO3] => [1 of Fe] + [ 3 of [1 of N + 3 of O ] ] => 1 * Fe + 3 * (1 * N + 3 * O)
Затем вы будете искать отдельные массы элементов, а затем заменить их.
Total Mass => 1 * 56 + 3 * (1 * 14 + 3 * 16) => 242
Теперь перейдем к программированию.
Поверьте мне, вы должны сделать то же самое в программировании.
Преобразуйте свою химическую формулу в форму, описанную выше, т.е.
Fe(NO3)3
вFe*1+(N*1+O*3)*3
, Я думаю, что это самая сложная часть в этой проблеме. Но это можно сделать и разбив на шаги.- Проверьте, все ли элементы имеют номер после него. Если нет, то добавьте "1" после него. Например, в этом случае
O
имеет номер после него, который3
, НоFe
а такжеN
не имеет его
После этого шага ваша формула должна измениться на
Fe1(N1O3)3
,Теперь конвертируем каждое число, скажем
num
вышеуказанной формулы:*num+
Если после текущего номера есть какой-то элемент.*num
Если вы встретили ')' или конец формулы после него.
После этого ваша формула должна измениться на
Fe*1+(N*1+O*3)*3
,
- Проверьте, все ли элементы имеют номер после него. Если нет, то добавьте "1" после него. Например, в этом случае
Теперь ваша задача - решить вышеприведенную формулу. Для этого есть очень простой алгоритм. Пожалуйста, обратитесь к: https://www.geeksforgeeks.org/expression-evaluation/. В вашем случае ваши операнды могут быть числом (скажем,
2
) или элемент (скажем,Fe
). Ваши операторы могут быть*
а также+
, Скобки также могут присутствовать.
Для нахождения отдельных масс, вы можете сохранить std::map<std::string, int>
содержащий element name
как key
И его mass
как value
,
Надеюсь это немного поможет.