DXライブラリのコードについて質問です

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
メカ
記事: 37
登録日時: 12年前

DXライブラリのコードについて質問です

#1

投稿記事 by メカ » 12年前

DXライブラリでスプリプトを読み込むコードを作成したのですが、
実行するとバグって動きません。
おそらくどこかのコードに誤りがあると思います。
何回見返してもわかりません。
バグの原因は何でしょうか?
少し長いコードですみませんがご回答お待ちしております。

DrawString関数のスプリプトコードです。

コード:

#include <dxlibp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//スクリプトは最大1000行まで読み込む
#define SCRIPT_MAX_LINE 1000
//スクリプト最大文字数
#define SCRIPT_MAX_STRING_LENGTH 300

typedef struct ScriptInformation_tag {
        int maxLineNumber;                      //スクリプト行数
        int currentLine;                        //現在何行目を実行しているか
        const char* filename;           //ファイル名
        char script[SCRIPT_MAX_LINE][SCRIPT_MAX_STRING_LENGTH];
} ScriptInformation;
//プロトタイプ宣言
int loadScript(const char* filename, ScriptInformation* scriptInfo);
void splitString(const char* src, char* dest[], const char* delim, int splitNum);

char* story_event[100];//実行するイベントのデータ
char Name[128];

int main()
{
	if (DxLib_Init()== -1)return(-1);
	ScriptInformation script;
while(ProcessMessage() == 0){
int next=0;
	int story_eventint[3];
	if(script.currentLine==0)next=1;
//DrawString関数
	if(strncmp(story_event[0],"DrawString", SCRIPT_MAX_STRING_LENGTH) == 0){
	for(int i;i<3;i=i+1)story_eventint[i+1]=atoi(story_event[i+1]);
DrawString(story_eventint[1],story_eventint[2],story_event[3],DX_COLOR_WHITE);
	next=1;}
if(next==1){
        loadScript("ファイル.txt", &script );
//splitString(分割したい文字列,分割された文字列,区切り文字,最大分割数);(1行の最大文字数は SCRIPT_MAX_STRING_LENGTH)
        splitString(script.script[script.currentLine], story_event, " ,", 10);
	}
}
 return 0;
}


//ファイル読み込み
int loadScript(const char* filename, ScriptInformation* scriptInfo)
{
        int pos;
        char c;
        //スクリプトファイル
        int fp;
        //スクリプト情報を初期化
        memset( scriptInfo , 0, sizeof(ScriptInformation) );
        //スクリプトファイルを開く
		if(fp=FileRead_open(filename)) ;
		//ファイル読み込みに失敗
//        if( fp == NULL ){printf("スクリプト %s を読み込めませんでした\n", filename);return -1;}
        //script書き込み時に使用
        pos = 0;
        for( ;; ) {
                //一文字読み込み
                c = FileRead_getc( fp );
                //ファイルの終わりかどうか
                if( FileRead_eof( fp ) )break;
                //文章先頭の空白部分を読み飛ばす
                while( (c == ' ' || c == '\t') && pos == 0 && !FileRead_eof( fp ) )c = FileRead_getc( fp );
				//1行の文字数が多すぎる
                if( pos >= SCRIPT_MAX_STRING_LENGTH - 1 ) {printf("error: 文字数が多すぎます (%d行目)", scriptInfo->currentLine );return -1;}
                //改行文字が出てきた場合,次の行へ移動
                if( c == '\n' ) {
                        //空行は読み飛ばす
                        if( pos == 0 )continue;                        
                        //\0を文字列の最後に付ける
                        scriptInfo->script[ scriptInfo->currentLine ][ pos ] = '\0';
                        //次の行に移動
                        scriptInfo->currentLine++;
                        //書き込み位置を0にする
                        pos = 0;
                }else {
                        //書き込み
                        scriptInfo->script[ scriptInfo->currentLine ][ pos ] = c;
                        //文字書き込み位置をずらす
                        pos++;
                }
        }
		FileRead_close(fp);
        //最大行数
        scriptInfo->maxLineNumber = scriptInfo->currentLine;
        //読み込み中の行を0にする
        scriptInfo->currentLine = 0;
        //スクリプトファイル名を設定
        scriptInfo->filename = filename;
        return 0;
}
//文字列分割(1行の最大文字数は SCRIPT_MAX_STRING_LENGTH)
//src : 分割したい文字列
//dest: 分割された文字列
//delim: 区切り文字
//splitNum : 最大分割数
void splitString(const char* src, char* dest[], const char* delim, int splitNum){
        int i;
        char* cp;
        char* copySrc;
        //元の文章をコピーする
        copySrc = (char*)malloc( sizeof(int) * SCRIPT_MAX_STRING_LENGTH + 1);
        strncpy( copySrc, src, SCRIPT_MAX_STRING_LENGTH );
        cp = copySrc;

        //strtokを使って copySrc をdelim区切りで分割する
        for( i = 0; i < splitNum ; i++ ) {
                //分割対象文字列が無くなるまで分割
                if( (dest[i] = strtok(cp, delim)) == NULL ) {
                        break;
                }
                //2回目にstrtokを呼び出す時は,cpをNULLにする
                cp = NULL;
        }
        //分割された文字列の最後の要素はNULLとしておく
        dest[i] = NULL;
}
ファイル.txt
DrawString 0,0,あいうえお
DrawString 0,20,かきくけこ
DrawString 0,40,さしすせそ

