回答編集履歴

2

内部表現イメージ図追加

2019/02/23 05:35

投稿

jimbe
jimbe

スコア12659

test CHANGED
@@ -8,6 +8,12 @@
8
8
 
9
9
  数値の取り出し部分では, 少数点が複数ある等の異常状態も無視しております.
10
10
 
11
+
12
+
13
+ 式の内部表現は以下のようなイメージになります.
14
+
15
+ ![CH(C0.8H0.2)2O のイメージ図](a364c6bbf60a9bb1451f52dc39c04430.png)
16
+
11
17
  ```C
12
18
 
13
19
  #include <stdio.h>

1

コード追加

2019/02/23 05:35

投稿

jimbe
jimbe

スコア12659

test CHANGED
@@ -1 +1,245 @@
1
- 少数点以下一桁~二桁程度でしたら, 計算を全て 100 倍で行って, 最後に 1/100 にするのは如何でしょうか.
1
+ ~~少数点以下一桁~二桁程度でしたら, 計算を全て 100 倍で行って, 最後に 1/100 にするのは如何でしょうか.~~
2
+
3
+
4
+
5
+ java で書いたものを移植する形で書いてみました.
6
+
7
+ メモリの大きさ等あちこち危ない作りですので, あまり長い式を計算しようとすると落ちると思います.
8
+
9
+ 数値の取り出し部分では, 少数点が複数ある等の異常状態も無視しております.
10
+
11
+ ```C
12
+
13
+ #include <stdio.h>
14
+
15
+ #include <stdlib.h>
16
+
17
+ #include <string.h>
18
+
19
+
20
+
21
+ typedef struct Material {
22
+
23
+ int type; //0=Atom, 1=Molecule
24
+
25
+ } Material_t;
26
+
27
+
28
+
29
+ typedef struct Atom {
30
+
31
+ int material_type; //0=Atom, 1=Molecule
32
+
33
+ char name[4]; //2文字+'\0'
34
+
35
+ int weight;
36
+
37
+ } Atom_t;
38
+
39
+ Atom_t atoms[] = {
40
+
41
+ { 0, "H", 1 },
42
+
43
+ { 0, "C", 12 },
44
+
45
+ { 0, "O", 16 },
46
+
47
+ {-1, "", -1 } //EOD
48
+
49
+ };
50
+
51
+ Atom_t *search_atom(char *name) {
52
+
53
+ Atom_t *p;
54
+
55
+ for(p=atoms; p->weight>0; p++) {
56
+
57
+ if(strcmp(p->name, name) == 0) return p;
58
+
59
+ }
60
+
61
+ return NULL; //無し
62
+
63
+ }
64
+
65
+
66
+
67
+ typedef struct MaterialValue {
68
+
69
+ Material_t *material; //Atom or Molecule
70
+
71
+ double ratio;
72
+
73
+ } MaterialValue_t;
74
+
75
+
76
+
77
+ typedef struct Molecule {
78
+
79
+ int material_type; //0=Atom, 1=Molecule
80
+
81
+ int materials_count;
82
+
83
+ MaterialValue_t materials[16]; //大きさはテキトウ
84
+
85
+ } Molecule_t;
86
+
87
+ Molecule_t *newMolecule() {
88
+
89
+ Molecule_t *molecule = (Molecule_t *)malloc(sizeof(Molecule_t));
90
+
91
+ molecule->material_type = 1;
92
+
93
+ molecule->materials_count = 0;
94
+
95
+ return molecule;
96
+
97
+ }
98
+
99
+ void add(Molecule_t *molecule, Material_t *material) {
100
+
101
+ MaterialValue_t *mv = &(molecule->materials[molecule->materials_count++]);
102
+
103
+ mv->material = material;
104
+
105
+ mv->ratio = 1.0;
106
+
107
+ }
108
+
109
+ void setRatio(Molecule_t *molecule, double ratio) {
110
+
111
+ molecule->materials[molecule->materials_count-1].ratio = ratio;
112
+
113
+ }
114
+
115
+ double getWeight(Molecule_t *molecule) {
116
+
117
+ int i;
118
+
119
+ double weight = 0;
120
+
121
+ for(i=0; i<molecule->materials_count; i++) {
122
+
123
+ MaterialValue_t *mv = &molecule->materials[i];
124
+
125
+ if(mv->material->type == 0) { //Atom
126
+
127
+ weight += ((Atom_t *)(mv->material))->weight * mv->ratio;
128
+
129
+ } else { //Molecule
130
+
131
+ weight += getWeight((Molecule_t *)(mv->material)) * mv->ratio;
132
+
133
+ }
134
+
135
+ }
136
+
137
+ return weight;
138
+
139
+ }
140
+
141
+
142
+
143
+
144
+
145
+ //スタック
146
+
147
+ Molecule_t *stack[16]; //大きさはテキトウ
148
+
149
+ int stack_pointer = 0;
150
+
151
+ void stack_push(Molecule_t *molecule) {
152
+
153
+ stack[stack_pointer++] = molecule;
154
+
155
+ }
156
+
157
+ Molecule_t *stack_pop() {
158
+
159
+ return stack[--stack_pointer];
160
+
161
+ }
162
+
163
+ Molecule_t *stack_peek() {
164
+
165
+ return stack[stack_pointer-1];
166
+
167
+ }
168
+
169
+
170
+
171
+ //解析
172
+
173
+ int isDigit(char c) {
174
+
175
+ return ('0' <= c && c <= '9');
176
+
177
+ }
178
+
179
+ int isDigitOrPeriod(char c) {
180
+
181
+ return (isDigit(c) || c == '.');
182
+
183
+ }
184
+
185
+ Molecule_t *parse(char *samplename) {
186
+
187
+ int i, j, k;
188
+
189
+ char v[16]; //大きさはテキトウ
190
+
191
+ stack_push(newMolecule());
192
+
193
+ for(i=0; i<strlen(samplename); i++) {
194
+
195
+ memset(v, 0, sizeof(v));
196
+
197
+ v[0] = samplename[i];
198
+
199
+ if(isDigit(v[0])) {
200
+
201
+ for(j=i+1, k=1; j<strlen(samplename) && isDigitOrPeriod(samplename[j]); k++, j++, i++) {
202
+
203
+ v[k] = samplename[j];
204
+
205
+ }
206
+
207
+ setRatio(stack_peek(), atof(v));
208
+
209
+ } else if(strcmp(v, "(") == 0) {
210
+
211
+ stack_push(newMolecule());
212
+
213
+ } else if(strcmp(v, ")") == 0) {
214
+
215
+ Material_t *material = (Material_t *)stack_pop();
216
+
217
+ add(stack_peek(), material);
218
+
219
+ } else {
220
+
221
+ add(stack_peek(), (Material_t *)search_atom(v));
222
+
223
+ }
224
+
225
+ }
226
+
227
+ return stack_pop();
228
+
229
+ }
230
+
231
+
232
+
233
+ int main(int argc, char *argv[]) {
234
+
235
+ printf("CO2=%f\n", getWeight(parse("CO2")));
236
+
237
+ printf("(CH3)2CO=%f\n", getWeight(parse("(CH3)2CO")));
238
+
239
+ printf("CH(C0.8H0.2)2O=%f\n", getWeight(parse("CH(C0.8H0.2)2O")));
240
+
241
+ return 0;
242
+
243
+ }
244
+
245
+ ```