思路:
之前写的乘法有点小问题,现在更正了
普通表达式运算:
采用字符串的形式输入一个表达式和栈结构来存储中间运算结果,可以参照《数据结构(严慧敏)》,依次从字符串中读取字符,如果是数字则读取整个数字,如果是运算符则判断优先级(出栈\压栈\计算)......
大整数表达式运算:
与普通的表达式同一个思路,只不过现在的数变成了大整数,所以得自己分别实现大整数的四则运算(另外说明下单词都是百度来的...)大致的说明下思路:
加法:
将数字字符串提取出来后从每个数字的最后一位开始相加,用一个变量t来存储是否进位,一开始没有进位所以我给t赋初值为0,每一次我都会判断是否有进位,如果有就让t=1(最多进一位),因为是字符所以运算的时候减去字符‘0’以方便运算。
while (lena >= 0 && lenb >= 0) {
result[i] = a[lena] + b[lenb] - 2 * '0' + t;
t = result[i] / 10;
result[i] = result[i] % 10 + '0';
i++; lena--; lenb--;
}
要考虑其中一位加完后另外一位没有加完的情况,这个时候直接将没有加完的加到结果上去就好了
while (lena >= 0) {//a没加完的情况
result[i] = a[lena] + t - '0';
t = result[i] / 10;
result[i] = result[i] % 10 + '0';
i++; lena--;
}
while (lenb >= 0) {//b没加完的情况
result[i] = b[lenb] + t - '0';
t = result[i] / 10;
result[i] = result[i] % 10 + '0';
i++; lenb--;
}
if (t)result[i++] = t + '0';
result[i] = '\0';//不要忘了最后加上‘\0’
BigIntegerResultReverse(result);//同时计算出来的结果其实是倒过来的,再次将结果反转
乘法:
static void BigIntegerMulti(char a[], char b[], char result[])
{
memset(result, '0', 1000);//先将结果数组初始化一波做准备
int lena = strlen(a) - 1;
int lenb = strlen(b) - 1;
int k = lenb, j = lena, t = 0, temp;//同样的t表示进位
while (k >= 0) {//数字(组)b的最后一位分别乘以a的每一位
for (j = lena; j >= 0; j--) {
temp = (b[k] - '0')*(a[j] - '0') + t + result[lenb - k + lena - j] - '0';//lenb-k表示计算到b的第k位
result[lenb - k + lena - j] = temp % 10 + '0'; //lena-j表示计算到a的第j位
t = temp / 10;//lenb - k + lena - j则表示此时正在计算的这一位应该加到结果的第lenb - k + lena - j位上去,想一想你手算的过程
}
if (k == 0)break;
if (t) {
result[lenb - k + lena + 1] = t + '0';
t = 0;
}
k--;
}
if (t) {
result[lena + lenb + 1] = t + '0';
result[lena + lenb + 2] = '\0';
}
else result[lena + lenb + 1] = '\0';
BigIntegerResultReverse(result);
}
(本人算法小白,存在的bug还请大佬指点一二),下面给出代码,如果要计算大整数记得在输入的时候加上'L';例如:“L132465454561231+45613465*15341865465”
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
static int charactor[256];
static void CharactorInit()
{
charactor['+'] = 1;
charactor['-'] = 2;
charactor['*'] = 3;
charactor['/'] = 4;
charactor['('] = 5;
charactor[')'] = 6;
//charactor[' '] = 7;
}
static int PriorityJudge(char x1, char x2)
{ //-1:x1<x2 0:x1=x2 1:x1>x2
if (charactor[x1] >= 1 && charactor[x1] <= 4 && charactor[x2] >= 1 && charactor[x2] <= 4 && x1 == x2)
return 1;
if (charactor[x1] == 5)
{
if (charactor[x2] == 6)
return 0;
return -1;
}
if (charactor[x1] == 3 || charactor[x1] == 4)
{
if (charactor[x2] == 5)
return -1;
return 1;
}
if (charactor[x1] == 1 || charactor[x1] == 2)
{
if (charactor[x2] <= 5 && charactor[x2] >= 3)
return -1;
return 1;
}
return -1;
}
// <-------------------------StatementCompulation------------------------------>
#define EMPTY 0
#define StackGrewSpeed 100
typedef struct CompulationStack
{
int *p = (int *)malloc(sizeof(int) * 1000);
int *top = p;
int AllLength = 1000;
int CurLength = 0;
} CompulationStack;
static int Pop(CompulationStack *stack);
static int Push(CompulationStack *stack, int x);
static int ResizeStack(CompulationStack *stack);
static int IsEmpty(CompulationStack *stack);
static int GetTop(CompulationStack *stack, int *x);
static int Caculator(int a, int b, char method);
static int JudgeCharactor(char x);
static int PriorityJudge(char x1, char x2);
/*
static void InitStatement(int cha) {
int length = sizeof(cha) / sizeof(int);
for(int i=0;i<length;i++)cha=
}
*/
static int Pop(CompulationStack *stack)
{
if (IsEmpty(stack))
return EMPTY;
stack->CurLength--;
return *--stack->top;
}
static int Push(CompulationStack *stack, int x)
{
if (stack->CurLength >= stack->AllLength)
ResizeStack(stack);
*stack->top++ = x;
stack->CurLength++;
return 1;
}
static int ResizeStack(CompulationStack *stack)
{
stack->AllLength += StackGrewSpeed;
stack->p = (int *)realloc(stack->p, stack->AllLength);
return 1;
}
static int IsEmpty(CompulationStack *stack)
{
if (stack->top == stack->p)
return !EMPTY;
return EMPTY;
}
static int GetTop(CompulationStack *stack, int *x)
{
if (!IsEmpty(stack))
{
return *x = *(stack->top - 1);
}
return 0;
}
static int Caculator(int a, int b, char method)
{
int a1 = a;
int a2 = b;
switch (method)
{
case '+':
return a1 + a2;
case '-':
return a1 - a2;
case '*':
return a1 * a2;
case '/':
return a1 / a2;
}
return -1;
}
static int JudgeCharactor(char x)
{
if (x - '0' >= 0 && x - '0' <= 9)
return 8;
return charactor[x];
}
int Compulation(char statement[])
{
CharactorInit();
int p, x, result = 0;
int statementLength = strlen(statement);
CompulationStack DigitStack;
CompulationStack CharactorStack;
for (int i = 0, j; i < statementLength;)
{
j = JudgeCharactor(statement[i]);
if (!j)
continue;
if (j == 8)
{
int k = i, temp = 0;
while (JudgeCharactor(statement[i + 1]) == 8)
i++;
for (int l = 0; l <= i - k; l++)
temp += (statement[i - l] - '0') * (int)pow(10, l);
Push(&DigitStack, temp);
i++;
}
else
{
p = PriorityJudge(GetTop(&CharactorStack, &x), statement[i]);
if (p == 1)
{
Push(&DigitStack, Caculator(Pop(&DigitStack), Pop(&DigitStack), Pop(&CharactorStack)));
// Push(&CharactorStack, statement[i]);
}
else if (p == 0)
{
//Push(&DigitStack, Caculator(Pop(&DigitStack), Pop(&DigitStack), Pop(&CharactorStack)));
Pop(&CharactorStack);
i++;
}
else if (p == -1)
{
Push(&CharactorStack, statement[i]);
i++;
}
}
}
if (IsEmpty(&CharactorStack))
return Pop(&DigitStack);
while (!IsEmpty(&CharactorStack))
Push(&DigitStack, Caculator(Pop(&DigitStack), Pop(&DigitStack), Pop(&CharactorStack)));
return Pop(&DigitStack);
return result;
}
// <------------------------BigInteger------------------------------------------>
#define Max_Biginteger_length 100000
static char result_temp[Max_Biginteger_length];
static void BigIntegerResultReverse(char result[]);
static void BigIntegerAdd(char a[], char b[], char result[]);
static void BigIntegerSub(char a[], char b[], char result[]);
static void BigIntegerMulti(char a[], char b[], char result[]);
//static void BigIntegerdevi(char a[], char b[], char result[]);
typedef struct BigIntegerStack
{
char *p[5000];
char **top = p;
int stackLength = 5000;
int CurLength = 0;
} BigIntegerStack;
static void B_Pop(BigIntegerStack *big_integer_stack, char p[])
{
if (big_integer_stack->top == big_integer_stack->p)
{
printf("something warning\n");
exit(0);
}
else
strcpy(p, *--big_integer_stack->top);
big_integer_stack->CurLength--;
}
static void B_Push(BigIntegerStack *big_integer_stack, char p[])
{
int len = strlen(p);
if (*big_integer_stack->top != NULL)free(*big_integer_stack->top);
*big_integer_stack->top = (char *)malloc(sizeof(char) * (len + 1));
strcpy(*big_integer_stack->top++, p);
big_integer_stack->CurLength++;
}
static void BigIntegerResultReverse(char result[])
{
int start = 0, end = strlen(result) - 1;
char temp;
for (; start < end; start++, end--) {
temp = result[start];
result[start] = result[end];
result[end] = temp;
}//reverse the result array
}
static void BigIntegerAdd(char a[], char b[], char result[])
{
int lena = strlen(a) - 1;
int lenb = strlen(b) - 1;
int t = 0, i = 0;
while (lena >= 0 && lenb >= 0) {
result[i] = a[lena] + b[lenb] - 2 * '0' + t;
t = result[i] / 10;
result[i] = result[i] % 10 + '0';
i++; lena--; lenb--;
}
while (lena >= 0) {
result[i] = a[lena] + t - '0';
t = result[i] / 10;
result[i] = result[i] % 10 + '0';
i++; lena--;
}
while (lenb >= 0) {
result[i] = b[lenb] + t - '0';
t = result[i] / 10;
result[i] = result[i] % 10 + '0';
i++; lenb--;
}
if (t)result[i++] = t + '0';
result[i] = '\0';
BigIntegerResultReverse(result);
}
static void BigIntegerSub(char a[], char b[], char result[])
{
int lena = strlen(a) - 1;
int lenb = strlen(b) - 1;
int t = 0, i = 0, flag = 0;
if (lena < lenb || (lena == lenb && strcmp(a, b) < 0)) {
char *p = b; b = a; a = p;
lena ^= lenb;
lenb ^= lena;
lena ^= lenb;
flag = 1;
}
while (lena >= 0 && lenb >= 0) {
result[i] = a[lena] - b[lenb] + '0' + t;
if (result[i] < '0') {
result[i] += 10;
t = -1;
}
else t = 0;
i++; lena--; lenb--;
}
while (lena >= 0) {
result[i] = a[lena--] + t;
if (result[i] < '0') {
result[i] += 10;
t = -1;
}
else t = 0;
i++;
}
if (flag)result[i++] = '-';
result[i] = '\0';
BigIntegerResultReverse(result);
}
static void BigIntegerMulti(char a[], char b[], char result[])
{
memset(result, '0', 1000);
int lena = strlen(a) - 1;
int lenb = strlen(b) - 1;
int k = lenb, j = lena, t = 0, temp;
while (k >= 0) {
for (j = lena; j >= 0; j--) {
temp = (b[k] - '0')*(a[j] - '0') + t + result[lenb - k + lena - j] - '0';
result[lenb - k + lena - j] = temp % 10 + '0';
t = temp / 10;
}
if (k == 0)break;
if (t) {
result[lenb - k + lena + 1] = t + '0';
t = 0;
}
k--;
}
if (t) {
result[lena + lenb + 1] = t + '0';
result[lena + lenb + 2] = '\0';
}
else result[lena + lenb + 1] = '\0';
BigIntegerResultReverse(result);
}
static char *B_Caculator(char a[], char b[], char method, char result[])//method参数为计算方法(+、-、*),通过对不同计算方法调用不同的大整数运算函数,同时对运算做一些预处理(比如两个负数相加就相当于两个正数相加,最后在所得的结果前面加上负号)
{
//char result[100000];
switch (method)
{
case '+':
if (a[0] == b[0] && a[0] == '-') {
BigIntegerAdd(&a[1], &b[1], result);
BigIntegerResultReverse(result);
result[strlen(result) + 1] = '\0';
result[strlen(result)] = '-';
BigIntegerResultReverse(result);
}
else if (a[0] == '-'&&b[0] != '-')BigIntegerSub(b, &a[1], result);
else if (b[0] == '-'&&a[0] != '-')BigIntegerSub(a, &b[1], result);
else BigIntegerAdd(a, b, result);
break;
case '-':
if (a[0] == b[0] && a[0] == '-')
BigIntegerSub(&b[1], &a[1], result);
else if (a[0] == '-'&&b[0] != '-') {
BigIntegerAdd(&a[1], b, result);
BigIntegerResultReverse(result);
result[strlen(result) + 1] = '\0';
result[strlen(result)] = '-';
BigIntegerResultReverse(result);
}
else if (b[0] == '-'&&a[0] != '-')BigIntegerAdd(a, &b[1], result);
else BigIntegerSub(a, b, result);
break;
case '*':
if (a[0] == b[0] && a[0] == '-')BigIntegerMulti(&a[1], &b[1], result);
else if (a[0] == '-' || b[0] == '-') {
if (a[0] == '-')BigIntegerMulti(&a[1], b, result);
else BigIntegerMulti(a, &b[1], result);
BigIntegerResultReverse(result);
result[strlen(result) + 1] = '\0';
result[strlen(result)] = '-';
BigIntegerResultReverse(result);
}
else BigIntegerMulti(a, b, result);
break;
default:
printf("--> unknown error(maby you input a unkonw charactor\n)");
break;
}
return result;
}
void BigIntegerCompulation(char statement[], char result_buff[])
{
CharactorInit();
int p, x, result = 0;
int statementLength = strlen(statement);
BigIntegerStack big_integer_stack;
CompulationStack CharactorStack;
memset(big_integer_stack.p, NULL, 5000);
char temp[100000], temp_result[100000];
for (int i = 0, j; i < statementLength;)
{
j = JudgeCharactor(statement[i]);
if (!j)
continue;
if (j == 8)
{
int k = i, temp_index = 0;
while (JudgeCharactor(statement[i]) == 8)//copy the next number
temp[temp_index++] = statement[i++];
temp[temp_index] = '\0';
B_Push(&big_integer_stack, temp);
}
else
{
p = PriorityJudge(GetTop(&CharactorStack, &x), statement[i]);
if (p == 1)
{
char a[100000], b[100000];
B_Pop(&big_integer_stack, b);//notice:pop b first,you subtract a subtrahend from a minuend
B_Pop(&big_integer_stack, a);//a is minuend,b is subtrahend
B_Push(&big_integer_stack, B_Caculator(a, b, Pop(&CharactorStack), temp_result));
}
else if (p == 0)
{
//Push(&DigitStack, Caculator(Pop(&DigitStack), Pop(&DigitStack), Pop(&CharactorStack)));
Pop(&CharactorStack);
i++;
}
else if (p == -1)
{
Push(&CharactorStack, statement[i]);
i++;
}
}
}
if (IsEmpty(&CharactorStack))
B_Pop(&big_integer_stack, result_buff);
else
{
while (!IsEmpty(&CharactorStack))
{
char a[100000], b[100000];
B_Pop(&big_integer_stack, b);
B_Pop(&big_integer_stack, a);
B_Push(&big_integer_stack, B_Caculator(a, b, Pop(&CharactorStack), temp_result));
}
B_Pop(&big_integer_stack, result_buff);
}
//BigIntegerResultReverse(result_buff);
if (result_buff[0] == '0')result_buff[1] = '\0';//if the result is equal to 0
}
int main() {
char statement[50000], result[2000];
gets_s(statement);
if (statement[0] == 'L') {
BigIntegerCompulation(&statement[1], result);
printf("%s\n", result);
}
else printf("%d\n", Compulation(statement));
return 0;
}