C语言程序设计基础期中项目之简易计算器

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

//对变量进行分析
typedef struct value {
    enum {
        FLOAT,
        ERROR,
        INT,
    } type;
    union {
        int zh;
        double fu;
    } val;
} Value;

//将字符串分段
typedef struct token {
    enum {
        Float,
        Integer,
        error,
        null,
        left_bracket,
        right_bracket,
        variable,
        operator,
    } type;
    char str[32];
} Token;

//变量赋值
typedef struct variable {
    char name[32];
    Value value;
} Variable;

typedef struct major_operator {
    char op;
    int position;
} Major;

int position_pointer = 0;

void type_ana(Token tokens[],int i);
Value meet_value(Value a,Value b,char opcode);
int check_parentheses(int l,int r,const Token tokens[]);
Value search_for_variable(char* str,Variable VARIABLE[],int* numbers,int* position_pointers);
int check_minus(int l,int r,Token tokens[]);
Major find_major_operator(Token tokens[],int l,int r);
Value eval(int l,int r,Variable VARIABLE[],Token tokens[],int *numbers);
Value eval_assign(int l,int r,Variable VARIABLE[],Token tokens[],int* numbers);
void print(Value val);
void Memset(Token tokens[],int number);

int main() {
    int len = 0;
    Token tokens[1025];
    Variable VARIABLE[129];
    int number_of_variables = 0;
    char s[32];
    char c;
    while(scanf("%input",s) != EOF) {
        len++;
        strcpy(tokens[len].str, s);
        type_ana(tokens, len);
        c = getchar();
        if (c == '\n' || c == EOF) {
            print(eval_assign(1, len, VARIABLE, tokens, &number_of_variables));
            Memset(tokens,len);
            len=0;
        }
    }
}

//判断输入类型
void type_ana(Token tokens[], int i) {
    int len = (int) strlen(tokens[i].str);
    if (len == 1) {
        if (*tokens[i].str == '+' || *tokens[i].str == '-' || *tokens[i].str == '*' || *tokens[i].str == '/' || *tokens[i].str == '=') {
            tokens[i].type = operator;
            return;
        } else if (*tokens[i].str == '(') {
            tokens[i].type = left_bracket;
            return;
        } else if (*tokens[i].str == ')') {
            tokens[i].type = right_bracket;
            return;
        }
    }
    char *input = tokens[i].str;
    int number_of_num = 0;
    int number_of_letter = 0;
    int number_of__ = 0;
    int number_of_dot = 0;
    for (int j = 0; j < len; j++) {
        if (*(input + j) >= 48 && *(input + j) <= 57) {
            number_of_num++;//数字
        } else if ((*(input+j) >= 65 && *(input + j) <= 90) || (*(input + j) >= 97 && *(input + j) <= 122)) {
            number_of_letter++;//字母
        } else if (*(input + j) == '_') {
            number_of__++;//下划线
        } else if (*(input + j) == '.') {
            number_of_dot++;//点
        }
    }
    if (number_of_dot == 1 && number_of_num == len - 1 && ((*input) >= 48 && (*input) <= 57) && (*(input + len - 1) >= 48 && *(input + len - 1) <= 57)) {
        if (*input == '0' && *(input + 1) != '.') {
            tokens[i].type = error;
            return;
        }
        tokens[i].type = Float;
        return;
    } else if ((number_of__ + number_of_letter + number_of_num == len) && (*input >= 97 && *input <= 122) || (*input >= 65 && *input <= 90) || *input == '_') {
        tokens[i].type = variable;
        return;
    } else if ((number_of_num == len && *input != '0') || (len == 1 && *input == '0')) {
        tokens[i].type = Integer;
        return;
    } else {
        tokens[i].type = error;
        return;
    }
}


Value meet_value(Value a,Value b,char mark) {
    Value Return;
    if (a.type == ERROR || b.type == ERROR) {
        Return.type = ERROR;
        Return.val.zh = 0;
        return Return;
    } else if (a.type == INT && b.type == INT) {
        Return.type = INT;
        switch (mark) {
            case '+':Return.val.zh = a.val.zh + b.val.zh;break;
            case '-':Return.val.zh = a.val.zh - b.val.zh;break;
            case '*':Return.val.zh = a.val.zh * b.val.zh;break;
            case '/':Return.val.zh = a.val.zh / b.val.zh;break;
            default:assert(0);
        }
        return Return;
    } else if (a.type == FLOAT || b.type == FLOAT) {
        Return.type = FLOAT;
        double fu_val1, fu_val2;
        unsigned int status = a.type * 2 + b.type;
        switch (status) {
            case 1:
                fu_val1 = (double)a.val.zh;
                fu_val2 = b.val.fu;
                break;
            case 2:
                fu_val1 = a.val.fu;
                fu_val2 = (double)b.val.zh;
                break;
            case 3:
                fu_val1 = a.val.fu;
                fu_val2 = b.val.fu;
                break;
            default:assert(0);
        }
        switch (mark) {
            case '+':Return.val.fu = fu_val1 + fu_val2;break;
            case '-':Return.val.fu = fu_val1 - fu_val2;break;
            case '*':Return.val.fu = fu_val1 * fu_val2;break;
            case '/':Return.val.fu = fu_val1 / fu_val2;break;
            default:assert(0);
        }
        return Return;
    }
}

