前提・実現したいこと
逆ポーランド記法で入力された数式の計算を行いたいと考えています。
また、制約としてスタックを用いて実装し、そのスタックは連結リストを用いて実装するというものです。
試作段階としてスタックのみを使用して実装した逆ポーランド記法の計算は問題なく計算できるのですが、スタックを連結リストで実装した際に、入力した数値が小数点以下6位や7位あたりで少しずれてしまい、計算結果が大きく変わってしまいました。数値の変動はGDBで確認しました。
入力方法として逆ポーランド記法の数式を文字列として入力しました。その際、数値と演算子の後にはスペースを入れています。これはスペースまでを一区切りにし、演算子だった場合はその演算子の演算を行い、数値だった場合はatofで数値へ戻しています。
これは、単純にプログラムが間違っているのかC言語やPCの特性なのかそのほかの要因なのか教えていただきたいと考えています。
該当のソースコード
c
1#include <stdio.h> 2#include <stdlib.h> 3#include <stdbool.h> 4 5#define STACK_SIZE 8 6#define DATA_SIZE 64 7 8struct cell{ 9 float value; 10 struct cell *next; 11}; 12 13struct cell *head = NULL; 14struct cell **p; 15 16bool first_flag = false; 17 18int PostfixNotation(char pnData_c[STACK_SIZE]); 19int Push(float data); 20int Pop(float *data, int n); 21void InsertCell(struct cell **p_pointer, float new_value); 22float DeleteCell(struct cell **p_pointer, int n); 23 24int main(){ 25 char pnData[64]; 26 float ans = 0; 27 int n = 0; 28 29 printf("input data(input space after number and operator)\n"); 30 scanf("%[^\n]%*c", &pnData); 31 32 PostfixNotation(pnData); 33 34 Pop(&ans, n - 1); 35 printf("ans : %.2f\n", ans); 36 37 return 0; 38} 39 40int PostfixNotation(char pnData_c[STACK_SIZE]){ 41 char temp[8] = ""; 42 int i = 0, j = 0, n = 0; 43 float pnData_f, first = 0, second = 0; 44 while(pnData_c[i] != '\0'){ 45 if(pnData_c[i] == ' '){ 46 if(pnData_c[i - 1] == '+'){ 47 Pop(&second, n - 1); 48 n--; 49 Pop(&first, n - 1); 50 n--; 51 Push(first + second); 52 }else if(pnData_c[i - 1] == '-'){ 53 Pop(&second, n - 1); 54 n--; 55 Pop(&first, n - 1); 56 n--; 57 Push(first - second); 58 n++; 59 }else if(pnData_c[i - 1] == '*'){ 60 Pop(&second, n - 1); 61 n--; 62 Pop(&first, n - 1); 63 n--; 64 Push(first * second); 65 n++; 66 }else if(pnData_c[i - 1] == '/'){ 67 Pop(&second, n - 1); 68 n--; 69 Pop(&first, n - 1); 70 n--; 71 Push(first / second); 72 n++; 73 }else{ 74 pnData_f = atof(temp); 75 Push(pnData_f); 76 n++; 77 } 78 j = 0; 79 i++; 80 for(int k = 0; k < STACK_SIZE; k++){ 81 temp[k] = '\0'; 82 } 83 } 84 temp[j] = pnData_c[i]; 85 j++; 86 i++; 87 } 88} 89 90int Push(float data){ 91 if(!first_flag){ 92 p = &head; 93 first_flag = true; 94 } 95 InsertCell(p, data); 96 p = &((*p)->next); 97 return 1; 98} 99 100int Pop(float *data, int i){ 101 p = &head; 102 *data = DeleteCell(p, i - 1); 103 return 1; 104} 105 106void InsertCell(struct cell **p_pointer, float new_value){ 107 struct cell* new_cell; 108 new_cell = malloc(sizeof(struct cell)); 109 new_cell->value = new_value; 110 new_cell->next = *p_pointer; 111 *p_pointer = new_cell; 112} 113 114float DeleteCell(struct cell **p_pointer, int i){ 115 struct cell *delete_cell; 116 float pop_data = 0; 117 while(i > 0 && *p_pointer != NULL){ 118 p_pointer = &((*p_pointer)->next); 119 i--; 120 } 121 delete_cell = *p_pointer; 122 pop_data = delete_cell->value; 123 *p_pointer = delete_cell->next; 124 free((void *)delete_cell); 125 return pop_data; 126}
入力例として
(1.7 + 2.8) * (2.5 - 4.7) + (-1)
を計算する場合は
1.7 2.8 + 2.5 4.7 - * -0.1 +
を入力しています。(最後の+の後にもスペースが入っています)
試作段階のスタックのみを使用したプログラム
c
1#include <stdio.h> 2#include <stdlib.h> 3 4#define STACK_SIZE 8 5 6float stack[STACK_SIZE]; 7int sp = 0; 8 9int Push(float data); 10int Pop(float *data); 11int PostfixNotation(char pnData_c[STACK_SIZE]); 12 13int main(){ 14 char pnData[64]; 15 float ans = 0; 16 17 printf("input data(input space after number and operator)\n"); 18 scanf("%[^\n]%*c", &pnData); 19 20 PostfixNotation(pnData); 21 22 Pop(&ans); 23 printf("ans : %.2f\n", ans); 24 25 return 0; 26} 27 28int Push(float data){ 29 if(sp >= STACK_SIZE){ 30 return 0; 31 }else{ 32 stack[sp] = data; 33 sp++; 34 return 1; 35 } 36} 37 38int Pop(float *data){ 39 if(sp <= 0){ 40 return 0; 41 }else{ 42 sp--; 43 *data = stack[sp]; 44 return 1; 45 } 46} 47 48int PostfixNotation(char pnData_c[STACK_SIZE]){ 49 char temp[8] = ""; 50 int i = 0, j = 0; 51 float pnData_f, first = 0, second = 0; 52 while(pnData_c[i] != '\0'){ 53 if(pnData_c[i] == ' '){ 54 if(pnData_c[i - 1] == '+'){ 55 Pop(&second); 56 Pop(&first); 57 Push(first + second); 58 }else if(pnData_c[i - 1] == '-'){ 59 Pop(&second); 60 Pop(&first); 61 Push(first - second); 62 }else if(pnData_c[i - 1] == '*'){ 63 Pop(&second); 64 Pop(&first); 65 Push(first * second); 66 }else if(pnData_c[i - 1] == '/'){ 67 Pop(&second); 68 Pop(&first); 69 Push(first / second); 70 }else{ 71 pnData_f = atof(temp); 72 Push(pnData_f); 73 } 74 j = 0; 75 i++; 76 for(int k = 0; k < STACK_SIZE; k++){ 77 temp[k] = '\0'; 78 } 79 } 80 temp[j] = pnData_c[i]; 81 j++; 82 i++; 83 } 84}
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/08/06 05:57
2020/08/06 09:49
2020/08/07 20:38