DXライブラリで改行がうまくいかない

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

DXライブラリで改行がうまくいかない

#1

投稿記事 by namari » 12年前

DXライブラリは\nで改行を行わないと知り、
大量の文章処理を行う都合上、あるchar型の文章の中に「@」を加えると、
そこで次の行に改行する処理を作ってみたのですが、うまくいきません。
下の画像のように@が文章中につくだけで、改行が行われません。
おそらくstrtokの使い方に難があるのでしょうが、困ったことに今手元に簡単なコンパイラがなく、
テストコンパイルでstrtokの挙動が理解通りか確かめる術がないです。
問題を指摘していただけると幸いです。

コード:

//GV.h
GLOBAL int message_cnt;//何個メッセージが書かれたかの最大値を見る
GLOBAL int message_graph_cnt;//メッセージを1から順に表示する
GLOBAL int message_rest_flag;//メッセージが2つ以上残っていたら移動させない
GLOBAL int pre_icon[1024];
GLOBAL char pre_id[1024][255];//pre_id[配列数][文字数]
GLOBAL char pre_message[3][1024][255];//pre_message[行目][配列数][文字数]


//message.cpp

//プロジェクト中のあちこちからメッセージを受け取る関数。1ターンに複数のメッセージを受け取ることもあるので、
//それを処理する。(敵を倒し、レベルが上がれば、「~に~ダメージ」「~をたおした」「レベルがあがった」の三つ)
void message_add(int icon,char id[],char message[]){//アイコンの画像番号、名前、メッセージ
        char *tp;
		int i=0;
    	message_cnt++;
        pre_icon[message_cnt]=icon;
		strncpy(pre_id[message_cnt],id,255);
		tp = strtok( message, "@" );/*↓おそらくここから問題の場所*/
		strncpy(pre_message[0][message_cnt],tp,255);
        while ( tp != NULL ) {
				i++;
                tp = strtok( NULL,"@" );
                if ( tp != NULL ) strncpy(pre_message[i][message_cnt],tp,255);
        }
}

//上のmessage_addの拡張版。1つの引数を受け取れるようになった。
void message_add(int icon,char id[],char message1[],char argument[],char message2[]){//アイコンの画像番号、名前、メッセージ1,受け取る引数、メッセージ2
        char *tp;
		int i=0;
	    char message[255];
        message_cnt++;
        pre_icon[message_cnt]=icon;
		strncpy(pre_id[message_cnt],id,255);
        sprintf(message,"%s%s%s",message1,argument,message2);
		tp = strtok( message, "@" );/*↓おそらくここから問題の場所*/
		strncpy(pre_message[0][message_cnt],tp,255);
        while ( tp != NULL ) {
				i++;
                tp = strtok( NULL,"@" );
                if ( tp != NULL ) strncpy(pre_message[i][message_cnt],tp,255);
        }
}

//メッセージウィンドウを表示する関数。
void graph_mess(){//メッセージウィンドウ(メッセージボックス、アイコン、ID名、メッセージ内容、時間)
		if(clear_flag==1&&message_graph_cnt==message_cnt){message_graph_cnt++;}
		if(message_cnt==0){
		message_rest_flag=0;
		}
		else if(message_cnt-message_graph_cnt>=1){
        SetDrawBlendMode( DX_BLENDMODE_ALPHA,  200 );
	    DrawGraph(0,360,img_board[202] , FALSE );
		SetDrawBlendMode( DX_BLENDMODE_NOBLEND,  0 );

        DrawRotaGraph( 67, 360+23, (float)30/48,  0.0, img_user[pre_icon[message_graph_cnt]], FALSE );

		DrawRotaGraph( 570, 460 , 1.0 , -PI/36*global_cnt ,img_board[203], TRUE );//メッセージ次あるよボタン

        DrawFormatString( 100, 360+8, BLUE, pre_id[message_graph_cnt]);
        DrawFormatString( 48, 360+54, BLACK, pre_message[0][message_cnt]);
        DrawFormatString( 48, 360+74, BLACK, pre_message[1][message_cnt]);
        DrawFormatString( 48, 360+94, BLACK, pre_message[2][message_cnt]);
        DrawFormatStringToHandle( 106, 360+33, BLACK,small_font, "%02d:%02d" ,time_hour,time_minute);
		message_rest_flag=1;
		if(CheckStatePad(configpad.z)==1){message_graph_cnt++;}
		}
		else if(message_cnt-message_graph_cnt==0){
        SetDrawBlendMode( DX_BLENDMODE_ALPHA,  200 );
	    DrawGraph(0,360,img_board[202] , FALSE );
		SetDrawBlendMode( DX_BLENDMODE_NOBLEND,  0 );
        DrawRotaGraph( 67, 360+23, (float)30/48,  0.0, img_user[pre_icon[message_graph_cnt]], FALSE );
        DrawFormatString( 100, 360+8, BLUE, pre_id[message_cnt]);
        DrawFormatString( 48, 360+54, BLACK, pre_message[0][message_cnt]);
        DrawFormatString( 48, 360+74, BLACK, pre_message[1][message_cnt]);
        DrawFormatString( 48, 360+94, BLACK, pre_message[2][message_cnt]);
        DrawFormatStringToHandle( 106, 360+33, BLACK,small_font, "%02d:%02d" ,time_hour,time_minute);
		message_rest_flag=0;
		}
}


