Класс Java, который может оценивать математические выражения:
package test;
public class Calculator {
public static Double calculate(String expression){
if (expression == null || expression.length() == 0) {
return null;
}
return calc(expression.replace(" ", ""));
}
public static Double calc(String expression) {
if (expression.startsWith("(") && expression.endsWith(")")) {
return calc(expression.substring(1, expression.length() - 1));
}
String[] containerArr = new String[]{expression};
double leftVal = getNextOperand(containerArr);
expression = containerArr[0];
if (expression.length() == 0) {
return leftVal;
}
char operator = expression.charAt(0);
expression = expression.substring(1);
while (operator == '*' || operator == '/') {
containerArr[0] = expression;
double rightVal = getNextOperand(containerArr);
expression = containerArr[0];
if (operator == '*') {
leftVal = leftVal * rightVal;
} else {
leftVal = leftVal / rightVal;
}
if (expression.length() > 0) {
operator = expression.charAt(0);
expression = expression.substring(1);
} else {
return leftVal;
}
}
if (operator == '+') {
return leftVal + calc(expression);
} else {
return leftVal - calc(expression);
}
}
private static double getNextOperand(String[] exp){
double res;
if (exp[0].startsWith("(")) {
int open = 1;
int i = 1;
while (open != 0) {
if (exp[0].charAt(i) == '(') {
open++;
} else if (exp[0].charAt(i) == ')') {
open--;
}
i++;
}
res = calc(exp[0].substring(1, i - 1));
exp[0] = exp[0].substring(i);
} else {
int i = 1;
if (exp[0].charAt(0) == '-') {
i++;
}
while (exp[0].length() > i && isNumber((int) exp[0].charAt(i))) {
i++;
}
res = Double.parseDouble(exp[0].substring(0, i));
exp[0] = exp[0].substring(i);
}
return res;
}
private static boolean isNumber(int c) {
int zero = (int) '0';
int nine = (int) '9';
return (c >= zero && c <= nine) || c =='.';
}
public static void main(String[] args) {
System.out.println(calculate("(((( -6 )))) * 9 * -1"));
System.out.println(calc("(-5.2+-5*-5*((5/4+2)))"));
}
}
HMODULE GetCurrentModule()
{ // NB: XP+ solution!
HMODULE hModule = NULL;
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)GetCurrentModule,
&hModule);
return hModule;
}
__ImageBase
сгенерированный символ компоновщика, который является заголовком DOS модуля (только MSVC). От этого можно бросить его адрес к HINSTANCE
или HMODULE
. Таким образом, это более удобно, чем прохождение через API.
, Таким образом, просто необходимо сделать это:
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
От https://devblogs.microsoft.com/oldnewthing/20041025-00/? p=37483
HMODULE является HINSTANCE, базовый адрес модуля. Так, я видел бы, как это работало. Но если все, что Вы хотите, является HMODULE исполняемого файла, почему бы не перечислить весь HMODULE's в процессе (EnumProcessModules). Одному из них свяжут Ваш .lib в.
ограничение, которое я вижу, - то, что Вы понятия не имеете, из которого DLL или EXE прибывает Ваш .lib. Вы могли бы хотеть сравнить HMODULEs (базовые адреса) с _ReturnAddress, который Вы получаете от своего .lib. Ваш .lib будет принадлежать самому высокому меньшему HMODLUE, чем Ваш _ReturnAddress
Я посмотрел бы GetModuleHandleEx()
использование флага GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
. Похоже, что можно изменить Ваш GetCurrentModule()
, чтобы назвать эту стандартную программу вместо VirtualQuery()
и передать адрес GetCurrentModule()
как lpModuleName
аргумент.
ETA:
const HMODULE GetCurrentModule()
{
DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;
HMODULE hm = 0;
::GetModuleHandleEx( flags, reinterpret_cast<LPCTSTR>( GetCurrentModule ), &hm );
return hm;
}
я не попробовал его, но я думаю, что это сделает то, что Вы хотите.