dic
記事: 658
登録日時: 14年前
住所: 宮崎県
連絡を取る:

Re: DXライブラリのコードについて質問です

#2

投稿記事 by dic » 12年前

一部分自信がないですが、わかったところを修正しました

分かったところは、初期化されていない値を使用していたことと、if(...) ; と空白の処理をしていたところです。
どちらとも、コンパイラで指摘されたのですが、コンパイラ、エディタは使用されていないのでしょうか?
Visual C++ 2010, 2008 Express は無料なのでおすすめです。
2行目の #include <dxlibp.h> も DxLib.h に変更しました。
あと、インデントをそろえてください
33行目、56行目が、意図しない動作をしていたと思います。

コード:

// ネットの質問.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include "DxLib.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//スクリプトは最大1000行まで読み込む
#define SCRIPT_MAX_LINE 1000
//スクリプト最大文字数
#define SCRIPT_MAX_STRING_LENGTH 300
 
typedef struct ScriptInformation_tag {
        int maxLineNumber;                      //スクリプト行数
        int currentLine;                        //現在何行目を実行しているか
        const char* filename;           //ファイル名
        char script[SCRIPT_MAX_LINE][SCRIPT_MAX_STRING_LENGTH];
} ScriptInformation;
//プロトタイプ宣言
int loadScript(const char* filename, ScriptInformation* scriptInfo);
void splitString(const char* src, char* dest[], const char* delim, int splitNum);
 
char* story_event[100];//実行するイベントのデータ
char Name[128];
 