画像

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: DXライブラリで改行がうまくいかない

#2

投稿記事 by h2so5 » 12年前

コンパイラがないならideoneなどのオンラインコンパイラを使いましょう。
http://ideone.com/

DXライブラリの関数は使用できませんが、strtokなどの標準関数は使用できるのでチェックは可能です。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: DXライブラリで改行がうまくいかない

#3

投稿記事 by みけCAT » 12年前

Ideoneでテストしてみたところ、こうなりました。

コード:

#include <cstdio>
#include <cstring>

// GV.hの部分とmessage_add関数を貼り付け

int main(void) {
    char id[255]="namari(namari)";
    char message[2550]="なんという偽物・・・@ちょっとだけ回復";
    message_add(0,id,message);
    printf("pre_icon = %d\n",pre_icon[1]);
    printf("pre_id = %s\n",pre_id[1]);
    printf("pre_message[0] = %s\n",pre_message[0][1]);
    printf("pre_message[1] = %s\n",pre_message[1][1]);
    printf("pre_message[2] = %s\n",pre_message[2][1]);
    return 0;
}
実行結果

コード:

pre_icon = 0
pre_id = namari(namari)
pre_message[0] = なんという偽物・・・
pre_message[1] = ちょっとだけ回復
pre_message[2] = 
http://ideone.com/I5HPF9
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
namari
記事: 111
登録日時: 12年前

Re: DXライブラリで改行がうまくいかない

#4

投稿記事 by namari » 12年前

h2so5 さんが書きました:コンパイラがないならideoneなどのオンラインコンパイラを使いましょう。
http://ideone.com/

DXライブラリの関数は使用できませんが、strtokなどの標準関数は使用できるのでチェックは可能です。
ありがとうございます。web上にコンパイラなんて作れるんですね・・・。
試してみます。

>みけCATさん
ありがとうございます!まさにそういう表示が欲しかったんです。
ただ僕と同じmessage_addで通ってますね・・・?
上手くいってるところを見るに、message_addやstrtokに問題はなかったように思われるんですが、
むしろどこにバグがあったんでしょう・・・?

追記:
今試してみたところ、
ハンドルされない例外が 0x008219E6 (RyuJin.exe) で発生しました: 0xC0000005: 場所 0x0089A192 への書き込み中にアクセス違反が発生しました。
というエラーとともに強制終了した場合と、思い通りの結果になるの二択でした。(message_addの位置によって違う。)
これはポインタのいじった時に出る問題なんでしょうが、結局わかりません。
ただし、@が処理されずにそのままという状態は僕のミスでした。これは簡単に言うとそもそもmessage_addの使っていない文章表示部分でした。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: DXライブラリで改行がうまくいかない

#5

投稿記事 by みけCAT » 12年前

@を3個以上書いていませんか?
"初号発進@大学進学"という文字列のように、見えなくても文字コードの一部が'@'と一致してしまうことがあります。
デバッガで、どこで落ちているか特定できませんか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: DXライブラリで改行がうまくいかない

#6

投稿記事 by みけCAT » 12年前

5引数版のmessage_addの処理内容は、sprintfの後は3引数版とほぼ同じようなので、
sprintfしたあと、3引数版のmessage_addを呼び出すようにしたらどうですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: DXライブラリで改行がうまくいかない

#7

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

再現できるデータのパターンとソースコードを書いてもらわないと追試できなのでお願いします。
strncpyは怪しいとは思いますが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

y_wing
記事: 16
登録日時: 12年前

Re: DXライブラリで改行がうまくいかない

#8

投稿記事 by y_wing » 12年前

\r\nで試してみましょう。

アバター
namari
記事: 111
登録日時: 12年前

Re: DXライブラリで改行がうまくいかない

#9

投稿記事 by namari » 12年前

>みけCATさん
>@を3個以上書いていませんか?
文中に@が入っているものはありませんでした。

>みけCATさん
>sprintfしたあと、3引数版のmessage_addを呼び出すようにしたらどうですか?
なるほど・・・。思いつきもしませんでした。

>y_wingさん
>\r\nで試してみましょう。
残念ながらDXライブラリでこれらを使うと改行をしてくれず、代わりにその記号以降全てが表示されないんですよね。
この掲示板にも改行の件が多く出ていて、やはり使えないという結論に至りました。

>softya(ソフト屋)さん
>再現できるデータのパターンとソースコードを書いてもらわないと追試できなのでお願いします。
>strncpyは怪しいとは思いますが。

どこまで書けばいいかいまいちわからないので、
全体の流れを書いてみます。
こんなに長く貼り付けるのも申し訳ないですが・・・
テストの結果、動作の失敗、成功は常時固定のようです。

コード:

