teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

ast

2018/09/08 11:56

投稿

yumetodo
yumetodo

スコア5852

answer CHANGED
@@ -62,4 +62,12 @@
62
62
 
63
63
  [C言語で安全に標準入力から数値を取得](https://qiita.com/yumetodo/items/238751b879c09b56234b)
64
64
 
65
- も参考に
65
+ も参考に
66
+
67
+ ---
68
+
69
+ 追記
70
+
71
+ なんか他の方がもうほぼそのまま答えのを貼ってしまっている状況で自重しても仕方ないので貼っておきます。ASTをunionとかでもうちょっとうまくやれば演算子の優先順位とかとかも作れます。
72
+
73
+ [https://wandbox.org/permlink/p1BzBKX3YSdDUgBq](https://wandbox.org/permlink/p1BzBKX3YSdDUgBq)

2

cio

2018/09/08 11:56

投稿

yumetodo
yumetodo

スコア5852

answer CHANGED
@@ -58,4 +58,8 @@
58
58
 
59
59
  [https://wandbox.org/permlink/RrMVCnLKt4oT7GKo](https://wandbox.org/permlink/RrMVCnLKt4oT7GKo)
60
60
 
61
- のようにパースすることが可能です。
61
+ のようにパースすることが可能です。
62
+
63
+ [C言語で安全に標準入力から数値を取得](https://qiita.com/yumetodo/items/238751b879c09b56234b)
64
+
65
+ も参考に

1

strtol

2018/09/03 21:11

投稿

yumetodo
yumetodo

スコア5852

answer CHANGED
@@ -1,1 +1,61 @@
1
- なんかstrtokとかatoiとかいう声が聞こえていますが、どれも使い勝手が今ひとつだったりエラー捕捉に難があるので、strtol系関数を使いましょう。
1
+ なんかstrtokとかatoiとかいう声が聞こえていますが、どれも使い勝手が今ひとつだったりエラー捕捉に難があるので、strtol系関数を使いましょう。
2
+
3
+ ---
4
+
5
+ `strtol`系関数は、概ね
6
+
7
+ ```c
8
+ long int strtol(const char *nptr, char **endptr, int base);
9
+ ```
10
+
11
+ のような宣言になっているわけですが、`nptr`に渡された文字列の先頭から、数値に変換可能な位置までを数値に変換します。そして`endptr`がNULLポインタではないならば、`*endptr`に変換可能でなくなった位置へのポインタを書き込みます。
12
+
13
+ 例えば
14
+
15
+ ```c
16
+ "3+4";
17
+ ```
18
+
19
+ という文字列があったとき、これをstrtol系関数にわたすと`endptr`には`+`の部分を指すポインタが書き込まれます。
20
+
21
+ これを利用すると
22
+
23
+ ```c
24
+ #include <stdio.h>
25
+ #include <math.h>
26
+ #include <stdlib.h>
27
+ #include <errno.h>
28
+ #include <ctype.h>
29
+
30
+ void parse(const char* str){
31
+ char* endptr1 = NULL;
32
+ errno = 0;
33
+ const int l = (int)strtol(str, &endptr1, 10);
34
+ if(errno != 0 || (0 == l && endptr1 == str)) exit(1);
35
+ const char* op = endptr1;
36
+ for(;isspace(*op); ++op);
37
+ const char* r_str = op + 1;
38
+ for(;isspace(*r_str); ++r_str);
39
+ char* endptr2 = NULL;
40
+ const int r = (int)strtol(r_str, &endptr2, 10);
41
+ if(errno != 0 || (0 == l && endptr2 == str)) exit(1);
42
+ printf(
43
+ "input: %s\n"
44
+ "left: %d\n"
45
+ "op: %c\n"
46
+ "right: %d\n",
47
+ str, l, *op, r
48
+ );
49
+ }
50
+ int main(void)
51
+ {
52
+ parse("3+4");
53
+ parse("3-4");
54
+ parse("3 + 4");
55
+ return 0;
56
+ }
57
+ ```
58
+
59
+ [https://wandbox.org/permlink/RrMVCnLKt4oT7GKo](https://wandbox.org/permlink/RrMVCnLKt4oT7GKo)
60
+
61
+ のようにパースすることが可能です。