int main()
{
    if( DxLib_Init() == -1 )
		return( -1 );
    
	ScriptInformation script;
	//	初期化(追加)
	memset( &script, 0, sizeof(script) );

	while(ProcessMessage() == 0)
	{
		int next=0;
	    int story_eventint[3];

		if( script.currentLine == 0 )
			next=1;
//DrawString関数
		if(strncmp(story_event[0],"DrawString", SCRIPT_MAX_STRING_LENGTH) == 0)
		{
			//		for(int i;i<3;i=i+1)story_eventint[i+1]=atoi(story_event[i+1]);
			//int	i;	i = 0 初期化していな
			for(int i=0;i<3;i=i+1)story_eventint[i+1]=atoi(story_event[i+1]);
			//DrawString(story_eventint[1],story_eventint[2],story_event[3],DX_COLOR_WHITE);
			next=1;
		}

		if(next==1)
		{
			loadScript("ファイル.txt", &script );
			//splitString(分割したい文字列,分割された文字列,区切り文字,最大分割数);(1行の最大文字数は SCRIPT_MAX_STRING_LENGTH)
			splitString(script.script[script.currentLine], story_event, " ,", 10);
		}
	}
	return 0;
}
 
 
//ファイル読み込み
int loadScript(const char* filename, ScriptInformation* scriptInfo)
{
        int pos;
        char c;
        //スクリプトファイル
        int fp;
        //スクリプト情報を初期化
        memset( scriptInfo , 0, sizeof(ScriptInformation) );
        //スクリプトファイルを開く
//        if(fp=FileRead_open(filename)) ;	← 条件式おかしい セミコロンもおかしい
        if( fp = FileRead_open( filename ) )
		{
		}
        //ファイル読み込みに失敗
//        if( fp == NULL ){printf("スクリプト %s を読み込めませんでした\n", filename);return -1;}
        //script書き込み時に使用
        pos = 0;
        for( ;; ) {
                //一文字読み込み
                c = FileRead_getc( fp );
                //ファイルの終わりかどうか
                if( FileRead_eof( fp ) )break;
                //文章先頭の空白部分を読み飛ばす
                while( (c == ' ' || c == '\t') && pos == 0 && !FileRead_eof( fp ) )c = FileRead_getc( fp );
                //1行の文字数が多すぎる
                if( pos >= SCRIPT_MAX_STRING_LENGTH - 1 ) {printf("error: 文字数が多すぎます (%d行目)", scriptInfo->currentLine );return -1;}
                //改行文字が出てきた場合,次の行へ移動
                if( c == '\n' ) {
                        //空行は読み飛ばす
                        if( pos == 0 )continue;                        
                        //\0を文字列の最後に付ける
                        scriptInfo->script[ scriptInfo->currentLine ][ pos ] = '\0';
                        //次の行に移動
                        scriptInfo->currentLine++;
                        //書き込み位置を0にする
                        pos = 0;
                }else {
                        //書き込み
                        scriptInfo->script[ scriptInfo->currentLine ][ pos ] = c;
                        //文字書き込み位置をずらす
                        pos++;
                }
        }
        FileRead_close(fp);
        //最大行数
        scriptInfo->maxLineNumber = scriptInfo->currentLine;
        //読み込み中の行を0にする
        scriptInfo->currentLine = 0;
        //スクリプトファイル名を設定
        scriptInfo->filename = filename;
        return 0;
}
//文字列分割(1行の最大文字数は SCRIPT_MAX_STRING_LENGTH)
//src : 分割したい文字列
//dest: 分割された文字列
//delim: 区切り文字
//splitNum : 最大分割数
void splitString(const char* src, char* dest[], const char* delim, int splitNum){
        int i;
        char* cp;
        char* copySrc;
        //元の文章をコピーする
        copySrc = (char*)malloc( sizeof(int) * SCRIPT_MAX_STRING_LENGTH + 1);
        strncpy( copySrc, src, SCRIPT_MAX_STRING_LENGTH );
        cp = copySrc;
 
        //strtokを使って copySrc をdelim区切りで分割する
        for( i = 0; i < splitNum ; i++ ) {
                //分割対象文字列が無くなるまで分割
                if( (dest[i] = strtok(cp, delim)) == NULL ) {
                        break;
                }
                //2回目にstrtokを呼び出す時は,cpをNULLにする
                cp = NULL;
        }
        //分割された文字列の最後の要素はNULLとしておく
        dest[i] = NULL;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: DXライブラリのコードについて質問です

#3

投稿記事 by softya(ソフト屋) » 12年前

dxlibp.hってDXLIBポータブルって事でPSPですよね。
PSPだとデバッガは使えないので厳しいかもしれませんが、VC++でデバッガで事前テストをするぐらいはしても良いのかも知れませんよ。
あとPSPでもテキストファイルは書き出せると思いますので、処理中のログファイルを作成してみてはどうでしょうか?
PSPでは頭を捻ってデバッグする方法を考えましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
メカ
記事: 37
登録日時: 12年前

Re: DXライブラリのコードについて質問です

#4

投稿記事 by メカ » 12年前

ご回答有難う御座います。
間違ったコードを直してみましたが、前と同じようにバグで強制終了してしまいます。
また、このコードでちゃんとスプリプト出来るかどうかも不安です。
コード自体に誤りは無いのでしょうか?
何度もすいません。

また、softyaさんの回答どうりにログファイルなども活用して、こちらの方でも誤りを探してみます。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: DXライブラリのコードについて質問です

#5

投稿記事 by softya(ソフト屋) » 12年前

大雑把に拝見。とりあえずスクリプトのロードもしないうちからstrcmpとかコードがトリッキーです。
分かりやすいコードを心がけてみましょう。そうすればバグも出づらくなります。
ロード → スクリプト処理 → ロード → スクリプト処理 の流れになるようにループ化します。

WindowsとPSP兼用バージョン。これでVC++のデバッガでテスト出来ます。

コード:

#ifdef WIN32	/*Windows用*/
#include "DxLib.h"
#else
#include <dxlibp.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//スクリプトは最大1000行まで読み込む
#define SCRIPT_MAX_LINE 1000
//スクリプト最大文字数
#define SCRIPT_MAX_STRING_LENGTH 300


#ifdef WIN32	/*Windows用*/
	#define DX_COLOR_WHITE GetColor(255,255,255)
#endif


typedef struct ScriptInformation_tag {
	int maxLineNumber;                      //スクリプト行数
	int currentLine;                        //現在何行目を実行しているか
	const char* filename;           //ファイル名
	char script[SCRIPT_MAX_LINE][SCRIPT_MAX_STRING_LENGTH];
} ScriptInformation;
//プロトタイプ宣言
int loadScript( const char* filename, ScriptInformation* scriptInfo );
void splitString( const char* src, char* dest[], const char* delim, int splitNum );

char* story_event[100];//実行するイベントのデータ
char Name[128];


#ifdef WIN32	/*Windows用*/
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) {
	ChangeWindowMode(TRUE);//ウィンドウモード
#else
int main() {
#endif
	if ( DxLib_Init() == -1 )return( -1 );
	ScriptInformation script;
    //  初期化(追加)
    memset( &script, 0, sizeof(script) );
	while( ProcessMessage() == 0 ) {
		int next = 0;
		int story_eventint[3];
		if( script.currentLine == 0 )next = 1;
//DrawString関数
		if( strncmp( story_event[0], "DrawString", SCRIPT_MAX_STRING_LENGTH ) == 0 ) {
			for( int i; i < 3; i = i + 1 )story_eventint[i + 1] = atoi( story_event[i + 1] );
			DrawString( story_eventint[1], story_eventint[2], story_event[3], DX_COLOR_WHITE );
			next = 1;
		}
		if( next == 1 ) {
			loadScript( "ファイル.txt", &script );
//splitString(分割したい文字列,分割された文字列,区切り文字,最大分割数);(1行の最大文字数は SCRIPT_MAX_STRING_LENGTH)
			splitString( script.script[script.currentLine], story_event, " ,", 10 );
		}
	}
	return 0;
}


//ファイル読み込み
int loadScript( const char* filename, ScriptInformation* scriptInfo ) {
	int pos;
	char c;
	//スクリプトファイル
	int fp;
	//スクリプト情報を初期化
	memset( scriptInfo , 0, sizeof( ScriptInformation ) );
	//スクリプトファイルを開く
	fp = FileRead_open( filename );
	if( -1==fp ) {
		return 0;
	}
	//ファイル読み込みに失敗
//        if( fp == NULL ){printf("スクリプト %s を読み込めませんでした\n", filename);return -1;}
	//script書き込み時に使用
	pos = 0;
	for( ;; ) {
		//一文字読み込み
		c = FileRead_getc( fp );
		//ファイルの終わりかどうか
		if( FileRead_eof( fp ) )break;
		//文章先頭の空白部分を読み飛ばす
		while( ( c == ' ' || c == '\t' ) && pos == 0 && !FileRead_eof( fp ) )c = FileRead_getc( fp );
		//1行の文字数が多すぎる
		if( pos >= SCRIPT_MAX_STRING_LENGTH - 1 ) {
			printf( "error: 文字数が多すぎます (%d行目)", scriptInfo->currentLine );
			return -1;
		}
		//改行文字が出てきた場合,次の行へ移動
		if( c == '\n' ) {
			//空行は読み飛ばす
			if( pos == 0 )continue;
			//\0を文字列の最後に付ける
			scriptInfo->script[ scriptInfo->currentLine ][ pos ] = '\0';
			//次の行に移動
			scriptInfo->currentLine++;
			//書き込み位置を0にする
			pos = 0;
		} else {
			//書き込み
			scriptInfo->script[ scriptInfo->currentLine ][ pos ] = c;
			//文字書き込み位置をずらす
			pos++;
		}
	}
	FileRead_close( fp );
	//最大行数
	scriptInfo->maxLineNumber = scriptInfo->currentLine;
	//読み込み中の行を0にする
	scriptInfo->currentLine = 0;
	//スクリプトファイル名を設定
	scriptInfo->filename = filename;
	return 0;
}
//文字列分割(1行の最大文字数は SCRIPT_MAX_STRING_LENGTH)
//src : 分割したい文字列
//dest: 分割された文字列
//delim: 区切り文字
//splitNum : 最大分割数
void splitString( const char* src, char* dest[], const char* delim, int splitNum ) {
	int i;
	char* cp;
	char* copySrc;
	//元の文章をコピーする
	copySrc = ( char* )malloc( sizeof( int ) * SCRIPT_MAX_STRING_LENGTH + 1 );
	strncpy( copySrc, src, SCRIPT_MAX_STRING_LENGTH );
	cp = copySrc;

	//strtokを使って copySrc をdelim区切りで分割する
	for( i = 0; i < splitNum ; i++ ) {
		//分割対象文字列が無くなるまで分割
		if( ( dest[i] = strtok( cp, delim ) ) == NULL ) {
			break;
		}
		//2回目にstrtokを呼び出す時は,cpをNULLにする
		cp = NULL;
	}
	//分割された文字列の最後の要素はNULLとしておく
	dest[i] = NULL;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
メカ
記事: 37
登録日時: 12年前

Re: DXライブラリのコードについて質問です

#6

投稿記事 by メカ » 12年前

コードの位置に問題がありました(^^)
スプリプトのロードを先に実行したら解決出来ました
ありがとうございました

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: DXライブラリのコードについて質問です

#7

投稿記事 by softya(ソフト屋) » 12年前

メカ さんが書きました:コードの位置に問題がありました(^^)
スプリプトのロードを先に実行したら解決出来ました
ありがとうございました
解決したコードの掲載もフォーラムルールなのでお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

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