//
//GV.h 大量の引数宣言
//
#include "../../../include/DxLib.h"
#include "define.h"
#include "math.h"

#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL extern 
#endif

#include "function.h"


//画像用変数宣言部
GLOBAL int img_user[256];	//ユーザーアイコン
GLOBAL int img_block[256];   //壁、床とかの画像
GLOBAL int img_item[32];   //アイテム画像
GLOBAL int img_board[256];   //その他画像

//音楽ファイル用変数宣言部
GLOBAL int sound_se[SE_MAX];
GLOBAL int sound_bgm[BGM_MAX];
GLOBAL int bgm_flag[BGM_MAX];

//フラグ・ステータス変数
GLOBAL int MOVE_CNT_MAX;

GLOBAL int func_state;	//関数制御用変数
GLOBAL int global_cnt;	//何にでもとりあえず使う適当なカウント

GLOBAL int speed_flag;//加速するか?

GLOBAL FILE *TxtHandle_key;

GLOBAL int key_config_flag[19];//フラグが0の時、そのフラグ番号のキー設定を行なう。

GLOBAL unsigned char key_down;
GLOBAL unsigned char key_left;
GLOBAL unsigned char key_right;
GLOBAL unsigned char key_up;
GLOBAL unsigned char key_esc;
GLOBAL unsigned char key_z;
GLOBAL unsigned char key_x;
GLOBAL unsigned char key_c;
GLOBAL unsigned char key_v;
GLOBAL unsigned char key_a;
GLOBAL unsigned char key_s;
GLOBAL unsigned char key_d;
GLOBAL unsigned char key_f;
GLOBAL unsigned char key_q;
GLOBAL unsigned char key_w;
GLOBAL unsigned char key_e;
GLOBAL unsigned char key_r;
GLOBAL unsigned char key_space;
GLOBAL unsigned char key_enter;

GLOBAL int right_move_cnt;//右移動制御
GLOBAL int left_move_cnt;//左移動制御
GLOBAL int down_move_cnt;//下移動制御
GLOBAL int up_move_cnt;//上移動制御

GLOBAL int time_hour;//時間(時間)
GLOBAL int time_minute;//時間(分)
GLOBAL int small_font;
GLOBAL int large_font;
GLOBAL int more_large_font;

GLOBAL int block[HEIGHT][WIDTH];

GLOBAL int message_cnt;//何個メッセージが書かれたかの最大値を見る
GLOBAL int message_graph_cnt;//メッセージを1から順に表示する
GLOBAL int message_rest_flag;//メッセージが2つ以上残っていたら移動させない
GLOBAL int pre_icon[1024];
GLOBAL char pre_id[1024][255];//pre_id[配列数][文字数]
GLOBAL char pre_message[3][1024][255];//pre_message[行目][配列数][文字数]



GLOBAL int pause_select_number;

GLOBAL int belongings[20];   //持ち物
GLOBAL int item_MAX;//今持ってるアイテム数
GLOBAL int clear_flag;
GLOBAL int item_select_number;//今カーソルの当たっているアイテムの番号
GLOBAL int item_what_to_do;//アイテムで選択肢から選んだ制御
GLOBAL int select_number_zero_flag;//アイテムカーソルをゼロに戻すフラグ


//構造体変数宣言部
GLOBAL configpad_t configpad;//コンフィグで設定したキー情報
GLOBAL ch_t ch;			//キャラクタデータ宣言
GLOBAL pad_t pad;
GLOBAL item_t item[256];
GLOBAL item_kind kind[1000];

//
//main.cpp すべてのまとめ
//
                        case 100://メイン
							    if(CheckStatePad(configpad.x)>0 && left_move_cnt==MOVE_CNT_MAX && right_move_cnt==MOVE_CNT_MAX && up_move_cnt==MOVE_CNT_MAX && down_move_cnt==MOVE_CNT_MAX ){speed_flag=1;}
								else if(CheckStatePad(configpad.x)==0 && left_move_cnt==MOVE_CNT_MAX && right_move_cnt==MOVE_CNT_MAX && up_move_cnt==MOVE_CNT_MAX && down_move_cnt==MOVE_CNT_MAX ){speed_flag=0;}
							    calc_main();
							    graph_main();
								item_zero_flag=0;
								if(CheckStatePad(configpad.a)>0 && left_move_cnt==MOVE_CNT_MAX && right_move_cnt==MOVE_CNT_MAX && up_move_cnt==MOVE_CNT_MAX && down_move_cnt==MOVE_CNT_MAX && message_rest_flag!=1){clear_flag=1;func_state=110;}
                                break;
						case 110://pause
								pause_select_number_move();
							    pause_graph_main();
								if(pause_select_number==0 && CheckStatePad(configpad.z)==1 && item_MAX!=0){func_state=120;}
								if(pause_select_number==0 && CheckStatePad(configpad.z)==1 && item_MAX==0 && item_zero_flag==0){message_add(0,"namari(namari)","がさごそ…なかはゴミばっかり!");item_zero_flag=1;}
								if(pause_select_number==3 && CheckStatePad(configpad.z)==1){end_flag=1;}
								if(CheckStatePad(configpad.x)==1){func_state=100;}
                                break;
						case 120://道具
							    pause_graph_item();
								if(CheckStatePad(configpad.z)==1){item_belongings_number=belongings[item_select_number];func_state=130;}
								if(CheckStatePad(configpad.x)==1){func_state=110;}
                                break;
