回答編集履歴

3

ast

2018/09/08 11:56

投稿

yumetodo
yumetodo

スコア5850

test CHANGED
@@ -127,3 +127,19 @@
127
127
 
128
128
 
129
129
  も参考に
130
+
131
+
132
+
133
+ ---
134
+
135
+
136
+
137
+ 追記
138
+
139
+
140
+
141
+ なんか他の方がもうほぼそのまま答えのを貼ってしまっている状況で自重しても仕方ないので貼っておきます。ASTをunionとかでもうちょっとうまくやれば演算子の優先順位とかとかも作れます。
142
+
143
+
144
+
145
+ [https://wandbox.org/permlink/p1BzBKX3YSdDUgBq](https://wandbox.org/permlink/p1BzBKX3YSdDUgBq)

2

cio

2018/09/08 11:56

投稿

yumetodo
yumetodo

スコア5850

test CHANGED
@@ -119,3 +119,11 @@
119
119
 
120
120
 
121
121
  のようにパースすることが可能です。
122
+
123
+
124
+
125
+ [C言語で安全に標準入力から数値を取得](https://qiita.com/yumetodo/items/238751b879c09b56234b)
126
+
127
+
128
+
129
+ も参考に

1

strtol

2018/09/03 21:11

投稿

yumetodo
yumetodo

スコア5850

test CHANGED
@@ -1 +1,121 @@
1
1
  なんかstrtokとかatoiとかいう声が聞こえていますが、どれも使い勝手が今ひとつだったりエラー捕捉に難があるので、strtol系関数を使いましょう。
2
+
3
+
4
+
5
+ ---
6
+
7
+
8
+
9
+ `strtol`系関数は、概ね
10
+
11
+
12
+
13
+ ```c
14
+
15
+ long int strtol(const char *nptr, char **endptr, int base);
16
+
17
+ ```
18
+
19
+
20
+
21
+ のような宣言になっているわけですが、`nptr`に渡された文字列の先頭から、数値に変換可能な位置までを数値に変換します。そして`endptr`がNULLポインタではないならば、`*endptr`に変換可能でなくなった位置へのポインタを書き込みます。
22
+
23
+
24
+
25
+ 例えば
26
+
27
+
28
+
29
+ ```c
30
+
31
+ "3+4";
32
+
33
+ ```
34
+
35
+
36
+
37
+ という文字列があったとき、これをstrtol系関数にわたすと`endptr`には`+`の部分を指すポインタが書き込まれます。
38
+
39
+
40
+
41
+ これを利用すると
42
+
43
+
44
+
45
+ ```c
46
+
47
+ #include <stdio.h>
48
+
49
+ #include <math.h>
50
+
51
+ #include <stdlib.h>
52
+
53
+ #include <errno.h>
54
+
55
+ #include <ctype.h>
56
+
57
+
58
+
59
+ void parse(const char* str){
60
+
61
+ char* endptr1 = NULL;
62
+
63
+ errno = 0;
64
+
65
+ const int l = (int)strtol(str, &endptr1, 10);
66
+
67
+ if(errno != 0 || (0 == l && endptr1 == str)) exit(1);
68
+
69
+ const char* op = endptr1;
70
+
71
+ for(;isspace(*op); ++op);
72
+
73
+ const char* r_str = op + 1;
74
+
75
+ for(;isspace(*r_str); ++r_str);
76
+
77
+ char* endptr2 = NULL;
78
+
79
+ const int r = (int)strtol(r_str, &endptr2, 10);
80
+
81
+ if(errno != 0 || (0 == l && endptr2 == str)) exit(1);
82
+
83
+ printf(
84
+
85
+ "input: %s\n"
86
+
87
+ "left: %d\n"
88
+
89
+ "op: %c\n"
90
+
91
+ "right: %d\n",
92
+
93
+ str, l, *op, r
94
+
95
+ );
96
+
97
+ }
98
+
99
+ int main(void)
100
+
101
+ {
102
+
103
+ parse("3+4");
104
+
105
+ parse("3-4");
106
+
107
+ parse("3 + 4");
108
+
109
+ return 0;
110
+
111
+ }
112
+
113
+ ```
114
+
115
+
116
+
117
+ [https://wandbox.org/permlink/RrMVCnLKt4oT7GKo](https://wandbox.org/permlink/RrMVCnLKt4oT7GKo)
118
+
119
+
120
+
121
+ のようにパースすることが可能です。