//判断表达式是否被一对匹配的括号包围,表达式的左、右括号是否匹配
int check_parentheses(int l, int r, const Token tokens[]) {
    if (tokens[l].type != left_bracket || tokens[r].type != right_bracket) {
        return 0;
    }
    int left_status = 0;
    int right_status = 0;
    for (int i = l + 1; i < r ; i++) {
        if (tokens[i].type == right_bracket) {
            return 0;
        }
        if (tokens[i].type == left_bracket) {
            left_status = 1;
            break;
        }
    }
    for (int i = r - 1; i > l ; i--) {
        if (tokens[i].type == left_bracket) {
            return 0;
        }
        if (tokens[i].type == right_bracket) {
            right_status = 1;
            break;
        }
    }
    if ((right_status ^ left_status) == 0) {
        return 1;
    } else {
        return 0;
    }
}

//
Value search_for_variable(char *str, Variable VARIABLE[], int *numbers, int *position_pointers) {
    Value Return;
    for (int i = 1; i <= *numbers; i++) {
        if (strcmp(str, VARIABLE[i].name) == 0) {
            *(position_pointers) = i;
            return VARIABLE[i].value;
        }
    }
    Return.type = ERROR;
    Return.val.zh = 0;
    return Return;
}


int check_minus(int l, int r, Token tokens[]) {
    if (*tokens[l].str != '-') {
        return 0;
    }
    if ((tokens[l - 1].type != operator) && (tokens[l - 1].type != left_bracket) && (l != 1)) {
        return 0;
    }
    if ((tokens[l + 1].type == left_bracket && check_parentheses(l + 1, r, tokens)) ||
    (tokens[l + 1].type == Float && r == l + 1) || (tokens[l + 1].type == Integer &&
    r == l + 1) || (tokens[l + 1].type == variable)) {
        return 1;
    }
    if (*tokens[l + 1].str == '-') {
        return check_minus(l + 1, r, tokens);
    }
    else return 0;
}


Major find_major_operator(Token tokens[], int l, int r) {
    Major Return;
    int into_parenthes = 0;
    int po_plus = -1;
    int po_minus = -1;
    int po_mul = -1;
    int po_divi = -1;
    for (int i = r; i >= l; i--) {
        if (tokens[i].type == right_bracket) {
            into_parenthes++;
        } else if (tokens[i].type == left_bracket && into_parenthes) {
            into_parenthes--;
        }
        if (tokens[i].type == operator && into_parenthes == 0) {
            switch (*tokens[i].str) {
                case '+':if (po_plus == -1 && po_minus == -1) {
                    po_plus = i;
                }
                    break;
                case '-':if (tokens[i - 1].type == operator || i == 1 || tokens[i - 1].type == left_bracket) {
                        break;
                    } else {
                    if (po_minus == -1 && po_plus == -1) {
                        po_minus = i;
                    }
                        break;
                }
                case '*':if (po_mul == -1 && po_divi == -1) {
                    po_mul = i;
                }
                    break;
                case '/':if (po_divi == -1 && po_mul == -1) {
                    po_divi = i;
                }
                    break;
                default:assert(0);
            }
        }
    }
    if (into_parenthes > 0) {
        Return.position = -1;
        Return.op = '+';
        return Return;
    }
    if ((po_plus > l && po_plus < r) || (po_minus > l && po_minus < r)) {
        Return.position = po_plus > po_minus ? po_plus : po_minus;
        Return.op = po_plus > po_minus ? '+' : '-';
        return Return;
    } else if ((po_mul > l && po_mul < r) || (po_divi > l && po_divi < r)) {
        Return.position = po_mul > po_divi ? po_mul : po_divi;
        Return.op = po_mul > po_divi ? '*' : '/';
        return Return;
    } else {
        Return.position = -1;
        Return.op = '+';
        return Return;
    }
}