//
//graph.cpp
//
void message_add(int icon,char id[],char message[]){//アイコンの画像番号、名前、メッセージ
        char *tp;
		int i=0;
    	message_cnt++;
        pre_icon[message_cnt]=icon;
		strncpy(pre_id[message_cnt],id,255);
		tp = strtok( message, "@" );
		strncpy(pre_message[0][message_cnt],tp,255);
        while ( tp != NULL ) {
				i++;
                tp = strtok( NULL,"@" );
                if ( tp != NULL ) strncpy(pre_message[i][message_cnt],tp,255);
        }
}

void message_add(int icon,char id[],char message1[],char argument[],char message2[]){//アイコンの画像番号、名前、メッセージ1,受け取る引数、メッセージ2
        char *tp;
		int i=0;
	    char message[255];
        message_cnt++;
        pre_icon[message_cnt]=icon;
		strncpy(pre_id[message_cnt],id,255);
        sprintf(message,"%s%s%s",message1,argument,message2);
		tp = strtok( message, "@" );
		strncpy(pre_message[0][message_cnt],tp,255);
        while ( tp != NULL ) {
				i++;
                tp = strtok( NULL,"@" );
                if ( tp != NULL ) strncpy(pre_message[i][message_cnt],tp,255);
        }
}

void graph_mess(){//メッセージウィンドウ(後ろ、アイコン、ID名、メッセージ内容、時間)
		if(clear_flag==1&&message_graph_cnt==message_cnt){message_graph_cnt++;}
		if(message_cnt==0){
		message_rest_flag=0;
		}
		else if(message_cnt-message_graph_cnt>=1){
        SetDrawBlendMode( DX_BLENDMODE_ALPHA,  200 );
	    DrawGraph(0,360,img_board[202] , FALSE );
		SetDrawBlendMode( DX_BLENDMODE_NOBLEND,  0 );

        DrawRotaGraph( 67, 360+23, (float)30/48,  0.0, img_user[pre_icon[message_graph_cnt]], FALSE );

		DrawRotaGraph( 570, 460 , 1.0 , -PI/36*global_cnt ,img_board[203], TRUE );//メッセージ次あるよボタン

        DrawFormatString( 100, 360+8, BLUE, pre_id[message_graph_cnt]);
        DrawFormatString( 48, 360+54, BLACK, pre_message[0][message_cnt]);
        DrawFormatString( 48, 360+74, BLACK, pre_message[1][message_cnt]);
        DrawFormatString( 48, 360+94, BLACK, pre_message[2][message_cnt]);
        DrawFormatStringToHandle( 106, 360+33, BLACK,small_font, "%02d:%02d" ,time_hour,time_minute);
		message_rest_flag=1;
		if(CheckStatePad(configpad.z)==1){message_graph_cnt++;}
		}
		else if(message_cnt-message_graph_cnt==0){
        SetDrawBlendMode( DX_BLENDMODE_ALPHA,  200 );
	    DrawGraph(0,360,img_board[202] , FALSE );
		SetDrawBlendMode( DX_BLENDMODE_NOBLEND,  0 );
        DrawRotaGraph( 67, 360+23, (float)30/48,  0.0, img_user[pre_icon[message_graph_cnt]], FALSE );
        DrawFormatString( 100, 360+8, BLUE, pre_id[message_cnt]);
        DrawFormatString( 48, 360+54, BLACK, pre_message[0][message_cnt]);
        DrawFormatString( 48, 360+74, BLACK, pre_message[1][message_cnt]);
        DrawFormatString( 48, 360+94, BLACK, pre_message[2][message_cnt]);
        DrawFormatStringToHandle( 106, 360+33, BLACK,small_font, "%02d:%02d" ,time_hour,time_minute);
		message_rest_flag=0;
		}
}


