ページ 1 / 1
テキストファイルの計算式を読み込無方法
Posted: 2017年6月07日(水) 13:52
by ki
はじめまして。
2+3などの計算式が書いてあるテキストファイルを読みこんで1行目に読み込んだ式、2行目に計算結果を表示したいのですが、
どうしていいのかわかりません。
どなたかご教授いただけませんでしょうか。
Re: テキストファイルの計算式を読み込無方法
Posted: 2017年6月07日(水) 14:23
by かずま
ki さんが書きました:はじめまして。
2+3などの計算式が書いてあるテキストファイルを読みこんで1行目に読み込んだ式、2行目に計算結果を表示したいのですが、
どうしていいのかわかりません。
計算のほうは引き受けますから、まずテキストファイルを 1行読み込む部分のプログラムを提示してください。
Re: テキストファイルの計算式を読み込無方法
Posted: 2017年6月07日(水) 14:34
by ki
初学者なのでこれでいいのか不確かですが、よろしくお願いいたします。
#include <stdio.h>
#include <stdlib.h>
#define MAX_STRINGS 80
void main(void)
{
char filename[] = "data.txt";
FILE *fp;
char data[MAX_STRINGS];
/* ファイル・オープン */
if ((fp = fopen(filename, "r")) == NULL)
{
printf("ファイル「%s」のオープンに失敗しました。プログラムを終了します。\n", filename);
exit(1);
}
/* データ処理 */
while (fgets(data, MAX_STRINGS, fp) != NULL)
{
printf("%s", data);
}
/* ファイル・クローズ */
fclose(fp);
Re: テキストファイルの計算式を読み込無方法
Posted: 2017年6月07日(水) 15:14
by かずま
ソースプログラムを貼り付けるときは、codeタグを使ってほしかった。
フォーラムルールをよく読んでください。お願いします。
さて、計算部分ですが、ちょっと謎めいた書き方をしています。
これを解読して、普通の書き方に直して、返信に貼り付けてください。
コード:
#include <stdio.h> // printf, fopen, fclose, fgets
#include <stdlib.h> // strtod, exit
#include <ctype.h> // isspace, isdigit
#include <math.h> // pow
#define MAX_STRINGS 80
unsigned char c;
const char *p, o[] = "+-*/^^";
int get(void) { do c = *p++; while (isspace(c)); return c; }
double expr(const char *b)
{
double v;
if (*b)
for (v = expr(b+2); c == b[0] || c == b[1]; )
c == '+' ? v += expr(b+2) :
c == '-' ? v -= expr(b+2) :
c == '*' ? v *= expr(b+2) :
c == '/' ? v /= expr(b+2) : (v = pow(v, expr(b)));
else
get() == '.' || isdigit(c) ? v = strtod(p-1, (char**)&p), get() :
c == '(' ? v = expr(o), c == ')' ? get() : (c = 1) :
c == '+' ? v = expr(b) :
c == '-' ? v = -expr(b) :
(v = c = 1);
return v;
}
int calc(const char *s, double *v) { return p = s, *v = expr(o), c; }
int main(void)
{
char filename[] = "data.txt";
FILE *fp;
char data[MAX_STRINGS];
if ((fp = fopen(filename, "r")) == NULL) { /* ファイル・オープン */
printf("ファイル「%s」のオープンに失敗しました。プログラムを終了します。\n", filename);
exit(1);
}
while (fgets(data, MAX_STRINGS, fp) != NULL) { /* データ処理 */
double val;
printf("%s", data);
if (calc(data, &val))
printf(" error\n");
else
printf(" %.15g\n", val);
}
fclose(fp); /* ファイル・クローズ */
return 0;
}
data.txt
コード:
2+3
1 + 2*(3-4)/5
355/113
2^3^2
4**5
実行結果
コード:
2+3
5
1 + 2*(3-4)/5
0.6
355/113
3.14159292035398
2^3^2
512
4**5
error
Re: テキストファイルの計算式を読み込無方法
Posted: 2017年6月07日(水) 15:45
by ki
フォーラムルールの件、申し訳ございません。
しばらく考えましたが、特にfor文の中が難しくて理解できませんでした・・・
Re: テキストファイルの計算式を読み込無方法
Posted: 2017年6月07日(水) 16:18
by かずま
ki さんが書きました:しばらく考えましたが、特にfor文の中が難しくて理解できませんでした・・・
コード:
for (v = expr(b+2); c == b[0] || c == b[1]; )
if (c == '+')
v += expr(b+2);
else if (c == '-')
v -= expr(b+2);
else if (c == '*')
v *= expr(b+2);
else if (c == '/')
v /= expr(b+2);
else
v = pow(v, expr(b));
これなら分かりますか?
Re: テキストファイルの計算式を読み込無方法
Posted: 2017年6月08日(木) 18:50
by かずま
三項演算子の ? : が難しいのではなく、expr(b+2) って何?
ということでしょうか?
式が "2+3" だとして、ちょっと考えてみましょう。
double expr(const char *b) が expr("+-*/^^") で呼び出されると、
b は "+-*/^^" を指すので、b+2 は "*/^^" を指します。
expr("*/^^") で呼び出されると、次は、expr("^^") で呼び出します。
expr("^^") で呼び出されると、次は、expr("") で呼び出します。
expr("") で呼び出されると、for文に行かず、else に行って、
get() で式から 1文字読み出し、それが数字だったら、strtod() で
値に変換し、v に入れます。v は 2 です。次の get() で後続の
演算子 '+' を c に入れて、expr からリターンします。
expr("^^") の for文に戻りますが、c が '^' ではないので戻ります。
expr("*/^^") の for文に戻りますが、c が '*', '/' ではないので戻ります。
expr("++*/^^") の for文に戻りますが、c が '+' なので、その + の
第二項である expr("*/^^") の値 3 を取得して、最初の値に足します。
v は 5 になります。
c には文字列の末尾の '\0' が入っていて、これで正常終了です。
納得していただけますか?
面白いと思いませんか?