実現したいこと
30 5
この文字列を
足し算して35と出力したい
エラー
30+5と出力されてしまう
該当のソースコード
c
1int main(void){ 2 char str[] = "30 5"; 3 4 str[2] = '+'; 5 int tashizan = atoi(str); 6 7 return 0; 8}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答6件
0
なんかstrtokとかatoiとかいう声が聞こえていますが、どれも使い勝手が今ひとつだったりエラー捕捉に難があるので、strtol系関数を使いましょう。
strtol
系関数は、概ね
c
1long int strtol(const char *nptr, char **endptr, int base);
のような宣言になっているわけですが、nptr
に渡された文字列の先頭から、数値に変換可能な位置までを数値に変換します。そしてendptr
がNULLポインタではないならば、*endptr
に変換可能でなくなった位置へのポインタを書き込みます。
例えば
c
1"3+4";
という文字列があったとき、これをstrtol系関数にわたすとendptr
には+
の部分を指すポインタが書き込まれます。
これを利用すると
c
1#include <stdio.h> 2#include <math.h> 3#include <stdlib.h> 4#include <errno.h> 5#include <ctype.h> 6 7void parse(const char* str){ 8 char* endptr1 = NULL; 9 errno = 0; 10 const int l = (int)strtol(str, &endptr1, 10); 11 if(errno != 0 || (0 == l && endptr1 == str)) exit(1); 12 const char* op = endptr1; 13 for(;isspace(*op); ++op); 14 const char* r_str = op + 1; 15 for(;isspace(*r_str); ++r_str); 16 char* endptr2 = NULL; 17 const int r = (int)strtol(r_str, &endptr2, 10); 18 if(errno != 0 || (0 == l && endptr2 == str)) exit(1); 19 printf( 20 "input: %s\n" 21 "left: %d\n" 22 "op: %c\n" 23 "right: %d\n", 24 str, l, *op, r 25 ); 26} 27int main(void) 28{ 29 parse("3+4"); 30 parse("3-4"); 31 parse("3 + 4"); 32 return 0; 33}
https://wandbox.org/permlink/RrMVCnLKt4oT7GKo
のようにパースすることが可能です。
も参考に
追記
なんか他の方がもうほぼそのまま答えのを貼ってしまっている状況で自重しても仕方ないので貼っておきます。ASTをunionとかでもうちょっとうまくやれば演算子の優先順位とかとかも作れます。
投稿2018/09/03 14:11
編集2018/09/08 11:56総合スコア5850
0
ベストアンサー
2個だけでなく、10 個以下の数字までを足し算できるようにしてみました。
calc.c
c
1#include <stdio.h> 2#include <stdlib.h> 3#include <limits.h> 4 5int str_to_nums(char* str, int* nums) { 6 char* start_p = str; 7 char* end_p = str; 8 int count = 0; 9 10 while (*end_p) { 11 long n = strtol(start_p, &end_p, 10); 12 if (start_p == end_p) { 13 puts("数値に変換できませんでした"); 14 return -1; 15 } 16 if (n > INT_MAX || n < INT_MIN) { 17 puts("int型には変換できません"); 18 return -1; 19 } 20 nums[count++] = n; 21 start_p = end_p; 22 // printf("count %d, n %d\n", count, nums[count - 1]); 23 } 24 return count; 25} 26 27 28int main(void) { 29 char* strs[] = { 30 " 30 5", 31 " 1 2 3 4" 32 }; 33 34 int nums[10]; 35 str_to_nums(strs[0], nums); 36 printf("'%s' -> %d\n", strs[0], nums[0] + nums[1]); 37 38 int count = str_to_nums(strs[1], nums); 39 int sum = 0; 40 for (int i = 0; i < count; i++) { 41 sum += nums[i]; 42 } 43 printf("'%s' -> %d\n", strs[1], sum); 44 45 return 0; 46}
投稿2018/09/08 10:26
総合スコア22324
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
既に関数を用いる方法は他の方々が回答されているので、私からは地道な手法の提案を。
1.一般的に使用される計算式(中置記法)を逆ポーランド記法に変換
2.ポーランド記法を元に演算
というのはいかがでしょう。
2.の演算部分はこんな感じになるかと。
C
1// 逆ポーランド記法の計算 2int calc_rpn(char *s) 3{ 4 int a, b, n; 5 6 while (*s) { 7 8 // 数値の場合はスタックに積む 9 if (・・・) { 10 // TODO 取り出してスタックに積む 11 12 // オペランドの場合は計算する 13 } else { 14 switch (*s) { 15 case '+': 16 a = pop(); 17 b = pop(); 18 push(b+a); 19 break; 20 case '-': 21 a = pop(); 22 b = pop(); 23 push(b-a); 24 break; 25 case '*': 26 a = pop(); 27 b = pop(); 28 push(b*a); 29 break; 30 case '/': 31 a = pop(); 32 b = pop(); 33 if (a == 0) break; 34 push(b/a); 35 break; 36 case '%': 37 a = pop(); 38 b = pop(); 39 if (a == 0) break; 40 push(b%a); 41 } 42 s++; 43 } 44 } 45 return pop(); 46}
投稿2018/09/04 14:02
総合スコア118
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
sscanf()関数を用いる方法もあります。
C
1#include <stdio.h> 2 3int main(void){ 4 char str[] = "30 5"; 5 int n; 6 int m; 7 8 if (sscanf(str, "%d %d", &n, &m) != 2){ 9 return 1; 10 } 11 12 printf("%d + %d = %d\n", n, m, n + m); 13 14 return 0; 15} 16
投稿2018/09/04 10:32
総合スコア113
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/09/06 05:54
2018/09/08 09:22 編集
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/09/03 17:57 編集
2018/09/04 01:54
退会済みユーザー
2018/09/04 13:28 編集
2018/09/04 13:40