void graph_itemmenu(){
	    int i,j;static int page=0,number=0;char *tp;char message[3][255];
		for(j=0;j<3;j++){strncpy(message[j],NULL,255);}
        SetDrawBlendMode( DX_BLENDMODE_ALPHA,  200 );
	    DrawGraph(0,60,img_board[204] , TRUE );
		SetDrawBlendMode( DX_BLENDMODE_NOBLEND,  0 );
		if(belongings[10]>0){DrawGraph(360,48,img_board[206],TRUE );
		if(CheckStatePad(configpad.right)==1 || CheckStatePad(configpad.left)==1 && select_move_flag==1){page=(page+1)%2;number=0;}}
		if(page==0){
		    for(i=0;i<=9;i++){
			    if(belongings[i]>0){DrawRotaGraph( 60, 80+28*i, 0.6,  0.0, kind[belongings[i]].img, TRUE );}
			    if(belongings[i]>0){DrawFormatString( 80,75+28*i, WHITE, kind[belongings[i]].name);}
		    }
		}
		if(page==1){
		    for(i=10;i<=19;i++){
			    if(belongings[i]>0){DrawRotaGraph( 60, 80+28*(i-10), 0.6,  0.0, kind[belongings[i]].img, TRUE );}
			    if(belongings[i]>0){DrawFormatString( 80,75+28*(i-10), WHITE, kind[belongings[i]].name);}
		    }
		}
		if(item_MAX!=0 && page==0){
			if(item_MAX<=10){
			     if(CheckStatePad(configpad.down)==1 && select_move_flag==1){number=(number+1)%item_MAX;}
		         if(CheckStatePad(configpad.up)==1 && select_move_flag==1){number=(number+item_MAX-1)%item_MAX;}
			}
			if(item_MAX>10){
			     if(CheckStatePad(configpad.down)==1 && select_move_flag==1){number=(number+1)%10;}
		         if(CheckStatePad(configpad.up)==1 && select_move_flag==1){number=(number+10-1)%10;}
			}
		}
		if(item_MAX!=0 && page==1){
		     if(CheckStatePad(configpad.down)==1 && select_move_flag==1){number=(number+1)%(item_MAX-10);}
		     if(CheckStatePad(configpad.up)==1 && select_move_flag==1){number=(number+(item_MAX-10)-1)%(item_MAX-10);}
		}
		if(select_number_zero_flag==1){number=0;select_number_zero_flag=0;page=0;}
		DrawGraph( 16, 75+number*28, img_board[205] , TRUE );

        SetDrawBlendMode( DX_BLENDMODE_ALPHA,  200 );
	    DrawGraph(0,360,img_board[202] , FALSE );
		SetDrawBlendMode( DX_BLENDMODE_NOBLEND,  0 );
        DrawRotaGraph( 67, 360+23, (float)30/48,  0.0, img_user[0], FALSE );
        DrawFormatString( 100, 360+8, BLUE, "namari(namari)");

        tp = strtok( kind[belongings[number]].explain, "@" );/*↓おそらくここから問題の場所*/
        strncpy(message[0],tp,255);
        while ( tp != NULL ) {
                i++;
                tp = strtok( NULL,"@" );
                if ( tp != NULL ) strncpy(message[i],tp,255);
        }
        DrawFormatString( 48, 360+54, BLACK, message[0]);
        DrawFormatString( 48, 360+74, BLACK, message[1]);
        DrawFormatString( 48, 360+94, BLACK, message[2]);
        DrawFormatStringToHandle( 106, 360+33, BLACK,small_font, "%02d:%02d" ,time_hour,time_minute);

		item_select_number=number+page*10;
}


//普段のゲーム画面の時、mainから呼ばれる。
void graph_main(){
		graph_back();//背景画像
		graph_block();//ブロック画像
		graph_item();//アイテム画像
        graph_up();//上部のステータス
        graph_ch();//主人公画像
		graph_mess();//メッセージ制御
		graph_status();//デバッグプレイで内部値を見る用
}
//ポーズ画面の時、mainから呼ばれる。
void pause_graph_main(){
		graph_back();
		graph_block();
		graph_item();
        graph_up();
        graph_ch();
		graph_pause();
		graph_character();
		graph_mess();
		graph_status();
}

//ポーズ画面で、道具を選択したとき、mainから呼ばれる。
void pause_graph_item(){
	    select_move_flag=1;
		graph_back();
		graph_block();
		graph_item();
        graph_up();
        graph_ch();
		graph_itemmenu();
		graph_mess();
		graph_status();
}

//
//item.cpp
//
#include "../include/GV.h"

int dont_flag=0;//拾わないフラグ

void item_get(){
	int i,j;
	for(i=0;i<=255;i++){
		if(ch.x==item[i].x && ch.y==item[i].y  && item[i].kind!=0 && speed_flag==0 && dont_flag==0 && right_move_cnt==MOVE_CNT_MAX && left_move_cnt==MOVE_CNT_MAX && down_move_cnt==MOVE_CNT_MAX && up_move_cnt==MOVE_CNT_MAX){
			for(j=0;j<=19;j++){if(belongings[j]==0){belongings[j]=item[i].kind;item_MAX=j+1;break;}}
			message_add(0,"namari(namari)","",kind[item[i].kind].name,"を手に入れた。");
			item[i].kind=0;
		}
		if(ch.x==item[i].x && ch.y==item[i].y  && item[i].kind!=0 && speed_flag==1 && dont_flag==0 && right_move_cnt==MOVE_CNT_MAX && left_move_cnt==MOVE_CNT_MAX && down_move_cnt==MOVE_CNT_MAX && up_move_cnt==MOVE_CNT_MAX){
			message_add(0,"namari(namari)","",kind[item[i].kind].name,"の上に乗った。");
			dont_flag=1;
		}
	}
	if(right_move_cnt!=MOVE_CNT_MAX || left_move_cnt!=MOVE_CNT_MAX || down_move_cnt!=MOVE_CNT_MAX || up_move_cnt!=MOVE_CNT_MAX){dont_flag=0;}
}