//求值函数
Value eval(int l, int r, Variable VARIABLE[], Token tokens[], int *numbers) {
    Value Return;
    Value Val;
    Major opcode;
    if (l > r) {
        Return.val.zh = 0;
        Return.type = ERROR;
    } else if (l == r) {
        if (tokens[l].type == Integer) {
            Return.type = INT;
            Return.val.zh = (int) atoi(tokens[l].str);
        } else if (tokens[l].type == Float) {
            Return.type = FLOAT;
            Return.val.fu = (float) strtod(tokens[l].str,NULL);
        } else if (tokens[l].type == variable) {
            Return = search_for_variable(tokens[l].str, VARIABLE, numbers, &position_pointer);
        } else {
            Return.type = ERROR;
            Return.val.zh = 0;
        }
    } else if (check_parentheses(l, r, tokens)) {
        Return = eval(l + 1, r - 1, VARIABLE, tokens, numbers);
    } else if (check_minus(l, r, tokens)) {
        Val = eval(l + 1, r, VARIABLE, tokens, numbers);
        Return.type = Val.type;
        switch (Val.type) {
            case FLOAT:Return.val.fu = (-1.0) * Val.val.fu;break;
            case INT:Return.val.zh = (-1) * Val.val.zh;break;
            case ERROR:Return.val.zh = 0;break;
            default:assert(0);
        }
    } else {
        opcode = find_major_operator(tokens, l, r);
        if (opcode.position != -1) {
            Return = meet_value(eval(l, opcode.position - 1, VARIABLE, tokens, numbers),
                               eval(opcode.position+1, r, VARIABLE, tokens, numbers), opcode.op);
        } else {
            Return.val.zh = 0;
            Return.type = ERROR;
        }
    }
    return Return;
}


Value eval_assign(int l, int r, Variable VARIABLE[], Token tokens[], int *numbers) {
    Value zhengzhendezhi;
    Value Return;
    Variable var;
    if (strcmp(tokens[l + 1].str, "=") == 0) {
        if (tokens[l].type != variable) {
            Return.type = ERROR;
            return Return;
        } else {
            zhengzhendezhi = search_for_variable(tokens[l].str, VARIABLE, numbers, &position_pointer);
            if (zhengzhendezhi.type == ERROR) {
                strcpy(var.name, tokens[l].str);
                var.value = eval_assign(l + 2, r, VARIABLE, tokens, numbers);
                //保存变量
                (*numbers)++;
                VARIABLE[(*numbers)] = var;
            } else {
                VARIABLE[position_pointer].value = eval_assign(l + 2, r, VARIABLE, tokens, numbers);
            }
            return eval_assign(l + 2, r, VARIABLE, tokens, numbers);
        }
    } else {
        return eval(l, r, VARIABLE, tokens, numbers);
    }
}

void print(Value val) {
    if (val.type == ERROR) {
        printf("Error\n");
    } else if (val.type == INT) {
        printf("%d\n", val.val.zh);
    } else if (val.type == FLOAT) {
        printf("%.6f\n", val.val.fu);
    }
}

void Memset(Token tokens[], int number) {
    for (int i = 1; i <= number; i++) {
        tokens[i].type = null;
        memset(tokens[i].str, 0, sizeof(tokens[i].str));
    }
}

This code appears to be a program that performs arithmetic calculations and variable assignments based on input from the user. Let's go through the code and understand its structure and functionality.
The code starts by including several header files: stdio.h, assert.h, stdlib.h, and string.h. These header files provide various functions for standard input/output, assertion handling, memory allocation, and string manipulation.
Next, the code defines three structs: Value, Token, and Variable. Here's a brief description of each struct:

1.Value: It represents a value that can be of three types: FLOAT, ERROR, or INT. The val field is a union that can hold either an integer (zh) or a double (fu).
2.Token: It represents a token, which is a small unit of a program's source code. Each token can have a type (such as Float, Integer, error, etc.) and a corresponding string representation (str).
3.Variable: It represents a named variable in the program. It has a name field (a string) and a value field (of type Value).

After defining the structs, the code declares several function prototypes and a global variable position_pointer.
The main function is the entry point of the program. It initializes variables and loops to read input from the user using scanf. It stores the input tokens in an array called tokens and then calls the type_ana function to analyze the type of each token.
The type_ana function examines the length and content of the input token to determine its type and updates the type field of the corresponding Token struct.
Following the main function, there are several other functions defined:

4.meet_value: It takes two Value structures and an operator as input and performs a specific operation (addition, subtraction, multiplication, or division) based on the operator, returning the result as a Value.
5.check_parentheses: It checks if the parentheses in a given range of tokens are balanced.
6.search_for_variable: It searches for a variable by name in the VARIABLE array and returns its corresponding Value.
7.check_minus: It checks if there is a unary minus operator in a given range of tokens.
8.find_major_operator: It finds the highest priority operator in a given range of tokens.
9.eval: It evaluates an arithmetic expression given a range of tokens, using the reverse Polish notation (RPN) algorithm.
10.eval_assign: It evaluates an assignment expression given a range of tokens.
11.print: It prints the value of a Value structure to the standard output.
12.Memset: It clears the tokens array up to a certain index.

Each of these functions performs a specific task related to parsing, evaluating, and handling arithmetic expressions and variable assignments.
Overall, this code seems to implement a basic calculator that supports arithmetic operations, variables, and assignments. It reads input from the user, analyzes the type of each token, and evaluates the corresponding expression or assignment using the defined functions.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cytingle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值