Facebook
From Sharescript.net, 3 Years ago, written in C++.
Embed
Download Paste or View Raw
Hits: 167
  1. #include <bits/stdc++.h>
  2. #include <unistd.h>
  3. #include <windows.h>
  4. class Trungto
  5. {
  6.     int n; // n là số phần tử của mảng input, mongoac và dongngoac để lưu lại có bao nhiêu dấu mở ngoặc đóng ngoặc
  7.     std::string test;
  8.     std::stack <std::string> s1;
  9.     std::stack <char> s2;
  10.     std::string tg, tg2; // Dùng để lưu lại số thập phân để xài
  11.     public:
  12.         std::string error;
  13.         Trungto(){}
  14.         Trungto(std::string test){
  15.             this->test = test;
  16.             this->n = test.length();
  17.         }
  18.         ~Trungto(){}
  19.         // Hàm để kiểm tra xem ký tự char c truyền vào có phải là một toán tử không, đồng thời phân chia độ ưu tiên của toán tử
  20.         int toantu(char c){
  21.             if(c == '*' || c == '/') return 2;
  22.             if(c == '+' || c == '-') return 1;
  23.             return 0;
  24.         }
  25.         // Hàm kiểm tra xem ký tự char c truyền vào có phải là một chữ số không
  26.         bool chuso(char c){
  27.             if(c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9')
  28.                 return true;
  29.             return false;
  30.         }
  31.         std::string tinhtoan(std::string a, std::string b, char c){
  32.             float x, y, s;
  33.             x = atof(a.c_str());
  34.             y = atof(b.c_str());
  35.             if(c == '+') s = x + y;
  36.             if(c == '-') s = y - x;
  37.             if(c == '*') s = x * y;
  38.             if(c == '/') s = y / x;
  39.             a = std::to_string(s);
  40.             return a;
  41.         }
  42.         void instack(){
  43.             tg = s1.top(); // Lấy phần tử của đỉnh stack s1
  44.             s1.pop(); // Xóa phần tử của đỉnh stack s1
  45.             tg2 = s1.top(); // Lấy phần tử của đỉnh stack s1 lần 2
  46.             s1.pop(); // Xóa phần tử của đỉnh stack s1 lần 2
  47.             s1.push(tinhtoan(tg, tg2, s2.top())); // Chèn vào đỉnh stack s1: tg + - * / tg2
  48.             s2.pop(); // Xóa phần tử của đỉnh stack s2
  49.         }
  50.         std::string lamtron(std::string a, int n){
  51.             std::stringstream ss;
  52.             int pos = a.find('.');
  53.             if(n == 0){
  54.                 for(int i = 0 ; i < pos; i ++){
  55.                     ss << a[i];
  56.                 }
  57.             }
  58.             else{
  59.                 for(int i = 0 ; i <= pos + n; i ++){
  60.                     ss << a[i];
  61.                 }
  62.             }
  63.             ss >> a;
  64.             return a;
  65.         }
  66.         bool validate(){
  67.             int mongoac = 0, dongngoac = 0;
  68.             bool check1;
  69.             /* Validate:
  70.             Ở giữa:
  71.             - Hai toán tử ko được gần nhau như này: *+
  72.             - Ngoặc vs số ko được gần nhau như này: 5(, )5
  73.             - Hai ngoặc không được như này: (), )(
  74.             - Dấu chấm phải nằm giữa 2 số: 9.6
  75.             - Số ngoặc mở phải bằng số ngoặc đóng và phải có ngoặc mở trước
  76.             - Ngoặc mở phải được thấy trước ngoặc đóng
  77.             - Toán tử phải nằm giữa 2 số hoặc nằm sau dấu ), nằm trước dấu (
  78.             Ở đầu:
  79.             - Chỉ có số và dấu mở ngoặc được phép
  80.             Ở cuối:
  81.             - Chỉ có số và dấu đóng ngoặc được phép
  82.             */
  83.             // Kiểm tra xem ký tự đầu tiên có phải là dấu mở ngoặc hoặc là 1 số không
  84.             if(test[0] != '(' && !chuso(test[0])){
  85.                 error = "Bạn đã viết sai cú pháp, ký tự đầu tiên phải là số hoặc dấu mở ngoặc!";
  86.                 return false;
  87.             }
  88.             else{
  89.                 if(test[0] == '('){
  90.                     mongoac ++;
  91.                 }
  92.                 // Kiểm tra xem ký tự cuối cùng có phải là dấu đóng ngoặc hoặc là 1 số không
  93.                 if(test[n-1] != ')' &&  !chuso(test[n-1])){
  94.                     error = "Bạn đã viết sai cú pháp, ký tự cuối cùng phải là số hoặc dấu đóng ngoặc!";
  95.                     return false;
  96.                 }
  97.                 else{
  98.                     check1 = false;
  99.                     for(int i = 1; i < n; i++){
  100.                         // Kiểm tra xem phần tử mình duyệt có chứa các ký tự khác không được phép không
  101.                         if(toantu(test[i]) == 0 && test[i] != '(' && test[i] != ')' && test[i] != '.' && !chuso(test[i]) && test[i] != ' '){
  102.                             error = "Dường như bạn đã nhập sai, những ký tự được hỗ trợ gồm + - * / ( ) . dấu cách và 0 đến 9!";
  103.                             return false;
  104.                         }
  105.                         // Dấu . phải nằm giữa 2 số
  106.                         if(test[i] == '.'){
  107.                             if(!chuso(test[i - 1]) || !chuso(test[i + 1])){
  108.                                 error = "Dường như bạn đã viết sai số thập phân, xem lại nhé!";
  109.                                 return false;
  110.                             }
  111.                         }
  112.                         // Hai toán tử không được gần nhau
  113.                         if(toantu(test[i]) != 0){
  114.                             if(toantu(test[i - 1]) != 0 || toantu(test[i + 1]) != 0){
  115.                                 error = "Dường như bạn đã viết toán tử liền kề nhau, xem lại nhé!";
  116.                                 return false;
  117.                             }
  118.                         }
  119.                         // Kiểm tra xem có các kiểu cấu trúc dạng này không: 5(, (), )( và tăng giá trị của dấu mở ngoặc lên 1
  120.                         if(test[i] == '('){
  121.                             mongoac ++;
  122.                             if(test[i - 1] == ')' || test[i + 1] == ')' || chuso(test[i - 1])){
  123.                                 error = "Bạn đã viết sai một trong số các cú pháp sau: 5(, (), )(";
  124.                                 return false;
  125.                             }
  126.                         }
  127.                         // Toán tử nằm giữa 2 số hoặc nằm sau dấu ), nằm trước dấu (
  128.                         if(toantu(test[i]) != 0){
  129.                             if(test[i - 1] != ')' && !chuso(test[i - 1])){
  130.                                 error = "Dường như bạn đã đặt sai chỗ toán tử, xem lại nhé!";
  131.                                 return false;
  132.                             }
  133.                             if(test[i + 1] != '(' && !chuso(test[i + 1])){
  134.                                 error = "Dường như bạn đã đặt sai chỗ toán tử, xem lại nhé!";
  135.                                 return false;
  136.                             }
  137.                         }
  138.                         // Kiểm tra xem có các kiểu cấu trúc dạng này không: )5, (), )( và tăng giá trị của dấu đóng ngoặc lên 1
  139.                         if(test[i] == ')'){
  140.                             dongngoac ++;
  141.                             if(test[i - 1] == '(' || test[i + 1] == '(' || chuso(test[i + 1])){
  142.                                 error = "Bạn đã viết sai một trong số các cú pháp sau: (5, (), )(";
  143.                                 return false;
  144.                             }
  145.                             // Kiểm tra xem dấu đóng ngoặc có xuất hiện trước dấu mở ngoặc không
  146.                             if(dongngoac > mongoac){
  147.                                 error = "Có vấn đề với dấu đóng ngoặc, hãy chắc chắn rằng bạn đã nhập đúng!";
  148.                                 return false;
  149.                                 check1 = true;
  150.                             }
  151.                         }
  152.                     }
  153.                     // Sau khi duyệt hết phần tử, so sánh dấu đóng và mở ngoặc xem có bằng nhau không
  154.                     if(dongngoac != mongoac && check1 == false){
  155.                         error = "Có vấn đề với dấu mở đóng ngoặc, số dấu mở ngoặc khác số dấu đóng ngoặc!";
  156.                         return false;
  157.                     }
  158.                 }
  159.             }
  160.             return true;
  161.         }
  162.         std::string start(int tronso){
  163.             std::stringstream ss; // Dùng để nối số thập phân
  164.             std::string a;
  165.             char b; // Dùng để lưu lại toán tử và dấu đóng mở ngoặc để xài
  166.             bool check, check2; // Check để kiểm tra xem số thập phân có tồn tại không, check2 để kiểm tra toán tử có tồn tại không
  167.             ss.str("");
  168.             ss.clear();
  169.             check2 = true;
  170.             for(int i = 0; i < n; i++){ // Duyệt hết chuỗi
  171.                 if(test[i] == ' ') continue;
  172.                 if(!chuso(test[i]) && test[i] != '.'){ // Nếu không phải là chữ số và dấu .
  173.                     if(ss.rdbuf()->in_avail() == 0){ // Kiểm tra ss có chứa số không
  174.                         b = test[i]; // b là toán tử hoặc dấu ngoặc
  175.                     }
  176.                     else{
  177.                         b = test[i]; // b là toán tử hoặc dấu ngoặc
  178.                         check = true;
  179.                         ss >> a; // a sẽ chứa số thập phân
  180.                         ss.str(""); // Clear ss
  181.                         ss.clear();
  182.                     }
  183.                 }
  184.                 else{ // Nếu là toán tử hoặc dấu ngoặc
  185.                     if(chuso(test[i]) || test[i] == '.'){ // Nếu là chữ số hoặc dấu .
  186.                         ss << test[i]; // Truyền vào ss
  187.                     }
  188.                     if(chuso(test[n - 1]) && i == (n - 1)){
  189.                         check = true;
  190.                         check2 = false;
  191.                         ss >> a;
  192.                         ss.str("");
  193.                         ss.clear();
  194.                     }
  195.                     else{
  196.                         continue;
  197.                     }
  198.                 }
  199.                 if(check == true){ // Nếu có giá trị số float được trả về
  200.                     s1.push(a);
  201.                 }
  202.                 if(check2 == true){ // Nếu có giá trị char được trả về
  203.                     if(b == '(') // Gặp dấu mở ngoặc thì cho vào stack s2
  204.                         s2.push(b);
  205.                     if(toantu(b) != 0){
  206.                         if(!s2.empty()){
  207.                             while(true){
  208.                                 if(s2.empty()) break;
  209.                                 if(toantu(b) > toantu(s2.top()) || toantu(b) == 0){
  210.                                     break;
  211.                                 }
  212.                                 else{
  213.                                     instack();
  214.                                 }
  215.                             }
  216.                         }
  217.                         s2.push(b);
  218.                     }
  219.                     if(b == ')'){
  220.                         while(true){
  221.                             if(s2.top() == '('){
  222.                                 s2.pop();
  223.                                 break;
  224.                             }
  225.                             else{
  226.                                 instack();
  227.                             }
  228.                         }
  229.                     }
  230.                 }
  231.                 check = false;
  232.             }
  233.             while(!s2.empty()){
  234.                 instack();
  235.             }
  236.             return lamtron(s1.top(), tronso);
  237.         }
  238. };
  239. int main(){
  240.     SetConsoleOutputCP(65001);
  241.     std::string bieuthuc = "9.898+8.22*(7.64-(8.2654+9.11)-2.65)*89+655.66";
  242.     int sochusosaudauphay = 2;
  243.     Trungto T {bieuthuc};
  244.     // Nếu cần xác định input có đúng không?
  245.     if(T.validate()){
  246.         std::cout << T.start(sochusosaudauphay);
  247.     }
  248.     else
  249.     {
  250.         std::cout << T.error;
  251.     }
  252.     // Nếu không cần xác định input mà tính toán luôn
  253.     // std::cout << T.start(sochusosaudauphay);
  254.    
  255.     return 0;
  256. }