void item_loss(int number){
	int i;
    select_number_zero_flag=1;
	for(i=number;i<item_MAX;i++){
	belongings[i]=belongings[i+1];
	}
	item_MAX=item_MAX-1;
}

void item_main(){
	item_get();
}

void item_ini(){
/*
    strcpy(kind[].name,"");
    strcpy(kind[].explain,"");
    kind[].price=;
    kind[].img=LoadGraph("dat/img/.png");
	kind[].alternative=;
	strcpy(	kind[].select[0],"");
    strcpy(	kind[].select[1],"");
    strcpy(	kind[].select[2],"");
    strcpy(	kind[].select[3],"");
    strcpy(	kind[].select[4],"");
    strcpy(	kind[].select[5],"");
    strcpy(	kind[].select[6],"");
    strcpy(	kind[].select[7],"");
    strcpy(	kind[].select[8],"");
    strcpy(	kind[].select[9],"");
*/

    strcpy(kind[1].name,"カラーパン");
    strcpy(kind[1].explain,"なんという偽物・・・ちょっとだけ回復");
    kind[1].price=200;
    kind[1].img=LoadGraph("dat/img/item_sample.png");
	kind[1].alternative=3;//食べる、投げる、置く
    strcpy(	kind[1].select[0],"食べる");
    strcpy(	kind[1].select[1],"投げる");
    strcpy(	kind[1].select[2],"置く");
}

int item_action(int item_kind,int action){


	if(item_kind==1){
		switch(action){
			case 0://食べる
				ch.hunger=ch.hunger+20;
				if(ch.hunger>ch.hunger_max){ch.hunger=ch.hunger_max;message_add(0,"namari(namari)","もぐもぐ・・・もう食べられないよ・・・");}
				else{message_add(0,"namari(namari)","もぐもぐ・・・少しだけお腹が膨れた");}
				item_loss(item_select_number);
				return 100;
            case 1://投げる
			    message_add(0,"namari(namari)","ぽいっ");
				return 100;
            case 2://置く
                message_add(0,"namari(namari)","",kind[item_kind].name,"を置いておいた。");
				return 100;
		};
	}
 return 100;
}
message_add(0,"namari(namari)","",kind[item.kind].name,"を@手に入れた。");のように
302行目のmessage_addに@をつけると、
うまく作動します。
362行目以降のmessage_addに@をつけても、強制終了されます。
正しくは、@をつけなくても、常時、pause_graph_itemを呼び出したら強制終了されます。

http://dl1.getuploader.com/g/namari2/41/progress2.png
func_state(main.cppにおいて、switch文に受け取られる引数)が100
メニューキーを押すと、110に飛ぶ。

http://dl1.getuploader.com/g/namari2/42/progress3.png
func_state(main.cppにおいて、switch文に受け取られる引数)が110
このあと、道具にカーソルを当てて、決定キーを押すと120に飛ぶ。
しかし、120に飛んだ瞬間強制終了。

http://dl1.getuploader.com/g/namari2/43/progress4.png
func_state(main.cppにおいて、switch文に受け取られる引数)が120だと思われるもの。
強制終了してしまった。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: DXライブラリで改行がうまくいかない

#10

投稿記事 by みけCAT » 12年前

毎フレームstrtokしているのですか?
一旦別の変数にコピーしてからstrtokするか、初期化でstrtokしてそのデータを保持しておくべきだと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: DXライブラリで改行がうまくいかない

#11

投稿記事 by みけCAT » 12年前

namari さんが書きました:message_add(0,"namari(namari)","",kind[item.kind].name,"を@手に入れた。");のように
302行目のmessage_addに@をつけると、
うまく作動します。
362行目以降のmessage_addに@をつけても、強制終了されます。
正しくは、@をつけなくても、常時、pause_graph_itemを呼び出したら強制終了されます。

正しい動作が強制終了なのですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: DXライブラリで改行がうまくいかない

#12

投稿記事 by みけCAT » 12年前

namari さんが書きました:362行目以降のmessage_addに@をつけても、強制終了されます。
strtokで文字列リテラルを書き換えるのは、まずいかもしれません。
IdeoneでのテストでもRuntime Errorになりました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: DXライブラリで改行がうまくいかない

#13

投稿記事 by みけCAT » 12年前

graph_itemmenu関数内、243行目で使われているiの初期化をしていないようですね。
前にあるfor文でi=10もしくはi=20になっているか、もしくは全く初期化されず不定の値であり、
messageの範囲外アクセスでアクセス違反になる可能性があると思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
namari
記事: 111
登録日時: 12年前

Re: DXライブラリで改行がうまくいかない

#14

投稿記事 by namari » 12年前

>みけCATさん
>毎フレームstrtokしているのですか?
>一旦別の変数にコピーしてからstrtokするか、初期化でstrtokしてそのデータを保持しておくべきだと思います。

はい。変更してみました。
これはmessage_addではなく、238行目にあたる部分のことですよね?

>正しい動作が強制終了なのですか?
変な表現でしたね、すみません。@を付けるかどうかに関わらずいつも強制終了になってしまうバグです。

>strtokで文字列リテラルを書き換えるのは、まずいかもしれません。
>IdeoneでのテストでもRuntime Errorになりました。
すみません、いまいち問題がわからないです・・・。

>graph_itemmenu関数内、243行目で使われているiの初期化をしていないようですね。
>前にあるfor文でi=10もしくはi=20になっているか、もしくは全く初期化されず不定の値であり、
>messageの範囲外アクセスでアクセス違反になる可能性があると思います。
致命的ですね・・・。まさにエラー内容もポインタのアクセス違反だったので、これが原因だと思いましたが、
書き直しても、同様の挙動となりました。

以下は書き直したコードです。

コード:

//
//GV.h 大量の引数宣言
//

GLOBAL char item_explain_message[3][255];//アイテム説明文の制御

//
//main.cpp すべてのまとめ
//

//変更なし。

//
//graph.cpp
//
void graph_itemmenu(){
	    int i=0,j;static int page=0,number=0;char *tp;
		for(j=0;j<3;j++){strncpy(item_explain_message[j],NULL,255);}
        SetDrawBlendMode( DX_BLENDMODE_ALPHA,  200 );
	    DrawGraph(0,60,img_board[204] , TRUE );
		SetDrawBlendMode( DX_BLENDMODE_NOBLEND,  0 );
		if(belongings[10]>0){DrawGraph(360,48,img_board[206],TRUE );
		if(CheckStatePad(configpad.right)==1 || CheckStatePad(configpad.left)==1 && select_move_flag==1){page=(page+1)%2;number=0;}}
		if(page==0){
		    for(i=0;i<=9;i++){
			    if(belongings[i]>0){DrawRotaGraph( 60, 80+28*i, 0.6,  0.0, kind[belongings[i]].img, TRUE );}
			    if(belongings[i]>0){DrawFormatString( 80,75+28*i, WHITE, kind[belongings[i]].name);}
		    }
		}
		if(page==1){
		    for(i=10;i<=19;i++){
			    if(belongings[i]>0){DrawRotaGraph( 60, 80+28*(i-10), 0.6,  0.0, kind[belongings[i]].img, TRUE );}
			    if(belongings[i]>0){DrawFormatString( 80,75+28*(i-10), WHITE, kind[belongings[i]].name);}
		    }
		}
		if(item_MAX!=0 && page==0){
			if(item_MAX<=10){
			     if(CheckStatePad(configpad.down)==1 && select_move_flag==1){number=(number+1)%item_MAX;}
		         if(CheckStatePad(configpad.up)==1 && select_move_flag==1){number=(number+item_MAX-1)%item_MAX;}
			}
			if(item_MAX>10){
			     if(CheckStatePad(configpad.down)==1 && select_move_flag==1){number=(number+1)%10;}
		         if(CheckStatePad(configpad.up)==1 && select_move_flag==1){number=(number+10-1)%10;}
			}
		}
		if(item_MAX!=0 && page==1){
		     if(CheckStatePad(configpad.down)==1 && select_move_flag==1){number=(number+1)%(item_MAX-10);}
		     if(CheckStatePad(configpad.up)==1 && select_move_flag==1){number=(number+(item_MAX-10)-1)%(item_MAX-10);}
		}
		if(select_number_zero_flag==1){number=0;select_number_zero_flag=0;page=0;}
		DrawGraph( 16, 75+number*28, img_board[205] , TRUE );

        SetDrawBlendMode( DX_BLENDMODE_ALPHA,  200 );
	    DrawGraph(0,360,img_board[202] , FALSE );
		SetDrawBlendMode( DX_BLENDMODE_NOBLEND,  0 );
        DrawRotaGraph( 67, 360+23, (float)30/48,  0.0, img_user[0], FALSE );
        DrawFormatString( 100, 360+8, BLUE, "namari(namari)");

        tp = strtok( kind[belongings[number]].explain, "@" );/*↓おそらくここから問題の場所*/
        strncpy(item_explain_message[0],tp,255);
        while ( tp != NULL ) {
                i++;
                tp = strtok( NULL,"@" );
                if ( tp != NULL ) strncpy(item_explain_message[i],tp,255);
        }
        DrawFormatString( 48, 360+54, BLACK, item_explain_message[0]);
        DrawFormatString( 48, 360+74, BLACK, item_explain_message[1]);
        DrawFormatString( 48, 360+94, BLACK, item_explain_message[2]);
        DrawFormatStringToHandle( 106, 360+33, BLACK,small_font, "%02d:%02d" ,time_hour,time_minute);

		item_select_number=number+page*10;
}
 
//
//item.cpp
//

//変更なし


アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: DXライブラリで改行がうまくいかない

#15

投稿記事 by みけCAT » 12年前

namari さんが書きました:>みけCATさん
>毎フレームstrtokしているのですか?
>一旦別の変数にコピーしてからstrtokするか、初期化でstrtokしてそのデータを保持しておくべきだと思います。

