📄 calculator.c
字号:
// isolate the name of the user-defined variable p1[0] = 0; nam = (char*) malloc(strlen(ptr)+1); strcpy(nam, ptr); i = strlen(nam); // remove blanks at end of variable name while ((i > 0) && (nam[i] <= ' ')) {nam[i] = 0; i--;} p1[0] = '='; ptr = p1; ptr++; // ignore Spaces i = 0; while ((ptr[i] <= ' ') && ((unsigned int)i < strlen(formel)) ) i++; if ((unsigned int)i < strlen(formel)) ptr += i; // does Variable with this name already exists? for (i = 0; i < cal->Vars; i++) if (strcmp(cal->Var[i].Name, nam) == 0) iVar = i; // remember, that we should save the results in a user-defined // variable setvar = 1; if (iVar >= 0) // Variable already exists, so deallocate the // new name free(nam); else if (cal->Vars < CALCULATOR_VARS-1) { // create new user-defined variable cal->Var[cal->Vars].Name = nam; iVar = cal->Vars; cal->Vars++; } else { // already 99 Variables uses; need to free the longest unused ilast = cal->RefCnt; ip = -1; for (i = 0; i < cal->Vars; i++) { if (cal->Var[i].Ref < ilast) { ip = i; ilast = cal->Var[i].Ref; } } if (ip >= 0) { iVar = ip; free(cal->Var[ip].Name); cal->Var[ip].Name = nam; } else { setvar = 0; free(nam); } } } } if (*iStack) { // we have already found the first operand in a previous call, so now // we first need a operator if (strlen(ptr)) { switch (ptr[0]) { case '+': OpStack[*iStack] = '+'; OpLvlStack[*iStack] = 2; ptr++; break; case '-': OpStack[*iStack] = '-'; OpLvlStack[*iStack] = 2; ptr++; break; case '*': OpStack[*iStack] = '*'; OpLvlStack[*iStack] = 3; ptr++; break; case '/': OpStack[*iStack] = '/'; OpLvlStack[*iStack] = 3; ptr++; break; case '^': OpStack[*iStack] = '^'; OpLvlStack[*iStack] = 4; ptr++; break; default: // no operator was found, so assume multyply OpStack[*iStack] = '*'; OpLvlStack[*iStack] = 3; } } // check, whether we can reduce the Stack a bit. // If the current operator has a equal or lower level than the previous // we can execute the last operation and replace the first operand with // the result. This can be done until the level of the current operator // is higher than the previous. while ((*iStack > 1) && (OpLvlStack[*iStack] <= OpLvlStack[*iStack-1])) { switch (OpStack[*iStack-1]) { case '+': NumStack[*iStack-2] += NumStack[*iStack-1]; break; case '-': NumStack[*iStack-2] -= NumStack[*iStack-1]; break; case '*': NumStack[*iStack-2] *= NumStack[*iStack-1]; break; case '/': NumStack[*iStack-2] /= NumStack[*iStack-1]; if (!finite(NumStack[*iStack-2])) CalculatorError = ERR_DIVZERO; break; case '^': NumStack[*iStack-2] = pow(NumStack[*iStack-2],NumStack[*iStack-1]); break; } OpStack[*iStack-1] = OpStack[*iStack]; OpLvlStack[*iStack-1] = OpLvlStack[*iStack]; (*iStack)--; } } // now look for an Operand // ignore Spaces i = 0; while ((ptr[i] <= ' ') && ((unsigned int)i < strlen(ptr)) ) i++; if ((unsigned int)i < strlen(ptr)) ptr += i; // check the sign. Here is is not an operator ksign = 1; if (ptr[0] == '-'){ ksign = -1; ptr++; } if (ptr[0] == '+'){ ksign = 1; ptr++; } // check, whether the formula beginns here with a bracket if (ptr[0] == '(') { braces = 1; ptr++; // opening bracket was found, so look for the corresponding // closing bracket for (i = 0; (unsigned int)i <= strlen(ptr); i++) { if (ptr[i] == '(') braces++; if (ptr[i] == ')') braces--; if ((braces == 0) || ((unsigned int)i == strlen(ptr))) { // if no closing bracket was found, interprete the line // end as a closing bracket last = ptr[i]; if ((unsigned int)i != strlen(ptr)) ptr[i] = 0; NumStack[*iStack] = Calculator(ptr, cal) * (double) ksign; ksign = 1; if ((unsigned int)i != strlen(ptr)) ptr[i] = last; ptr = &ptr[i+1]; break; } } // ignore Spaces i = 0; while ((ptr[i] <= ' ') && ((unsigned int)i < strlen(ptr)) ) i++; if ((unsigned int)i < strlen(ptr)) ptr += i; // remember where we are in the formula p1 = ptr; p2 = ptr; } else { // there was no bracket, so look for a number msign = ksign; // find the operand p1 = 0; p2 = 0; // sign is already determined, so remaining should begin with digits // or a point it is not allowed to begin a number with the exponent! // the decimal point is allowed to be input as a comma if (((ptr[0] >= '0') && (ptr[0] <= '9')) || (ptr[0] == ',') || (ptr[0] == '.')) { // we have found a number, so find the end of the number (only // mantissa). Commas are now changed to the decimal point p1 = ptr; while (((p1[0] >= '0') && (p1[0] <= '9')) || (p1[0] == ',') || (p1[0] == '.')) { if (p1[0] == ',') p1[0] = '.'; p1++; } last = p1[0]; // remember the character, which ends the mantissa p1[0] = 0; sscanf (ptr, "%lf", &mantisse); // read in the mantissa p1[0] = last; if (toupper(last) == 'E') { // is the last character a exponent // indicator ? p1++; // check sign of exponent p2 = p1; if (p2[0] == '-') { p2++; p1++; esign = -1; } else if (p2[0] == '+') { p2++; p1++; esign = 1; } // find end of exponent while ((p2[0] >= '0') && (p2[0] <= '9')) p2++; last = p2[0]; p2[0] = 0; sscanf (p1, "%lf", &exponent); // read in the exponent mantisse = mantisse * pow(10,exponent*esign); p2[0] = last; } // put the found number on the stack NumStack[*iStack] = (double) msign * mantisse; } else { // we have not found a number, so the formula may contain a variable // or a function. The name of this allways has to begin with a // character in the range [a..z] or [A..Z] p1 = 0; p2 = 0; if (((ptr[0] >= 'a') && (ptr[0] <= 'z')) || ((ptr[0] >= 'A') && (ptr[0] <= 'Z'))) { p1 = ptr; p1++; // find the end of the name; names may contain the characters // [a..z] or [A..Z] or some digits. while (((p1[0] >= 'a') && (p1[0] <= 'z')) || ((p1[0] >= 'A') && (p1[0] <= 'Z')) || ((p1[0] >= '0') && (p1[0] <= '9'))) p1++; last = p1[0]; // remember the character, which separates the name p1[0] = 0; fkt = (char*) malloc(strlen(ptr)+1); nam = (char*) malloc(strlen(ptr)+1); strcpy(nam, ptr); // internal functions are interpreted case insensitive, therefore // convert the searchstring to uppercase for (i = 0; (unsigned int)i < strlen(ptr) +1; i++) fkt[i] = toupper(ptr[i]); p1[0] = last; ifkt = 1; // ---------- internal functions ---------------------------------------- // look in the table of internal constants/variables; zfkt = -1; while (fkt[0] == ' ') fkt++; for (ii = 0; ii < INTERNCONS; ii++) { if (strstr(fkt, interncons[ii]) == fkt) { zfkt = ii; // change of ifkt to 0 indicates, that we have found and // calculated a function ifkt = 0; break; } } if (zfkt >= 0) { switch(zfkt) { case 0: // "ANS" copy the last result to the stack NumStack[*iStack] = (double) msign * CalculatorRes; break; case 1: // "PI" copy PI to the stack NumStack[*iStack] = (double) msign * CalculatorPI; break; } } if (ifkt) { // look in the table of internal functions; zfkt = -1; while (fkt[0] == ' ') fkt++; for (ii = 0; ii < INTERNFKT; ii++) { if (strstr(fkt, internfkt[ii]) == fkt) { zfkt = internfktid[ii]; // change of ifkt to 0 indicates, that we have found and // calculated a function ifkt = 0; break; } } // for real funktions increment p1 to take into account closing brackets if (zfkt >= 0) { switch(zfkt) { case 0: // "LN" natural logarithmus NumStack[*iStack] = (double) msign * log(FindBrackets(p1, &i, cal)); if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 1: // "EXP" power of e NumStack[*iStack] = (double) msign * exp(FindBrackets(p1, &i, cal)); if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 2: // "LOG10" logarithmus of base 10 NumStack[*iStack] = (double) msign * log10(FindBrackets(p1, &i, cal)); if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 3: // "LOG2" logarithmus of base 2 NumStack[*iStack] = (double) msign * log(FindBrackets(p1, &i, cal))/log(2.); if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 4: // "LOG" logarithmus of base N dummy = FindDualParam(p1, &i, cal, &basis); dummy = log(dummy)/log(basis); NumStack[*iStack] = (double) msign * dummy; if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 5: // "ABS" value without sign NumStack[*iStack] = (double) msign * fabs(FindBrackets(p1, &i, cal)); break; case 6: // "SQRT" sqare root NumStack[*iStack] = (double) msign * sqrt(FindBrackets(p1, &i, cal)); if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 7: // "ATAN2" arcustanges with two parameters for correct sign dummy = FindDualParam(p1, &i, cal, &basis); dummy = atan2(basis, dummy); if (CalculatorRad == 2) // Degree dummy *= 180./CalculatorPI; NumStack[*iStack] = (double) msign * dummy; if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 8: // "SIGN" return sign of number dummy = FindBrackets(p1, &i, cal); basis = dummy/fabs(dummy); NumStack[*iStack] = (double) msign * basis; break; case 9: // "AHSIN" arcus sinus hyperbolicus dummy = FindBrackets(p1, &i, cal); dummy = asinh(dummy); if (CalculatorRad == 2) // Degree dummy *= 180./CalculatorPI; NumStack[*iStack] = (double) msign * dummy; if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 10: // "ASIN" arcus sinus dummy = FindBrackets(p1, &i, cal); dummy = asin(dummy); if (CalculatorRad == 2) // Degree dummy *= 180./CalculatorPI; NumStack[*iStack] = (double) msign * dummy; if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 11: // "HSIN" sinus hyperbolicus dummy = FindBrackets(p1, &i, cal); if (CalculatorRad == 2) // Degree dummy *= CalculatorPI/180.; NumStack[*iStack] = (double) msign * sinh(dummy); break; case 12: // "SIN" sine dummy = FindBrackets(p1, &i, cal); if (CalculatorRad == 2) // Degree dummy *= CalculatorPI/180.; dummy = sin(dummy); if (fabs(dummy) < 1e-15) dummy = 0; NumStack[*iStack] = (double) msign * dummy; break; case 13: // "AHCOS" arcus cosinus hyperbolicus dummy = FindBrackets(p1, &i, cal); dummy = acosh(dummy); if (CalculatorRad == 2) // Degree dummy *= 180./CalculatorPI; NumStack[*iStack] = (double) msign * dummy; if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 14: // "ACOS" arcus cosinus dummy = FindBrackets(p1, &i, cal); dummy = acos(dummy); if (CalculatorRad == 2) // Degree dummy *= 180./CalculatorPI; NumStack[*iStack] = (double) msign * dummy; if (!finite(NumStack[*iStack])) CalculatorError = ERR_DOMAIN; break; case 15: // "HCOS" cosinus hyperbolicus dummy = FindBrackets(p1, &i, cal); if (CalculatorRad == 2) // Degree dummy *= CalculatorPI/180.; NumStack[*iStack] = (double) msign * cosh(dummy); break; case 16: // "COS" cosinus dummy = FindBrackets(p1, &i, cal);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -