四則演算プログラムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Justy

Re:無題

#101

投稿記事 by Justy » 18年前

ちなみに上記条件を実行するには字句解析いう方法
 どっちかというと構文解析になりますが、最終的には必要になりますね。
 これをやらないと計算順序がわからないので、正しく計算できません。
 
 今の二項演算レベルであれば、力業で解決できるとは思いますが。

@とんぷぅ~

Re:無題

#102

投稿記事 by @とんぷぅ~ » 18年前

Justyさんおはようございます。レスありがとうございました。

<今の二項演算レベルであれば、力業で解決できるとは思いますが。
力業とはどういうことでしょうか? 

Justy

Re:無題

#103

投稿記事 by Justy » 18年前

>力業とはどういうことでしょうか?
 ちょっとわかりにくかったですね。
 えーと、比喩的な表現でいろいろと意味があるのですが、ここでは
思いつくまま書いていくことを指しています。

 今回のケースですと、本来であれば二項演算の「式」はどういう文字の要素で成り立ち、
どういうルールで何の文字が現れるのかを正確に仕様化してプログラムを考えるのですが、
二項演算ほどシンプルなものであれば適当に「数字 演算子 数字」とだけ分かってれば
正負の単項演算や括弧が入ってきても、シンプルであるが故に仕様に基づいた構文解析とか
しなくても適当に対処できなくはないかな、ということです。

@とんぷぅ~

Re:無題

#104

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

<「数字 演算子 数字」とだけ分かってれば
<正負の単項演算や括弧が入ってきても、シンプルであるが故に仕様に基づいた構文解析とか
<しなくても適当に対処できなくはないかな、ということです。

う~んなんとなくおっしゃられていることは分かるんですが、なかなか
考えがまとまらないですね。今はopという変数に演算子を格納しているのですが
そこに括弧を格納し、switchなどで分岐させるのでしょうか?
はたまた括弧用の変数を用意した方がいいのでしょうか?

検討違いかもしれませんがよろしくお願いします。

Justy

Re:無題

#105

投稿記事 by Justy » 18年前

今はopという変数に演算子を格納しているのですが
 それはそれでいいと思いますよ。


そこに括弧を格納し、switchなどで分岐させるのでしょうか?
はたまた括弧用の変数を用意した方がいいのでしょうか?
 単項演算のみで考えた場合括弧は対応状態だけ
チェックして基本は無視でいいと思います。

 ちょっとサンプル作ってみました。
 括弧付きの正負の単項演算のみに対応したものです。
 つまり、"--(+(-(3)))"のようなものを解析します。

 parse_test()の中の test_expression_tbl[/url]の中にテスト用の
単項演算の式が複数入っています。
 この文字列を1つずつ parse()に引き渡して、正当な単項演算ができれば
1が戻り、失敗すれば 0が戻ります。

 この延長線上で考えれば二項演算も楽にできると思います。

@とんぷぅ~

Re:無題

#106

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございました。

サンプルプログラム拝見しました。初めに思ったのですが、
main関数の短さに驚きました。あれだけ短いと他の関数で
何の処理をしているのかがつかみ易いですね。それだけでも
大変勉強になりました。

ただ、サンプルいろいろと動かしてみたのですが、まだ実際どのように
すれば解析出来るのか見えてきません。括弧の対応状況を調べるというのは
例えばopに'('が入っていたら')'と対応しているか調べるということですよね?

なお今現在管理人さんのサンプルを下に、opには演算子(0~9以外の文字)
をopに格納するようにしているのですが、その条件に'(' ')'を加えればよいの
でしょうか?もし加えた場合、演算子が上書きされてしまわないでしょうか?

質問ばかりですみません。よろしくお願いします。

Justy

Re:無題

#107

投稿記事 by Justy » 18年前

>あれだけ短いと他の関数で 何の処理をしているのかがつかみ易いですね
 私の場合、普通仕事で書く場合 main関数は数行しかないです。
 他の人を見ても、どんなに大きなプログラムでも概ね多くてmain関数は十数行程度ですね。


>まだ実際どのように すれば解析出来るのか見えてきません
 parse関数が二項演算「因子 演算子 因子」でいうところの因子の演算を
行うものであるのはわかりますよね?

 そして parse関数の第二引数はどこまで解析が終わったか(正確には未解析の文字列の先頭)を返すことが
できるように設計されています。


 この二点から、まず解析したい文字列を parse()にかけて
正常に因子の計算ができたことを確認し、解析が終わった文字列から演算子(+-*/)
を取り出します(opにでも代入しておくといいでしょう)。
 で、その次の文字からを再度 parse関数にかけてあげれば2つ目の数値が取り出せます。
 
(実際にはこのサンプルの仕様上、parse関数は未解析の文字列の先頭が NUL文字であることを
確認しているので、このチェックを外さなければなりませんが)

 従って、サンプルの parse関数を使うのであれば、もう解析の為の whileループは不要です。


>その条件に'(' ')'を加えればよいの でしょうか?
 いいえ、全て parse関数が処理しています。
 main関数が行わなければならないのは parse関数への引数と戻り値の管理と
演算子の管理、そして実際の計算だけとなります。

@とんぷぅ~

Re:無題

#108

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

>parse関数が二項演算「因子 演算子 因子」でいうところの因子の演算を
>行うものであるのはわかりますよね?

正直な所、因子の演算という意味がよく理解できません。

申し訳ありません。Justyさんのおっしゃられていることが理解出来ません。
大変丁寧な説明だと思うのですが、私の知識では理解出来ませんでした。

parse()にかけてというのは、引数を渡すということなのでしょうか?
parse(const char *expression, const char **end, int *pValue)となっていますが
どのようにすればいいのか分かりません。skipやfactorもどんな方に処理すればよいのかも分かりません。
 
>もう解析の為の whileループは不要です
while ( st != '\0' ) {
		if ( ! ( st >= '0' && st <= '9' ) && i != 0 ) {
			op = st;		
			st = '\0';	
			lop = atoi ( st );
			rop = atoi ( &st[i+1] );
			break;
		}
		i++;
	}

この部分でしょうか?

Justy

Re:無題

#109

投稿記事 by Justy » 18年前

正直な所、因子の演算という意味がよく理解できません。
 二項演算というのはわかりますか?
 二つの数と演算子を元に、新たな数を導く計算のことです。
 四則演算なら例えば「1 + 1」とか「5 * 4」のように「数字 演算子 数字」の
ような形になります。

 因子というのはここでいう数字の部分に相当します。
 数字と書かなかったのは数字だけがここに来るとは限らないので、因子と書きました。
 例えば「-(+(-5)) / +++(3) 」であれば2つの因子とはそれぞれ「-(+(-5))」と「+++(3)」を指します。

 parse関数はこの 「-(+(-5))」や「+++(3)」の文字列を解析して、
int型のデータに変換する機能を持っています。


parse()にかけてというのは、引数を渡すということなのでしょうか?
 そうです。


parse(const char *expression, const char **end, int *pValue)となっていますが
どのようにすればいいのか分かりません。skipやfactorもどんな方に処理すればよいのかも分かりません。
 使うのは基本的には parse関数だけでいいのですが、ひょっとしてサンプルが何をしているのも
わからなかったのでしょうか?

 parseの第一引数は解析したい「因子」となる文字列を指定します。
 第二引数は第一引数の文字列を「因子」としての解析が終了した直後の文字列の位置を
ポインタを経由して取得できます。
 第三引数は「因子」としての解析が成功したのなら結果がポインタを経由して取得できます。

 例を挙げますと以下のようなプログラムの場合
[color=#d0d0ff" face="monospace]    const char *p;
    int val;
    const char *expression = "-(--( 5 )) -4";
    parse(expression, &p, &val);
    printf("%d # %s\n", val, p);[/color]
 実行するとこのように表示されます。

[color=#d0d0ff" face="aria[/url]-5 # hdfghdfgh[/color]
 parse関数は valに -5を、pには 第一引数で指定した文字列の中で因子としての解析が終わった位置を戻しているので、
このように表示されます。

 では、こうしたらどうでしょうか。
[color=#d0d0ff" face="monospace]    const char *p;
    int val1, val2;
    const char *expression = "-(--( 5 )) -4";
    parse(expression, &p, &val1);
    parse(p, &p, &val2);
    printf("%d , %d\n", val1, val2);[/color]
 表示は
[color=#d0d0ff" face="aria[/url]-5 , -4[/color]
 になるはずです。

 1回目の parse解析で、expression内の文字列解析し、-5という値を出しています。
 そのとき、pは expression文字列の中の "-4"の部分を指しているポインタになっているので、
その pをそのまま parseにかけると2つ目の値 -4が取得しています。


 この説明でなんとなく掴めたでしょうか?

@とんぷぅ~

Re:無題

#110

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

説明して下さったおかげで因子については理解出来ました。

>基本的には parse関数だけでいいのですが
これはparse関数内で他の関数を呼び出しているから、parse関数を
呼び出せばいいという考え方でよいのでしょうか?

>ひょっとしてサンプルが何をしているのもわからなかったのでしょうか?

はい。すみません。実際はこんな処理をしているのかな~ということしか分かりませんでした。
ポインタが絡んでくるともう駄目になってしまい、本を見ながら解読していたので
すが、意味を理解することが出来ませんでした。

>この説明でなんとなく掴めたでしょうか?
先ほどよりは掴めてきました。ただ、なんとなくですが。。

結局のところ、変数opに括弧と演算子を格納することが出来る
ようになるということでしょうか?結論が今いち掴めないです。
理解力不足ですみません。

バグ

Re:無題

#111

投稿記事 by バグ » 18年前

ポインタは決して難しいものではありませんよ。
これは私が初めてポインタを理解できたような気がした時に頭に過ぎった例えです。
参考になるか分かりませんが、良かったら読んでみて下さい。



メモリを本だと考えて下さい。

アドレスをページだと考えて下さい。

その本に書かれている文章が変数や関数だと考えて下さい。

ポインタはその書かれた場所を指し示す栞だと考えて下さい。

栞は単体では意味を成しませんよね?

書物に挟む事で初めて意味を成すものです。


int nVal;
int* pPtr;

pPtr = &nVal;


これは、nValという変数が書かれているページにpPtrという栞を挟んだと考えればどうでしょう?
pPtrは栞でありながら、nValが書かれたページでもある訳です。


*pPtr = 10;


つまり、上記のような代入を行うと、pPtrが挟まれているページの内容を10に書き換えなさいという意味になる訳です。ですから、pPtrという栞を通して、間接的にnValを書き換える事になる訳です。

参考になればよいですが…(^_^;)

@とんぷぅ~

Re:無題

#112

投稿記事 by @とんぷぅ~ » 18年前

バグさん。レスありがとうございます。

<pPtrという栞を通して、間接的にnValを書き換える事になる訳です。

 確かに間接参照の考え方としては理解しやすいですね。
しかし、よく思いつきましたね。大変参考になりました!

ありがとうございました。

Justy

Re:無題

#113

投稿記事 by Justy » 18年前

 上司の方に説明する必要があるので、中身を理解する必要があるのは
わかるのですが、今は中身の処理より、結果に注目してください。
 つまり、parse()の中身は今は無視してください。


>parse関数を呼び出せばいいという考え方でよいのでしょうか?
 単項部分に限って言えば、Y


>変数opに括弧と演算子を格納することが出来る ようになるということでしょうか?
 N
 括弧を格納する必要はありません。


 先ほどのコードに手を加えてみました。
[color=#d0d0ff" face="monospace]    const char *p;
    int val;
    const char *expression = "-(--( 5 )) -4";
    parse(expression, &p, &val);
    printf("val = %d, p = %s\n", val, p);[/color]
 このコードの実行結果は
[color=#d0d0ff" face="aria[/url]val1 = -5, p = -4[/color]
 となります。
 さて、ここで注目なのは 1つ目の parseを実行し終わったところで文字列へのポインタ pは
"-4"を指しています。
 ということとは p[0]は '-'であり、p[1]='4'である、ということです。

 では、これをふまえて、expressionの式を二項演算に代えてみました。
[color=#d0d0ff" face="monospace]    const char *p;
    int val;
    const char *expression = "-(--( 5 )) * -4";
    parse(expression, &p, &val);
    printf("val = %d, p = %s\n", val, p);[/color]
 このコードだったらどうでしょう?
 この結果 pは何を指すと思いますか?

@とんぷぅ~

Re:無題

#114

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

理由はよく分かりませんが、たぶん-4を指すんだと思います。

Justy

Re:無題

#115

投稿記事 by Justy » 18年前

>理由はよく分かりませんが、たぶん-4を指すんだと思います。
 では実際にテストしてみて下さい。


# ところでこのままのペースで話を進めると、ある程度形になるまで
まだ相当な時間がかかりそうな気がするのですが・・・。
 先輩か上司の方に一度現状を見て貰って、状況とソースを整理してみてはどうでしょう?

@とんぷぅ~

Re:無題

#116

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

>では実際にテストしてみて下さい。

実行したら-4を指していました。

>ところでこのままのペースで話を進めると、ある程度形になるまで
>まだ相当な時間がかかりそうな気がするのですが・・・。
>先輩か上司の方に一度現状を見て貰って、状況とソースを整理してみてはどうでしょう?

はい。確かにそうですね。多桁は除いて、せめて括弧付きの計算が出来て
から確認を取りたいと思っています。う~んプログラムは難しいですね。。(( T_T)トボトボ

Justy

Re:無題

#117

投稿記事 by Justy » 18年前

>実行したら-4を指していました。
 あれ? おかしいですね。
 expressionは "-(--( 5 )) * -4"になっていますか?


>括弧付きの計算が出来てから確認を取りたいと思っています。
 期限とかないんですか?

@とんぷぅ~

Re:無題

#118

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

>expressionは "-(--( 5 )) * -4"になっていますか?
はい。なっております。
実行結果va = -5, p = * -4となりました。

>期限とかないんですか?
期限はとくにないです。早く出来れば出来るだけいいんでしょうけど。

Justy

Re:無題

#119

投稿記事 by Justy » 18年前

>実行結果va = -5, p = * -4となりました
 ですよね。
 ということは、この時の p[0]は '*'になるので、これをopに保存すれば、
正しく演算子を取得できるのではないでしょうか。

 で、再び、そのp[0]の次の文字p[1]からの文字列を再度 parseにかければ、
2つ目の数値が取り出せます。

@とんぷぅ~

Re:無題

#120

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

>で、再び、そのp[0]の次の文字p[1]からの文字列を再度 parseにかければ、
>2つ目の数値が取り出せます。

p++などで、n文字分進ませればいいんですよね?
そして今までのコードに組み込めばいいんでしょうか?

@とんぷぅ~

Re:無題

#121

投稿記事 by @とんぷぅ~ » 18年前

間違えました。Pの要素でした。

op = p;
i++;

こういうことですよね?

Justy

Re:無題

#122

投稿記事 by Justy » 18年前

>こういうことですよね?
 ですです。
 で、後は演算子が四則演算であるかチェックして、オーバーフローチェックもどこかに入れて
実際に計算すれば(中身を理解する作業は別にして)二項演算は終了です。

@とんぷぅ~

Re:無題

#123

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

組み込み方が分からずなんかテンパってきました。
この場合expressionをコマンドライン引数に置き換えてやればいいんですよね?

Justyさんのサンプルでparse_test以外を今までのソースに組み合わせればいいんですよね?

Justy

Re:無題

#124

投稿記事 by Justy » 18年前

>この場合expressionをコマンドライン引数に置き換えてやればいいんですよね?
 Y

>Justyさんのサンプルでparse_test以外を今までのソースに組み合わせればいいんですよね?
 Y

 parse関数に関しては、今の実装ですと終端が NUL文字であることをチェックして
1か 0か(成功したかどうか)を戻すようになっているので、その部分だけは
削った方がいいかと思います。

@とんぷぅ~

Re:無題

#125

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございました。

一応ソースを添付しておきます。
#pragma warning ( disable : 4996 )

#include  <stdio.h>
#include  <string.h>
#include  <stdlib.h>
#include  <limits.h>
#include  <math.h>
#include  <ctype.h>
#include  "calc.h"

/*----------------- 関数プロトタイプ宣言 -----------------*/

//	エラーメッセージ
void usage_err     ( int, char *[/url] );
void integer_err   ();
void int_over_err  ();
void operator_err  ();
void div_err	   ();
void over_flow_err ();

//	四則計算
long long add ( long long, long long );
long long sub ( long long, long long );
long long mul ( long long, long long );
long long did ( long long, long long );
long long mod ( long long, long long );


// NUL文字
#define ASCII_NUL				('\0')

// 式文字列のバッファサイズ
#define EXPRESSION_BUFF_SIZE	( 128 )

// 配列サイズ
#define ArraySize(array)		(sizeof(array)/sizeof(*(array)))

/*********************************************************************/

// 構文
//	factor      ::= integer | ('(' factor ')') | ('+' factor) | ('-' factor)
//	expression  ::= factor

// 空白をスキップ
static const char *skip_parce(const char *p)
{
	if(p)
	{
		while(isspace(*p))
			++p;
	}
	return p;
}


// 要素解析
static int parse_factor(const char **p, int *pValue)
{
	int c;
	
	// 空白をスキップ
	*p = skip_parce(*p);
	c = **p;
	
	if(isdigit(c))
	{
		char *end;
		*pValue = (int)strtol(*p, &end, 10);
		*p = end;
		return 1;
	}
	else
	if(c == '(')
	{
		++(*p);
		if(parse_factor(p, pValue))
		{
			*p = skip_parce(*p);
			if(**p == ')')
			{
				++*p;
				return 1;
			}
		}
	}
	else
	if(c == '-')
	{
		++(*p);
		if(parse_factor(p, pValue))
		{
			*pValue = -(*pValue);
			return 1;
		}
	}
	else
	if(c == '+')
	{
		++(*p);
		if(parse_factor(p, pValue))
			return 1;
	}
	return 0;		// 異常
}

// 解析
static int parse(const char *expression, const char **end, int *pValue)
{
	// NULLチェック
	if(expression && pValue)
	{
		// 要素解析
		const char *p = expression;
		if(parse_factor(&p, pValue))
		{
			// 解析が終了した文字列の位置を記録
			p = skip_parce(p);
			if(end)	*end = p;
		}
	}
	return 0;
}


/*********************************************************************/

/*-------- 受け取ったコマンドライン引数を配列strまとめる --------*/

void storage ( int argc, char *argv[/url], char st[128] )
{
	int i = 0, j = 0, s = 0;

	while ( ++i < argc ) {
		s = 0;
		while ( argv != '\0' ) {
			st[j] = ( argv );
			s++;
			j++;
		}
	}
	st[j]='\0';
}

/*----------------- main関数 -----------------*/

int main ( int argc, char *argv[/url] )
{
	long long  lop;			//	左オペランド
	long long  rop;			//	右オペランド
	long long  i = 0;		//	配列要素
	long long  n = 0;
	long long  surplus;		//	余り
	long long  result;		//	結果

	char  op;				//	演算子
	char  st[128];			//	コマンドライン引数を格納
	char  *check;			//	変換不能な文字列へのポインタを格納
	
	//	パラメータのチェック
	if ( argc <= 1 || argc >= 5 ) {
		usage_err ( argc, argv );
	}
	
	storage ( argc, argv, st );

	//	文字列のチェック
	while ( st != '\0' ) {
		if ( ! ( st >= '0' && st <= '9' ) && i != 0 ) {
			op = st;		
			st = '\0';	                                      
			lop = atoi ( st );
			rop = atoi ( &st[i+1] );
			break;
		}
		i++;
	}

	//	左オペランドのチェック
	strtol ( st, &check, 10 );
	if ( errno != ERANGE ) {
		if ( *check != '\0' )
			integer_err ();
	} else {
		int_over_err ();
	}

	//	右オペランドのチェック
	strtol ( &st[i+1], &check, 10 );
	if ( errno != ERANGE ) {
		if ( *check != '\0' )
			integer_err ();
	} else {
		int_over_err ();
	}

	switch ( op ) {
		case '+':
			result = add ( lop, rop );	
			break;
		case '-':	
			result = sub ( lop, rop );	
			break;
		case '*':	
			result = mul ( lop, rop );	
			break;
		case '/':	
			if ( rop == 0 )
				div_err ();
			
			//	除算のオーバーフローを考慮
			if ( ( lop == INT_MIN ) && ( rop == -1 ) )
				over_flow_err ();
			
			result  = did ( lop, rop );
			surplus = mod ( lop, rop );

			if ( surplus == 0 ) {
				printf ( "%lld %c %lld = %lld\n", lop, op, rop, result );
				exit   ( 0 );
			} else if ( surplus != 0 ) { 
				printf ( "%lld %c %lld = %lld 余り %lld\n", lop, op, rop, result, surplus );
				exit   ( 0 );
			}
			break;
		default:
			operator_err ();
	}

	//	加、減、乗算のオーバーフローを考慮
	if ( ( result > INT_MAX ) || ( result < INT_MIN ) )
		over_flow_err ();

	//	左オペランド、演算子、右オペランドの順に出力
	printf ( "%lld %c %lld = %lld\n", lop, op, rop, result );
	exit   ( 0 );
}


ソース部分で//文字列のチェックという部分を削り、//右オペランドのチェック
の上の部分でparse()関数を呼び出せばいいんですよね?

>終端が NUL文字であることをチェックして
>1か 0か(成功したかどうか)を戻すようになっているので
アドバイスありがとうございました。その部分については削除しました。

@とんぷぅ~

Re:無題

#126

投稿記事 by @とんぷぅ~ » 18年前

連レスすみません。
大変見にくいので添付ファイルにします。

Justy

Re:無題

#127

投稿記事 by Justy » 18年前

>ソース部分で//文字列のチェックという部分を削り、//右オペランドのチェック
>の上の部分でparse()関数を呼び出せばいいんですよね?
 そんなかんじですが、実際に呼び出したソースを見ないことにはなんとも。

@とんぷぅ~

Re:無題

#128

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

parse関数にstを渡したいのですが、型が違うため困っています。
このような場合は関数の型を変更すればよいのでしょうか?

Justy

Re:無題

#129

投稿記事 by Justy » 18年前

 第一引数ですよね?
 型が違うというのはstを第一引数に parse(st, ....)として渡せない、ということですか?
 何か警告かコンパイルエラーが出るのですか?

@とんぷぅ~

Re:無題

#130

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

間違いました。stは渡せました。
引数を指定してparse(st, &p, &val);
op = pと代入したのですが、上手くいきません。

引数の指定が間違っているのでしょうか?

Justy

Re:無題

#131

投稿記事 by Justy » 18年前

 iって何でしょう?
 parseが正常に行われたのなら、演算子は p[0]に入っているはずなのですが。

@とんぷぅ~

Re:無題

#132

投稿記事 by @とんぷぅ~ » 18年前

間違いました。すみませんp[0]に演算子が入っているのですが
計算自体できません。これはまだatoiで変換してないからなのですが、

例えば21 + (-5)という式があれば、valに21 pに+ (-5)がはいると思う
んですが、この時valとpをatoiで整数にするんでしょうか?

今までlopとopで表していたので、かなりごっちゃになってきました。
自分が理解出来ていないため、上手く質問することができず、ご迷惑
をおかけしますがよろしくお願いします。

Justy

Re:無題

#133

投稿記事 by Justy » 18年前

>これはまだatoiで変換してないからなのですが
 これは2つ目の数字の話ですか?


>この時valとpをatoiで整数にするんでしょうか?
 valとpをatoiで整数化ですか?
 ちょっと意味を掴みかねるのですが、2つ目の数字を取得したいということであれば
は pを使って再度 parseしてください。
 
2007/06/05(火) 16:22 投稿の2つ目のサンプルがどうなっていたかみればわかると思います。

@とんぷぅ~

Re:無題

#134

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございました。

アドバイスありがとうございます。なんとか出来ました!!! 

ソースを見て頂きたいのですが、main関数内のstrtolの部分を削ると上手く
いくのですが、削らないと上手くいかないのはparse_factor関数で判定している
からなのでしょうか?

ちなみに括弧を付けた式を入力したとき (-5) + 4 と入力すると
-5 + 4 = -1となってしまい、括弧が表示されません。
これは出力する際に条件を加えなくてはならないのでしょうか?

お忙しい中何度もすみません。

@とんぷぅ~

Re:無題

#135

投稿記事 by @とんぷぅ~ » 18年前

今テストしていたんですが、かなりバグがありました。
明らかにおかしいという部分の指摘をお願いします。

Justy

Re:無題

#136

投稿記事 by Justy » 18年前

>main関数内のstrtolの部分を削ると上手く いくのですが、
>削らないと上手くいかないのはparse_factor関数で判定している
 もうこのチェック方法ではだめですね。
 このチェックが int型変換時の intで扱える範囲を超えた場合に対するチェックであれば
parse_factor()内の strtol()を使っているところでチェックするといいでしょう。


>-5 + 4 = -1となってしまい、括弧が表示されません。
 それはそうでしょう。
 数値に変換したあとの lop/ropを使って printfしていますから。
 普通に文字列 stを表示すればいいのではないですか?


>今テストしていたんですが、かなりバグがありました。
>明らかにおかしいという部分の指摘をお願いします。

 parse()の戻り値をチェックしていない点でしょうか。
 因子に不正な文字が入っていてもそれを無視してしまっています。

 さらに parse()は元々成功したとき 1を返すようにしていましたが、
それがなくなっています。
(NUL文字チェックは削ってもいいのですが、1は戻すようにしてください)

@とんぷぅ~

Re:無題

#137

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

>このチェックが int型変換時の intで扱える範囲を超えた場合に対するチェックであれば
>parse_factor()内の strtol()を使っているところでチェックするといいでしょう。

了解しました。ありがとうございます。

>数値に変換したあとの lop/ropを使って printfしていますから。
>普通に文字列 stを表示すればいいのではないですか?

確かにその通りですね。固定観念はいけないですねw

>parse()の戻り値をチェックしていない点でしょうか。
>因子に不正な文字が入っていてもそれを無視してしまっています。

戻り値のチェックとはどういったことをすればよいのでしょうか?

Justy

Re:無題

#138

投稿記事 by Justy » 18年前

>戻り値のチェックとはどういったことをすればよいのでしょうか?
 2007/06/04(月) 18:14のソースは戻り値をチェックしています。
(先にも書きましたが、parse関数は成功したら 1を返すよう修正してください)

@とんぷぅ~

Re:無題

#139

投稿記事 by @とんぷぅ~ » 18年前

>先にも書きましたが、parse関数は成功したら 1を返すよう修正してください
すみませんでした。NULLチェックを省きました。

// 解析
static int parse(const char *expression, const char **end, long long *pValue)
{
// 要素解析
const char *p = expression;
if(parse_factor(&p, pValue))
{
// 解析が終了した文字列の位置を記録
p = skip_parce(p);
if(end) *end = p;

// 解析が終わってもう文字が残っていなければ成功
if(*p == ASCII_NUL)
return 1;
}
return 0;
}

こうでいいんですよね? ただ、減算、乗算、除算がうまくいきません。

Justy

Re:無題

#140

投稿記事 by Justy » 18年前

>NULLチェックを省きました。
 えーと、NUL文字チェックは削ってください。
 でもそこまで到達しているなら、1を返して下さい。

@とんぷぅ~

Re:無題

#141

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

>NUL文字チェックは削ってください。
削るというのは?上記ではおかしいのでしょうか?

>1を返して下さい。
return 1;の部分ではないのですか?

すみませんがよく理解出来ません。どういうことでしょうか?

Justy

Re:無題

#142

投稿記事 by Justy » 18年前

>削るというのは
 削除する、ということです。


>return 1;の部分ではないのですか?
 以前、NUL文字チェックを削ってください、と言ったとき、return 1まで削ってしまいました。
 で、return 1をしてくださいと言ったら、今度は削ったはずの NUL文字チェックが復活していました。
 なので、NUL文字チェックは削除した状態で、1を戻すようにしてください。

@とんぷぅ~

Re:無題

#143

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。
すみませんでした。これでOKですよね??
// 解析
static int parse(const char *expression, const char **end, long long *pValue)
{
  // 要素解析
  const char *p = expression;
    if(parse_factor(&p, pValue))
    {
    // 解析が終了した文字列の位置を記録
    p = skip_parce(p);
      if(end) *end = p;
      return 1;
    }
    return 0;
}

Justy

Re:無題

#144

投稿記事 by Justy » 18年前

>これでOKですよね
 OKです。これで終端が NUL文字じゃなくても成功として返すようになります。

@とんぷぅ~

Re:無題

#145

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

問題点がありまして、
①減算5 - 2等を行うと7という結果が出る。
②乗算1 * 1等を行うと正しく計算されず、over_flowのメッセージが出る。
③除算5 / 1等のを行うと0余り5という結果が出る。

①についてはropに演算子がくっついた状態になってしまっています。
②、③はropに-3689348814741910324という数が入ってしまいます。
どこがおかしいのでしょうか?

Justy

Re:無題

#146

投稿記事 by Justy » 18年前

>どこがおかしいのでしょうか?
 戻り値をチェックした上での話ですか?

 だとすると現状の最新のソースをビルドできる形で
出して頂かないと、なんとも・・・。

@とんぷぅ~

Re:無題

#147

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

>だとすると現状の最新のソースをビルドできる形で
>出して頂かないと、なんとも・・・。

了解しました。かなり見ずらいですがよろしくお願いします。

Justy

Re:無題

#148

投稿記事 by Justy » 18年前

 ちょっと時間がないので手短に。

・ parseの戻り値をチェックしてください。
 チェックして、問題があれば(0が戻ってきている)エラーとしてください。

・ 2回目の parse(ropの方)で、第一引数に pを与えています。
 parseはあくまで因子しか解析しませんが、p[0]が演算子であり、因子でないためエラーになっています。
 因子(があるでろう)文字列を指すよう調整してください。

Comp

Re:無題

#149

投稿記事 by Comp » 18年前

はじめまして、
横槍ですいません。

②、③についてですが、

とんぷぅ~さんはステップ実行が出来る環境でしょうか?

出来るのであれば、1+1の場合と1*1の場合で比べて見てください。

違いは+と*だけなのに片方はオーバーフローしてしまう、
じゃあ +と*の処理してる所は、どこなんでしょう?
その差は何なんでしょう?
おかしな所が浮き上がってきませんか?
ちょっとした処理の忘れ物があるだけです。

がんばってください。

@とんぷぅ~

Re:無題

#150

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。Compさん。レスありがとうございます。

"Justyさん"

>parseの戻り値をチェックしてください。
>チェックして、問題があれば(0が戻ってきている)エラーとしてください。

本当に申し訳ありません。具体的にどのようにすればよいのか分かりません。
if等で指定すればいいのでしょうか?

"Compさん"

>ちょっとした処理の忘れ物があるだけです。

う~ん。分かりません。ステップさせてみたんですが、ここがこうでという
筋道を立てて理解することが出来ていないので、最終的な結果しか分からないです。
ちなみにその処理とはmain関数内ではないんですよね?

@とんぷぅ~

Re:無題

#151

投稿記事 by @とんぷぅ~ » 18年前

すみません。解決できました。pに気を取られすぎていました。

ちなみにまだ戻り値のチェックは出来ていません(泣)

@とんぷぅ~

Re:無題

#152

投稿記事 by @とんぷぅ~ » 18年前

連続レスすみません。

勘違いでした。まだ①、②、③とも解決できていません。。。orz

@とんぷぅ~

Re:無題

#153

投稿記事 by @とんぷぅ~ » 18年前

またまたすみません。無事動きました。
もう少し整理してからソースを載せたいと思いますので、
よろしくお願いします。

@とんおうぅ~

Re:無題

#154

投稿記事 by @とんおうぅ~ » 18年前

こんばんは。

今、int型を超える場合のオーバーフローチェックをしていたのですが、
parse_factor()
*pValue = (int) strtol (*p, &end, 10);の部分の下に
	if ( errno != ERANGE )
    {
		if ( *end != '\0' )
                        // 整数以外が入力された場合   
			integer_err();
	}
    else
    {       // int型を超えていた場合
		int_over_err();
	}
としたのですが、上手く動きません。何がいけないのでしょうか?

@とんぷぅ~

Re:無題

#155

投稿記事 by @とんぷぅ~ » 18年前

連レスすみません。名前を間違えましたw

Justy

Re:無題

#156

投稿記事 by Justy » 18年前

ちなみにまだ戻り値のチェックは出来ていません
if等で指定すればいいのでしょうか
 一昨日あたりに書いたと思ったのですが、ifでチェックして下さい。


上手く動きません
 できれば何がどう旨く動かないのか書いて欲しいところですが。
 でもまぁ大体推測はつきます。

[color=#d0d0ff" face="aria[/url]if ( *end != '\0' )[/color]

 NUL文字でなければエラーにするのは多分数式の後に余計な文字があるかどうかを
みようとしたのだと思いますが、それでは最初の parseチェックでエラーになってしまいますよ。
 2回目の parseが終わった後、チェックするようにすれば式が最後まで解析されたかどうか判ると思います。

@とんぷぅ~

Re:無題

#157

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

>2回目の parseが終わった後、チェックするようにすれば
ということはmain関数内で行えばよいのでしょうか?

う~ん。中々難しいですね。

まだいじってないのですが、一応ソース載せておきます。

Justy

Re:無題

#158

投稿記事 by Justy » 18年前

>ということはmain関数内で行えばよいのでしょうか?
 Y
 これで parseの戻り値さえチェックすれば完成なのではないでしょうか。

@とんぷぅ~

Re:無題

#159

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。お世話になっております。
レスが遅れて申し訳ありませんでした。

戻り値のチェックですが、こんな感じでいいでしょうか?
static int Parse (const char *expression, const char **end, long long *pValue)
{
	// 要素解析
	const char *p = expression;
	if (Parse_factor (&p, pValue))
	{
		// 解析が終了した文字列の位置を記録
		p = Skip_parce (p);
		if (end)	*end = p;
		
		return 1;
	}
	
	if (Parse == 0)
	{
		printf("error : return error\n");
	}
	return 0;
}

Justy

Re:無題

#160

投稿記事 by Justy » 18年前

>戻り値のチェックですが、こんな感じでいいでしょうか
 まぁ場所的にはそこでも間違いではないですが、そのチェック位置に
来たときは常にエラーです。

 つまりそこでチェックする場合、エラーチェックそのものが不要になります。


 ただ、parseの再利用性を考えるならそこでチェックせず、main側で行った方がいいでしょう。
 せっかく parse関数は成功すれば 1が、失敗すれば 0が戻ってきているのですから。
[color=#d0d0ff" face="monospace]
if(!parse (st, &p, &lop))
    printf("error\n");[/color]

>if (Parse == 0)
 ちなみにこの if文は常に偽となります。
 意味がありません。

keichan

Re:無題

#161

投稿記事 by keichan » 18年前

>>if (Parse == 0)
> ちなみにこの if文は常に偽となります。
> 意味がありません。

ちょこっと解説をば。

なぜ "常に偽" になるかですが、関数を()なしで使用した場合
その関数のアドレスを指すことになります。
(関数ポインタを使用したことがあるならすんなり理解していただけると思いますが)

関数の"アドレス"なので 0 はあり得ません。

よって

Parse(!=0) == 0
は常に偽になります。

ご存知なネタでしたらスルーしてください。

@とんぷぅ~

Re:無題

#162

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。keichanさん。レスありがとうございました。
// 文字列stの解析
	Parse (st, &p, &lop);

	// opに演算子を代入
	op = p[0];
	p++;

	// 文字列pの解析 
	Parse (p, &p, &rop);
	
	if (!Parse (st, &p, &lop))
	{
		printf("error\n");
	}
これで問題無いですよね?

>if (Parse == 0)
>ちなみにこの if文は常に偽となります。
>意味がありません。

掘り下げて論理式を調べてみました。今更ですが、
間違った考え方をしていました。指摘ありがとうございます。

Justy

Re:無題

#163

投稿記事 by Justy » 18年前

>これで問題無いですよね?
 戻り値のチェック方法自体は問題ないですが、
なぜ Parseが3回も呼ばれるようになってしまったのでしょうか?

 しかも1回目と2回目は一切チェックしていないですし。

@とんぷぅ~

Re:無題

#164

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

>戻り値のチェック方法自体は問題ないですが、
>なぜ Parseが3回も呼ばれるようになってしまったのでしょうか?
>しかも1回目と2回目は一切チェックしていないですし。

すみません。よく理解出来ません。こういうことなんでしょうか?
if (!Parse (st, &p, &lop))

	{

		printf("error\n");

	}
op = p[0];
p++;
if (!Parse (p, &p, &rop))

	{

		printf("error\n");

	}

Justy

Re:無題

#165

投稿記事 by Justy » 18年前

>こういうことなんでしょうか?
 そうです。
 ただ、errorと表示ながらもそのまま処理を何事もなかったかのように処理を続行しているのは気になりますが。

@とんぷぅ~

Re:無題

#166

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。お世話になってます。レスありがとうございます。

修正してビルドしたんですが、負数の-2147483648(int型の限界)
を入力すると強制的に-2147483647となってしまいます。これは
parse関数内のstrtolの仕様なんでしょうか?

ただ"-2147483648"自体はオーバフローしていないので
ちょっとおかしいと思うのですが、何処がいけないのでしょうか?

Justy

Re:無題

#167

投稿記事 by Justy » 18年前

>ちょっとおかしいと思うのですが、何処がいけないのでしょうか?
 あー、なるほど。
 たしかにこのままではその値は扱えませんね。


 Parse_factor()を見るとわかると思いますが、符号があった場合
ひとまずスキップして数字文字を見つけようとします。
 で、その数字文字を整数化した後、符号に従って符号変換をします。

 つまり、-2147483648の場合、符号を無視した数字 2147483648が INT_MAXを超える為、
strtolの結果が INT_MAXである 2147483647となり、その後符号を反転するので
-2147483647になってしまいます。

 一番簡単な解決方法としては(機種依存になりますが) strtolの代わりに
_strtoi64を使って解析し、その後、lop / ropが INT_MIN~INT_MAXの範囲内に
あることをチェックするのが一番簡単だと思います。

@とんぷぅ~

Re:無題

#168

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

無事解決出来ました。ちなみにエラーメッセージをまとめるには
もっといい方法があるんでしょうか?(例えば関数化にしても、マクロにしても)
さすがにコードが見にくいので、こうした方がいいというようなことがあればお願いします。

Justy

Re:無題

#169

投稿記事 by Justy » 18年前

ちなみにエラーメッセージをまとめるには もっといい方法があるんでしょうか?
 今は用途別に関数を作っているのですね。
 見たところ、exitに渡す終了コードと文字列以外には違いはないようです。

 であれば、終了コードとエラーメッセージの文字列を引数に受け取るエラー関数を
用意してみてはどうでしょうか。

[color=#d0d0ff" face="aria[/url]int error_exit(int exit_code, const char *message);[/color]

 こんな関数を用意して、エラーを検出したら
 
[color=#d0d0ff" face="aria[/url]error_exit(-1, "0 division is a prohibition");[/color]

 のように使うカンジで。



#余裕があったら
int error_exit(int exit_code, const char *format, ...);
の形式にチャレンジしてもいいかもしれません。

@とんぷぅ~

Re:無題

#170

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。

ちょっとやってみます!!

@とんぷぅ~

Re:無題

#171

投稿記事 by @とんぷぅ~ » 18年前

一応作成してみたのですが、引数の設定が分からず
妥協してしまいました。折角教えて下さったのに申し訳ありません。

一応ソース添付しますので、何かありましたらご指摘お願いします。
ヘッダと分けておいたのですが、ビルドが面倒だと思うので一緒にしておきました。
余計に読みにくいとは思いますが、よろしくお願いします。

Justy

Re:無題

#172

投稿記事 by Justy » 18年前

>何かありましたらご指摘お願いします

 んーと

・ exitの多用
 どのルートを経由しても必ず exitで終わらせるのは、どうなんでしょう。
 exitしなければならない状態というのはよほどの異常事態です。
 できれば exitすることなく、普通に main関数を抜けるようにした方が、
いいのではないでしょうか。


・ エラーコードが直値
 定数を直接コードの中に埋め込むのはあまり良い方法とはいえません。
 例えばバッファサイズの 128とか、エラーコードとか。
 特に後者は exit_codeが 1とか言われてもさっぱり意味がわからないので、
何かしら defineや enumなどで名前を割り振っておくといいでしょう。


・ エラーの場合、式が表示されないことある。
 式の中にエラーがあった場合でも、入力された式を表示してから
エラーとした方がいいのではないでしょうか。


・ char st[128]
 mainの引数から 128文字以上入力されると Storage()内でバッファをオーバーしてしまい
不正なプログラムになります。
 128文字以上にならないようにしましょう。


・ lop / ropの範囲チェック
 四則演算の結果が出てからチェックしていますが、する前にした方がいいのではないでしょうか。


・ 式の最後に余計な文字があった場合
 "1+1a"のように最後に余計な文字があっても解析が成功しますが、これはいいのでしょうか。


・ テスト
 コードを書いてからビルドして、その後テストをするとき、
毎回毎回式をコマンドラインでキーボードから打つか or MSVCのコマンドライン引数の設定で
記入した内容を main関数の引数に渡していると思うのですが、面倒くさくないですか?

 そういうときはデバッグ向けに式をプログラムの中に埋め込んで、
自動的にテストできるようにしてはどうでしょうか。
 ついでにテスト用の式を配列にしておいて、複数の式を順次解析、結果表示していくように
していくと、様々なケースのテストを一度に行うことができますよ。

 参考までに改良したコードを載せておきます。
(添付のコードの mainの中の #if 1を #if 0にするとこのテストモードになります)

@とんぷぅ~

Re:無題

#173

投稿記事 by @とんぷぅ~ » 18年前

Justyさん。レスありがとうございます。
ソース拝見しました。さすがJustyさん。
あぁ~やはりプロっぽいコーディングですね。

質問があるのですが、エラーコードの数とエラーメッセージ一覧の個数が
一致していないと思うのですが、それは何故なんでしょうか?

// テーブルの数とエラーコードの数が一致するかどうか検証
// 範囲外なら codeを 0に

というコメント以下はどういうふうに読めばいいのでしょうか?
// エラーコード
enum 
{
	ERROR_CODE_NO_ERROR,
	ERROR_CODE_INVALID_EXPRESSION,
	ERROR_CODE_INT_OUT_OF_RANGE,
	ERROR_CODE_INVALID_OPERATOR,
	ERROR_CODE_DIVIDED_ZERO,
	ERROR_CODE_MULTI_OVERFLOW,
	ERROR_CODE_NUMBER_OF_UNUSUAL_ARGS,
	ERROR_CODE_STRING_BUFFER_OVER,
	ERROR_CODE_MAX
};

//	エラーメッセージ一覧
void ErrorMessage(int code)
{
	static const char * const message_list[/url] = 
	{
		"unknown",
		"Please input a correct expression",
		"The range of the int type is exceeded",
		"Please input the operator correctly",
		"0 division is a prohibition",
		"The over_flow learns by experience",
		"Please input the argument correctly",
		"Buffers of character string overflowed.",
	};
	
	// テーブルの数とエラーコードの数が一致するかどうか検証
	StaticAssert(ArraySize(message_list) == ERROR_CODE_MAX,
			message_list_size_and_ERROR_CODE_MAX_is_not_equal);
	
	// 範囲外なら codeを 0に
	if(code < 1 && code>=ArraySize(message_list))
		code = 0;
	printf("error : %s\n", message_list[code]);
}

asd

Re:無題

#174

投稿記事 by asd » 18年前

横槍失礼します。

提示されたコードだけを読む限り、エラーコードには正常終了を表すコードが含まれているように思います。
(ERROR_CODE_NO_ERROR)

また関数などのエラーコードは負の数で返ってくることが多いのと、用意したエラーコード以上値が入ってきた場合に、範囲外にならないような補正が
// 範囲外なら codeを 0に
のくだりではないでしょうか。

間違っていたらゴメンナサイ。

@とんぷぅ~

Re:無題

#175

投稿記事 by @とんぷぅ~ » 18年前

asdさん。素早いレスありがとうございます。

ではERROR_CODE_MAXがエラーコード以上の値が入った場合の処理
ということでよいのでしょうか?

マクロを忘れてました。
// 静的アサート(コンパイル時)
#define StaticAssert(eval, tag) typedef char StaticAssert_##tag_[1][(eval)]

アサートって引数が1つだと思ったのですが、これは自作ということですよね?

Justy

Re:無題

#176

投稿記事 by Justy » 18年前

質問があるのですが、エラーコードの数とエラーメッセージ一覧の個数が
一致していないと思うのですが、それは何故なんでしょうか?

 一致していないように見えるだけだと思います。
 エラーメッセージ message_listの配列要素数は見ての通り8個あります。
 で、エラーコードは
[color=#d0d0ff" face="monospace]
    ERROR_CODE_NO_ERROR,                    // 0・・・エラーではない
    ERROR_CODE_INVALID_EXPRESSION,          // 1・・・何かのエラー
    ERROR_CODE_INT_OUT_OF_RANGE,            // 2・・・何かのエラー
    ERROR_CODE_INVALID_OPERATOR,            // 3・・・何かのエラー
    ERROR_CODE_DIVIDED_ZERO,                // 4・・・何かのエラー
    ERROR_CODE_MULTI_OVERFLOW,              // 5・・・何かのエラー
    ERROR_CODE_NUMBER_OF_UNUSUAL_ARGS,      // 6・・・何かのエラー
    ERROR_CODE_STRING_BUFFER_OVER,          // 7・・・何かのエラー
    ERROR_CODE_MAX                          // 8・・・エラーコードの数[/color]
 で、実際にエラーとして使われるのはERROR_CODE_NO_ERROR(1)~ERROR_CODE_STRING_BUFFER_OVER(7)の
計7個ですが、enumにはエラーではないことを示すERROR_CODE_NO_ERRORもあるので
計8個となり、message_listの要素数と同じだけあります。

 ERROR_CODE_MAXは、特殊な使い方をするもので、エラーコード
としては使いません。
 実はエラーコードの数を表すのに使われます。


というコメント以下はどういうふうに読めばいいのでしょうか?
 asdさんの書かれている通りです。
 このErrorMessage関数から見ると codeに何が入ってくるかは予想できないので、
配列に対して不正なアクセスをしないようにしています。

 例えば codeが 100とか -100とかの状態で message_list

コード:

にアクセスしたら
まずいですよね?


 ちなみに StaticAssertは enumのエラーコード数と message_listの配列要素数を
比較していますが、これは片方に何か追加したのにもう片方の追加を
忘れたりしないようにする為の予防策です。

 双方の数が一致しないとコンパイル時にエラーがでるので、
実行時にエラーを出すより、気づきやすくなります。


[color=#a89898]>[i]アサートって引数が1つだと思ったのですが、これは自作ということですよね?[/i][/color]
 自作ですね。
 そのソースのどこかにマクロが定義してあります。

@とんぷぅ~

Re:無題

#177

投稿記事 by @とんぷぅ~ » 18年前

遅くなりましたが皆様レス本当にありがとうございました。

管理人さん始め、Justyさん。その他大勢の方に回答をいただけ
大変助かりました。まだまだ未熟者ですがよろしくお願いします。

管理人

Re:無題

#178

投稿記事 by 管理人 » 18年前

完成されました?! お疲れ様でした!
あまりお力になれず申し訳ないです^^;
これから大変でしょうけど、頑張ってください!

初歩の初歩で・・・・

#179

投稿記事 by » 18年前

今、僕は「VisualC++ 2005」を用いて、0「導入」より始めようとしたのですが
何度やっても、「DxLib.sln」をビルドすると
『ビルド エラーが発生しました。続行して、最後に成功したビルドを実行しますか?』
と出て、「はい」とすると・・・

『プログラム'C:\Documents and Settings\****\デスクトップ\DxLib_VC
\サンプルプログラム実行用フォルダ\Debug\DxLib.exe'を開始できません。

指名されたファイルが見つかりません。』

と出てしまい、どうしようもないのです。
ちなみに「DxLib.sln」を開く前には変換ヴィザードが出ました。
「VisualC++」最新だからでしょうか教えてください。

管理人

Re:初歩の初歩で・・・・

#180

投稿記事 by 管理人 » 18年前

お使いのコンパイラは製品版ですか?
それともフリーのExpressEditionですか?
前者でしたら何も設定なしに出来ますが、後者では設定が必要です。

http://homepage2.nifty.com/natupaji/DxLib/dxuse.html

この辺ご参考にどうぞ。

Re:初歩の初歩で・・・・

#181

投稿記事 by » 18年前

そうです・・・後者なのです。
参考にさせていただきます。
ありがとうございました!

たまねぎ

Re:初歩の初歩で・・・・

#182

投稿記事 by たまねぎ » 18年前

突然すいません。

visual studio2005でCtrl+F5と押してコンパイル?をすると、”指定されたファイルは見つかりません。”と出てきます。

おそらくコンパイルは出来ているのだと思うんですが、実行結果が出てきません。

どうしたらいいのか教えてください。

閉鎖

“C言語何でも質問掲示板” へ戻る