はい。変更してみました。
これはmessage_addではなく、238行目にあたる部分のことですよね?
申し訳ないですが、変更されているようには見えません。
新しいコードで59行目以降です。
namari さんが書きました:>正しい動作が強制終了なのですか?
変な表現でしたね、すみません。@を付けるかどうかに関わらずいつも強制終了になってしまうバグです。
わかりました。
namari さんが書きました:>strtokで文字列リテラルを書き換えるのは、まずいかもしれません。
>IdeoneでのテストでもRuntime Errorになりました。
すみません、いまいち問題がわからないです・・・。
strtokは、渡された文字列を直接書き換えます。
一方、文字列リテラルは一般には書き換えられない(書き換えようとした場合の動作は未定義)と言われています。
テストコード:http://ideone.com/xVU332
namari さんが書きました:>graph_itemmenu関数内、243行目で使われているiの初期化をしていないようですね。
>前にあるfor文でi=10もしくはi=20になっているか、もしくは全く初期化されず不定の値であり、
>messageの範囲外アクセスでアクセス違反になる可能性があると思います。
致命的ですね・・・。まさにエラー内容もポインタのアクセス違反だったので、これが原因だと思いましたが、
書き直しても、同様の挙動となりました。
for文でiの値が書き変わった場合に、そのまま初期化されないように見えます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
namari
記事: 111
登録日時: 12年前

Re: DXライブラリで改行がうまくいかない

#16

投稿記事 by namari » 12年前

>みけCATさん
結局アイテムの説明文に関しては、@で改行を行わず、3行分の説明文をそれぞれ最初につくることで妥協しました。

これでバグはすべてなくなり、改行制御が完成しました。
みなさん、特にみけCATさん、本当にありがとうございました。

一応解決は押しますが、実はmessage_addの5引数版がしっかり動くのに、message_addの3引数版が動かないことから推測して、
おまじない的なバグ修正をしてしまったところがあります。

コード:

void message_add(int icon,char id[],char message1[]){//アイコンの画像番号、名前、メッセージ
        char *tp;
		int i=0,j;
	    char message[255];
    	message_cnt++;
        pre_icon[message_cnt]=icon;
		strncpy(pre_id[message_cnt],id,255);
		for(j=0;j<3;j++){sprintf(pre_message[j][message_cnt],"");}//初期化
        sprintf(message,"%s",message1);//なんだか意味のないくだりっぽいけど、ここでヌル文字を挿入してるみたいなことをしている。と思う。ないと動かない。
		tp = strtok( message, "@" );
		strncpy(pre_message[0][message_cnt],tp,255);
        while ( tp != NULL ) {
				i++;
                tp = strtok( NULL,"@" );
                if ( tp != NULL ) strncpy(pre_message[i][message_cnt],tp,255);
        }
}

void message_add(int icon,char id[],char message1[],char argument[],char message2[]){//アイコンの画像番号、名前、メッセージ1,受け取る引数、メッセージ2
        char *tp;
		int i=0,j;
	    char message[255];
        message_cnt++;
        pre_icon[message_cnt]=icon;
		strncpy(pre_id[message_cnt],id,255);
		for(j=0;j<3;j++){sprintf(pre_message[j][message_cnt],"");}
        sprintf(message,"%s%s%s",message1,argument,message2);
		tp = strtok( message, "@" );
		strncpy(pre_message[0][message_cnt],tp,255);
        while ( tp != NULL ) {
				i++;
                tp = strtok( NULL,"@" );
                if ( tp != NULL ) strncpy(pre_message[i][message_cnt],tp,255);
        }
}

もう完成したので問題はないですが、もしわかったのなら、この謎を教えてくださると嬉しいです。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: DXライブラリで改行がうまくいかない

#17

投稿記事 by みけCAT » 12年前

namari さんが書きました:もう完成したので問題はないですが、もしわかったのなら、この謎を教えてくださると嬉しいです。
これではわかりませんか?
みけCAT さんが書きました:
namari さんが書きました:>strtokで文字列リテラルを書き換えるのは、まずいかもしれません。
>IdeoneでのテストでもRuntime Errorになりました。
すみません、いまいち問題がわからないです・・・。
strtokは、渡された文字列を直接書き換えます。
一方、文字列リテラルは一般には書き換えられない(書き換えようとした場合の動作は未定義)と言われています。
テストコード:http://ideone.com/xVU332
ちなみに、messageはローカル変数ですが、strncpyでグローバル変数にコピーしているので、
スコープによりデータが消える心配はありません。
【追記】
C言語/C++では、関数の引数をchar* hogeを指定するのとchar hoge[]と指定するのはほぼ同じことです。
すなわち、どちらも呼び出し元のデータが直接見え、操作できることになります。
引数で与えられた文字列を書き換える仕様でないときは、const char hoge[]という引数にするといいです。
【追記ここまで】

また、lstrcpyでいいはずの文字列コピー処理(8行目と9行目)にわざわざsprintfを用いているのが気になります。
バッファオーバーランを防ぐ意味でstrncpyを使うのは大丈夫そうです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

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