ページ 11

動作が停止してしまいます

Posted: 2012年8月09日(木) 14:30
by NATTO
[1] 質問文
 [1.1]メモ帳のテキストを読み込みすることが目標です。 
 [1.2]  mymain.cpp

コード:

#include "myhelper.h"
#include "mymain.h"

//画像ハンドル
int medaka1;
int kotaewaku[3];

//問題記録変数
Mondai allQ[4];
int g_usedQ_num;
int g_janru = 0;

//問題読み込み関数
int LoadQuestion(char *pfname){
	int f = 0;  //ファイルハンドル
	char buf[1024];  //テキスト一時読み込み一時バッファ

	f = FileRead_open(pfname);
	if (f==0) return -1;  //読み込みエラー

	g_usedQ_num = 0;
	while( FileRead_eof(f) == 0 )  //終端チェック
	{
		//一行読み込み
		FileRead_gets( buf, 1023, f ) ;
		int qn,qk,qm;
		sscanf_s(buf, "%d,%d,%d", &qn, &qk, &qm);
		Mondai m;
		m.Qnum = qn;
		m.Qkeishiki = qk;
		m.marubatu = qm;
		//ZeroMemory(buf, sizeof(buf) * 1024);
		char qb[80];
		FileRead_gets( qb, 78, f ) ;
		memcpy(m.Qbunshou, qb, sizeof(m.Qbunshou));
		FileRead_gets( buf, 1023, f ) ;
		char Ao[40],At[40];
		sscanf_s(buf, "%s,%s", &Ao, &At);
		memcpy(m.Answer_one, Ao, sizeof(m.Answer_one));
		memcpy(m.Answer_two, At, sizeof(m.Answer_two));
		ZeroMemory(buf, sizeof(buf) * 1024);
		FileRead_gets( buf, 1023, f ) ;
		char a1[20],a2[20],a3[20];
		sscanf_s(buf, "%s,%s,%s", &a1, &a2, &a3);
		memcpy(m.ans_one, a1, sizeof(m.ans_one));
		memcpy(m.ans_two, a2, sizeof(m.ans_two));
		memcpy(m.ans_three, a3, sizeof(m.ans_three));
		memcpy(allQ[g_usedQ_num].ans_one, m.ans_one, sizeof(allQ[g_usedQ_num].ans_one));
		memcpy(allQ[g_usedQ_num].ans_two, m.ans_two, sizeof(allQ[g_usedQ_num].ans_two));
		memcpy(allQ[g_usedQ_num].ans_three, m.ans_three, sizeof(allQ[g_usedQ_num].ans_three));
		memcpy(allQ[g_usedQ_num].Answer_one, m.Answer_one, sizeof(allQ[g_usedQ_num].Answer_one));
		memcpy(allQ[g_usedQ_num].Answer_two, m.Answer_two, sizeof(allQ[g_usedQ_num].Answer_two));
		memcpy(allQ[g_usedQ_num].Qbunshou, m.Qbunshou, sizeof(allQ[g_usedQ_num].Qbunshou));
		allQ[g_usedQ_num].marubatu = m.marubatu;
		allQ[g_usedQ_num].Qkeishiki = m.Qkeishiki;
		allQ[g_usedQ_num].Qnum = m.Qnum;
		//memcpy(allQ[g_usedQ_num], m, sizeof(allQ[g_usedQ_num]));
		g_usedQ_num++;
	}
	//ファイルを閉じる
	FileRead_close( f ) ;
	return 0;
}

//メインループ
void MyMain(){

	DrawBox( 0,0,640,480,GetColor(255,255,255),TRUE);
	//DrawGraph(0,0, medaka1, FALSE);
	SetFontSize(32);
	ChangeFont("MS Pゴシック");
	DrawFormatString(70,170,GetColor(255,0,0),"(Z)物語系 全1問");
	DrawFormatString(70,210,GetColor(255,255,0),"(X)人物系 全1問");
	DrawFormatString(70,250,GetColor(0,255,0),"(C)スキル系 全1問");
	DrawFormatString(70,290,GetColor(0,0,255),"(A)物語(難問)系 全1問");
	SetFontSize(40);
	DrawFormatString(70,370,GetColor(0,0,0),"ジャンルを選ぶがよい!");
	SetFontSize(48);
	DrawFormatString(100,50,GetColor(0,0,0),"めだかボックス問題集");
	DrawFormatString(100,100,GetColor(0,0,0),"~Quiz Of Medaka~");

	int key = GetJoypadInputState( DX_INPUT_KEY_PAD1 );
	if( key & PAD_INPUT_A ) g_janru = 1;
	if( key & PAD_INPUT_B ) g_janru = 2;
	if( key & PAD_INPUT_C ) g_janru = 3;
	if( key & PAD_INPUT_X ) g_janru = 4;

	/*switch(g_janru)
	case 1:
	    break;

	case 2:
		break;

	case 3:
		break;

	case 4:
		break;*/

}

//色々なファイルの読み込み
int LoadFiles(){
	//画像ファイルの読み込み
	//if ( medaka1 = LoadGraph("media\\めだか.png") == -1) return -1;
	if (LoadQuestion("media\\Que_monogatari.txt")==-1) return -1;
	kotaewaku[1] = LoadGraph("media\\答え枠1.png");
	kotaewaku[2] = LoadGraph("media\\答え枠2.png");
	kotaewaku[3] = LoadGraph("media\\答え枠3.png");
	if ( kotaewaku[1] == -1 || kotaewaku[2] == -1 || kotaewaku[3] == -1){
		return -1;
	}

	return 1;
}
  mymain.h

コード:

//他から呼び出されるMyMainの関数宣言
void MyMain();
int LoadFiles();
  myhelper.cpp

コード:

#include "myhelper.h"
#include "mymain.h"

//グローバル変数
int g_lasttime;					//前回のループ終了時間(ミリ秒)
float g_frametime = 0.017f;		//1フレームの表示にかかった時間(秒)


// プログラムの開始関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
						LPSTR lpCmdLine, int nCmdShow )
{
	if (strcmp(lpCmdLine, "-f") != 0) ChangeWindowMode(TRUE);
	//DXライブラリの初期化処理
	if( DxLib_Init() == -1 ) return -1;
	//描画対象を裏画面に設定
	SetDrawScreen(DX_SCREEN_BACK);
	//ファイルの読み込み
	if( LoadFiles() == -1 ) return -1;

	//画面サイズ(当たり判定用)の初期化
	Rect2D gf = { {-64,-64}, {640+64,480+64}, 768, 608};
	memcpy( &g_framerect, &gf, sizeof(Rect2D) );
	//スクロール開始点の初期化
	g_current_field_pos.x = 0;
	g_current_field_pos.y = 0;
	//ステージサイズの初期化
	Rect2D gs = { {0,0}, {639,479}, 640,480} ;
	memcpy( &g_stagesize, &gs, sizeof(Rect2D) );

	//メインループ
	g_lasttime = GetNowCount() & INT_MAX;
	while(ProcessMessage()==0 && CheckHitKey(KEY_INPUT_ESCAPE)==0){
		ClsDrawScreen();	//画面を消去
		MyMain();
		ScreenFlip();		//画面を切り替え
		//1ループにかかった時間を計測
		int curtime = GetNowCount() & INT_MAX;
		g_frametime = (float)(curtime - g_lasttime) / 1000.0f;
		g_lasttime = curtime;
		if (g_frametime > 0.03f) g_frametime = 0.03f;
	}

	DxLib_End() ;			// DXライブラリ使用の終了処理
	return 0 ;				// ソフトの終了 
}


//スクロール用データ
Rect2D g_framerect = { {-64,-64}, {640+64,480+64}, 768, 608};	//画面領域(当たり判定)
Point2D g_current_field_pos = {0,0};	//現在の左上座標
Rect2D g_stagesize = { {0,0}, {639,479}, 640,480};	//ステージサイズ

//スクロール用関数
//データ上の座標を画面表示用座標に変更する
Point2D PosInView(Point2D in){
	return SubVector(in, g_current_field_pos);
}
//そのX座標版とY座標版
int XInView(float inx){
	return (int)(inx - g_current_field_pos.x);
}
int YInView(float iny){
	return (int)(iny - g_current_field_pos.y);
}
/*画面を左へスクロール
(自キャラから200ピクセルを保つようスクロール)*/
void ScrollToLeft(float jikiposx){
	//スクロール可能かをチェック
	if ((int)jikiposx - SCROLL_LIMIT > (int)g_stagesize.lefttop.x){
		g_current_field_pos.x = jikiposx - SCROLL_LIMIT;
		g_framerect.lefttop.x = g_current_field_pos.x - 64;
		g_framerect.lefttop.y = g_current_field_pos.y - 64;
		g_framerect.rightbottom.x = g_current_field_pos.x + 640 + 64;
		g_framerect.rightbottom.y = g_current_field_pos.y + 480 + 64;
	}
}
/*画面を右へスクロール
(自キャラから200ピクセルを保つようスクロール)*/
void ScrollToRight(float jikiposx){
	if ((int)jikiposx + SCROLL_LIMIT < (int)g_stagesize.rightbottom.x){
		g_current_field_pos.x = jikiposx - (640 - SCROLL_LIMIT);
		g_framerect.lefttop.x = g_current_field_pos.x - 64;
		g_framerect.lefttop.y = g_current_field_pos.y - 64;
		g_framerect.rightbottom.x = g_current_field_pos.x + 640 + 64;
		g_framerect.rightbottom.y = g_current_field_pos.y + 480 + 64;
	}
}
/*画面を上へスクロール*/
void ScrollToUp(float jikiposy){
	//スクロール可能かをチェック
	if ((int)jikiposy - SCROLL_LIMIT > (int)g_stagesize.lefttop.y){
		g_current_field_pos.y = jikiposy - SCROLL_LIMIT;
		g_framerect.lefttop.x = g_current_field_pos.x - 64;
		g_framerect.lefttop.y = g_current_field_pos.y - 64;
		g_framerect.rightbottom.x = g_current_field_pos.x + 640 + 64;
		g_framerect.rightbottom.y = g_current_field_pos.y + 480 + 64;
	}
}
/*画面を下へスクロール*/
void ScrollToDown(float jikiposy){
	if ((int)jikiposy + SCROLL_LIMIT < (int)g_stagesize.rightbottom.y){
		g_current_field_pos.y = jikiposy - (480 - SCROLL_LIMIT);
		g_framerect.lefttop.x = g_current_field_pos.x - 64;
		g_framerect.lefttop.y = g_current_field_pos.y - 64;
		g_framerect.rightbottom.x = g_current_field_pos.x + 640 + 64;
		g_framerect.rightbottom.y = g_current_field_pos.y + 480 + 64;
	}
}

/*スクロールを計算に入れた描画関数*/
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness){
	DrawLine(XInView(x1), YInView(y1), XInView(x2), YInView(y2), 
			Color, Thickness);
}
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag){
	DrawCircle(XInView(x), YInView(y), (int)r, Color, FillFlag);
}

/*アニメーション表示をする関数
画像を表示する座標xとy、
イメージデータの配列imgarray、総コマ数framenum、アニメの表示速度fps
アニメーション用の一時データanimtmpを引数とする。
1枚絵を表示する場合は、
imgarrayにint型変数のアドレス、allframeに1、fpsに1.0fを指定すること。
*/
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
				   int *imgarray, int allframe, float fps){
	//現在の経過秒数を求める
	float t = (float)( GetNowCount() & INT_MAX );
	//表示すべきコマ数を求める
	int animpat = (int)(t/(1000/fps)) % allframe;
	//そのコマを描画
	DrawRotaGraph(XInView(x),YInView(y), ExtRate, Angle, imgarray[animpat], TRUE, TurnFlag);
}

/*ベクトルを作成する関数
入力ベクトルを正規化してから長さを掛ける*/
Vector CreateVector(Vector in, float veclen){
	Vector result;
	in = Normalize(in);
	result.x = in.x * veclen;
	result.y = in.y * veclen;
	return result;
}
/*ベクトルの足し算を行う関数*/
Vector AddVector(Vector v1, Vector v2){
	Vector result;
	result.x = v1.x + v2.x;
	result.y = v1.y + v2.y;
	return result;
}
/*ベクトルの引き算を行う関数
座標からベクトルを求める場合にも使える
その場合v1は終点、v2は始点とする*/
Vector SubVector(Vector v1, Vector v2){
	Vector result;
	result.x = v1.x - v2.x;
	result.y = v1.y - v2.y;
	return result;
}

/*座標に速度ベクトルを足す関数(等速運動用)
g_frametimeを考慮する*/
Vector AddVectorInFrameTime(Vector pos, Vector speed){
	Vector result;
	result.x = pos.x + speed.x * g_frametime;
	result.y = pos.y + speed.y * g_frametime;
	return result;
}
/*座標に速度ベクトルと加速度を足す関数(等加速度運動用)
g_frametimeを考慮する*/
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel){
	Vector result;
	result.x = pos.x + speed.x * g_frametime + accel.x * pow(g_frametime,2) / 2;
	result.y = pos.y + speed.y * g_frametime + accel.y * pow(g_frametime,2) / 2;
	return result;
}
/*ベクトルを正規化する関数*/
Vector Normalize(Vector in){
	Vector result;
	float l = sqrt( in.x * in.x + in.y * in.y );
	result.x = in.x / l;
	result.y = in.y / l;
	return result;
}
/*内積を求める関数*/
float DotProduct(Vector v1, Vector v2){
	return v1.x * v2.x + v1.y * v2.y;
}
/*外積を求める関数*/
float CrossProduct(Vector v1, Vector v2){
	return v1.x * v2.y - v1.y * v2.x;
}
/*ベクトルを回転させる関数*/
Vector RotateVector(Vector in, float radian){
	Vector result;
	result.x = -sin(radian)*in.y + cos(radian)*in.x;
	result.y =  cos(radian)*in.y + sin(radian)*in.x;
	return result;
}
/*ベクトルの長さの二乗を求める関数
長さが必要なときはsqrtで平方根を求める*/
float VectorLengthSquare(Vector in){
	return in.x * in.x + in.y * in.y;
}


/*Line2Dを描画する関数*/
void DrawLine2D(Line2D in, int Color, int Thickness){
	DrawLine(XInView(in.startpos.x), YInView(in.startpos.y),
		XInView(in.endpos.x), YInView(in.endpos.y), Color, Thickness);
}
/*Ball2Dを描画する関数*/
void DrawBall2D(Ball2D in, int Color, int FillFlag){
	DrawCircle(XInView(in.position.x), YInView(in.position.y),
		(int)in.hankei, Color, FillFlag);
}
/*線の傾きを求めてLine2Dのメンバkatamukiにセットする関数*/
void SetLine2DKatamuki(Line2D *in){
	in->katamuki = atan2(in->endpos.y - in->startpos.y, in->endpos.x - in->startpos.x);
}


/*Ball2DとLine2Dの当たり判定を行う関数*/
bool HitTestLineAndBall(Line2D linein, Ball2D ballin){
	Vector avec, bvec;
	avec = SubVector(ballin.position, linein.startpos);
	bvec = SubVector(linein.endpos, linein.startpos);
	float dot = DotProduct(avec, bvec);				//内積を求める
	float bl = VectorLengthSquare(bvec);		//ベクトルbの長さの二乗を求める
	if ( (dot > -ZEROVALUE) && (dot < bl) ) {		//衝突の可能性有り
		//円と線の距離を求める
		//ボールの中心から垂直におろした線の交点を求める
		Vector bnvec = Normalize(bvec);					//ベクトルbの正規化
		float dot2 = DotProduct(avec, bnvec);
		bnvec.x *= dot2;						
		bnvec.y *= dot2; 
		Point2D kouten = AddVector(linein.startpos, bnvec);
		Vector dist = SubVector(ballin.position, kouten);
		float al = VectorLengthSquare(dist);
#ifdef _DEBUG
		DrawBall2D(ballin, GetColor(128,128,128),FALSE);
		DrawLineInView(linein.startpos.x, linein.startpos.y,
			linein.startpos.x+avec.x, linein.startpos.y+avec.y, 65535,1);
		DrawLineInView(linein.startpos.x, linein.startpos.y, 
			kouten.x, kouten.y, GetColor(255,0,0),1);
		DrawLineInView(kouten.x, kouten.y, 
			ballin.position.x, ballin.position.y, GetColor(255,0,0),1);
#endif
		if ( al < (ballin.hankei * ballin.hankei)  ){
			return TRUE;
		}
	}
	return FALSE;
}

/*頂点と線の位置関係を調べる関数
線の左または上側にあればTRUE、右または下側にあればFALSEを返す*/
bool IsPointAtLineFace(Line2D linein, Point2D ptin){
	Vector avec, bvec;
	avec = SubVector(ptin, linein.startpos);
	bvec = SubVector(linein.endpos, linein.startpos);
	float cross = CrossProduct(avec, bvec);
	//外積が正なら点は線の表側(左側)にある
	if ( cross > -ZEROVALUE )	return TRUE;
	return FALSE;
}

/*Line2D同士の当たり判定を行う関数*/
bool HitTestLineAndLine(Line2D line1, Line2D line2){
	Vector avec, bvec, cvec, dvec, evec, fvec;
	avec = SubVector(line1.endpos, line1.startpos);		//a2-a1
	bvec = SubVector(line2.startpos, line1.startpos);	//b1-a1
	cvec = SubVector(line2.endpos, line1.startpos);		//b2-a1
	dvec = SubVector(line2.endpos, line2.startpos);		//b2-b1
	evec = SubVector(line1.startpos, line2.startpos);	//a1-b1
	fvec = SubVector(line1.endpos, line2.startpos);		//a2-b1

	float a,b,c,d;
	a = CrossProduct(avec, bvec);
	b = CrossProduct(avec, cvec);
	c = CrossProduct(dvec, evec);
	d = CrossProduct(dvec, fvec);
	
	if( ((a*b) < ZEROVALUE) && ((c*d) < ZEROVALUE) ){
		return TRUE;
	}
	return FALSE;
}


/*Ball2D同士の当たり判定を行う関数*/
bool HitTestBallAndBall(Ball2D ball1, Ball2D ball2){
#ifdef _DEBUG
		DrawBall2D(ball1, GetColor(128,128,128),FALSE);
		DrawBall2D(ball2, GetColor(128,128,128),FALSE);
#endif
	if ( pow(ball1.position.x - ball2.position.x, 2) + pow(ball1.position.y - ball2.position.y,2)
		< pow(ball1.hankei+ball2.hankei, 2) ){
		return TRUE;
	}else{
		return FALSE;
	}
}

/*Point2DとRect2Dの当たり判定を行う関数*/
bool HitTestPointAndBox(Rect2D rect, Point2D pt){
	if ( (rect.lefttop.x < pt.x) && (pt.x < rect.rightbottom.x) &&
		(rect.lefttop.y < pt.y) && (pt.y < rect.rightbottom.y) ){
			return TRUE;
	}
	return FALSE;
}

//シンプルタイマー関数
const int MAXTIMER = 32;
int g_goaltimes[MAXTIMER];
/*タイマーに目標値を設定して始動させる関数
目標値timeはミリ秒で設定する*/
void SetSimpleTimer(int idx, int time){
	if(idx>MAXTIMER) return;
	g_goaltimes[idx] = (GetNowCount() & INT_MAX) + time;
}
/*タイマーの結果を取得する関数
返値が負ならまだ目標値に達していない
正なら目標値を超えている*/
int GetPassedTime(int idx){
	return (GetNowCount() & INT_MAX) - g_goaltimes[idx];
}
  myhelper.h

コード:

#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
	float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
	Point2D startpos, endpos;
	float katamuki;	//傾きをラジアン値で記録
	Vector speed;	//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
	Point2D position;
	float hankei;	//半径
};
//四角形を記録する構造体
struct Rect2D{
	Point2D lefttop;
	Point2D rightbottom;
	float width;
	float height;
};
//問題についての構造体
struct Mondai{
	int Qnum;         //問題数
	int Qkeishiki;    //問題形式1=4択 2=記述問題 3=○×クイズ
	int marubatu;     //○か×か 1=○ 2=×
	char Qbunshou[80]; //問題文
	char Answer_one[40];  //答え1つ目(正しい)
	char Answer_two[40];  //答え2つ目(間違ってはいない)
	char ans_one[20],ans_two[20],ans_three[20];  //4択の間違え1、2、3
};

//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
				   int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;	//画面領域(当たり判定)
extern Point2D g_current_field_pos;	//現在の左上座標
extern Rect2D g_stagesize;	//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
メモ帳
1,2,0
めだかボックス第1巻の最初の一言は何か。
世界は平凡か?,世界は平凡か?
0,0,0

char型に0を入れていますが、あまり気にしないでいただけると嬉しいです…

というコードでmymain.cppとmymain.hは自分で書いたコードで、
myhelper.cppとmyhelper.hは解説書についていたコードです。

 [1.3]ウィンドウが開いてすぐに、○○○.txtは動作を停止しました、というメッセージがでてしまいます。 
 [1.4] どうすれば正しくメモ帳が読み込まれるのかがわかりません。
     できたら、説明もしていただけると嬉しいです。なにぶん、初めての状況ですので…

[2] 環境  
 [2.1] OS : Windows
 [2.2] コンパイラ名 : VC++ 2008EE DXLib使用

[3] その他
 ・あまり理解できないかもしれないので、わかりやすく説明、回答していただけると、とてもありがたいです!


とても長いコードですいません。
抜粋がしづらかったので…

Re: 動作が停止してしまいます

Posted: 2012年8月09日(木) 15:18
by みけCAT
まず、本当に読み込みたいのはメモ帳に書かれている文字列ですか?それともテキストファイルですか?
後者のほうが前者より非常に楽です。
前者は他プロセス内へのメモリの確保など、高度な技術が必要です。
(参考:http://www.inasoft.org/lv2csv/lvcsvcom/chapter3.html

次に、scanf系の関数でchar型の配列に文字列を読み込む時は、変数名の前に&をつけてはいけません。
そして、sscanf_sではどうかわかりませんが、scanfではカンマ区切りの文字列は連結して読み込まれてしまいます。
strtokなどを使用するべきだと思います。
参考:http://ideone.com/tK5nV

コード:

#include <stdio.h>
 
int main(void) {
	char test1[10]="error";
	char test2[10]="error";
	scanf("%s,%s",test1,test2);
	printf("%s,%s\n",test1,test2);
	return 0;
}
NATTO さんが書きました:char型に0を入れていますが、あまり気にしないでいただけると嬉しいです…
私も主に競技プログラミングで、フラグとしてchar型を用いて0/1を代入することがあるので、あまり気にしません。

Re: 動作が停止してしまいます

Posted: 2012年8月09日(木) 17:15
by NATTO
みけCATさん、ありがとうございます!
sscanf_s関数の&については修正しました。
デバッグしてみたところ、
mymain.cppのLoadQustion関数の中で宣言したint fに、
きちんとファイルハンドルが入っていなかったようです。
そのせいで、おかしいのでしょうか…

Re: 動作が停止してしまいます

Posted: 2012年8月09日(木) 19:19
by みけCAT
ファイルは正しい位置に置いてありますか?

Re: 動作が停止してしまいます

Posted: 2012年8月10日(金) 09:23
by NATTO
正しい位置においてあるんですけどね…
media\\Que_monogatari.txtになっているはずですが。

あと、テキストファイルのなかの文字列をいったん、
構造体mにいれて、それを配列構造体allQにうつすとい方法をとりたいのですが、
それは難しいのですか?
「14歳からはじめるC言語わくわくゲームプログラミング教室」という解説書は、
その方法をとっているのですが…

Re: 動作が停止してしまいます

Posted: 2012年8月10日(金) 11:01
by nil
デバッグ実行やコメントアウトを使って
まずどの部分で不具合が起こっているのかを特定してください

Re: 動作が停止してしまいます

Posted: 2012年8月10日(金) 12:16
by NATTO
デバッグを使って少しずつ進めていったら、
まず、107行目で、
「○○○.exe の 0x770d15de でハンドルされていない例外が発生しました:
0xC0000005: 場所 0x00000000 に書き込み中にアクセス違反が発生しました。」
というエラーメッセージがでました。
またステップインで見ていくと、mymain.cppの19行目のときに、
変数fに -268435456 という値が入っていました。
そのせいでうまくいかないのだと思います。
「デバッグなしで開始」をすると、すぐに動作が停止してしまいます。

Re: 動作が停止してしまいます

Posted: 2012年8月10日(金) 12:29
by softya(ソフト屋)
fは0以外なら正常です。ファイルハンドルですから。
http://homepage2.nifty.com/natupaji/DxL ... other.html
その後ろを追いかけてみてください。

それとステップ実行せずにデバッグ開始で開始すれば
「○○○.exe の 0x770d15de でハンドルされていない例外が発生しました:
0xC0000005: 場所 0x00000000 に書き込み中にアクセス違反が発生しました。」
の該当命令で停止するはずです。
よく分からない関数で停止していたら、呼出し履歴で呼び出しの関数元に戻ることもできます。

Re: 動作が停止してしまいます

Posted: 2012年8月10日(金) 16:38
by NATTO
mymain.cppの27行目から、ステップインしようとすると、
「現在の場所のソース コードを表示できません。」とでて、先に進めませんでした。

ファイルハンドルのほうは、負の値でも正常に進んでいました。
教えてくださってありがとうございます!

Re: 動作が停止してしまいます

Posted: 2012年8月10日(金) 21:45
by softya(ソフト屋)
NATTO さんが書きました:mymain.cppの27行目から、ステップインしようとすると、
「現在の場所のソース コードを表示できません。」とでて、先に進めませんでした。

ファイルハンドルのほうは、負の値でも正常に進んでいました。
教えてくださってありがとうございます!
はい。それは出来ませんのでライブラリ関数はステップ オーバーしてください。
まぁ私の回答待つよりも色々試したほうが良いですけどね。

Re: 動作が停止してしまいます

Posted: 2012年8月10日(金) 22:27
by NATTO
ステップインしても、ステップオーバーをしても
「○○○.exe の 0x770d15de でハンドルされていない例外が発生しました:
0xC0000005: 場所 0x00000000 に書き込み中にアクセス違反が発生しました。」
と表示され、107行目に移動して、左に緑の矢印が表示されるのですが、
これは、27行目の処理がおかしいということですか?

Re: 動作が停止してしまいます

Posted: 2012年8月10日(金) 22:42
by softya(ソフト屋)
ソコじゃないですね。
sscanf_s(buf, "%s,%s", &Ao, &At);
のところじゃないですか?
ほんとにデバッグビルドしてステップオーバーしてますか?
ちなみに sscanf_sの使い方が間違っています。

Re: 動作が停止してしまいます

Posted: 2012年8月11日(土) 23:59
by NATTO
ちゃんとしているはずなんですが…
ブレークポイントを1行前くらいにおいて、
ステップオーバーで進めていくのではないのですか?
それと、sscanf_s関数は前述した、解説書と同じ使い方(解説書では、数値を扱っていましたが)
で、使っているはずなのですが…

Re: 動作が停止してしまいます

Posted: 2012年8月12日(日) 00:10
by softya(ソフト屋)
sscanf_s(buf, "%s,%s", &Ao, &At);
の前の行にブレークポイントをおいてステップオーバーをしてみてください。
それと文字列と数値ではやり方が全然違いますので、よく確認してください。
「sscanf_s、_sscanf_s_l、swscanf_s、_swscanf_s_l (CRT)」
http://msdn.microsoft.com/ja-jp/library ... s.80).aspx
MSDNを見た頂くと分かりますが、みけCATさんが最初の頃に指摘している問題点の他に、もうひとつ問題があります。

Re: 動作が停止してしまいます

Posted: 2012年8月12日(日) 08:00
by beatle
scanfで"%s,%s"が動かないというのが解説されているページを示します。
C言語 CSVファイルの読み込み
ここによれば、"%s,%s"と書くと最初の%sにカンマも含めて取られてしまうそうです。
"%s"の代わりに"%[^,]"を使えばカンマが来るまで読み込むようになるようです。

Re: 動作が停止してしまいます

Posted: 2012年8月13日(月) 10:04
by NATTO
beatleさんの方法で、38行目を

コード:

sscanf_s(buf, "%[^,],%s", Ao, At);
44行目を

コード:

sscanf_s(buf, "%[^,],%[^,],%s", a1, a2, a3);
このように修正しました。

デバッグでステップオーバーしていくと、
38行目で「○○○.exe の 0xfefefefe でハンドルされていない例外が発生しました: 0xC0000005: Access violation」
と出てしまいます。
fefefefeという表示はよく出そうな表示に思えますが、
どういうことでしょうか…

Re: 動作が停止してしまいます

Posted: 2012年8月13日(月) 10:08
by softya(ソフト屋)
私のリンクをよく見て頂くと分かると思いますが文字列はバッファの大きさの指定が必須です。
それがsscanf_sとsscanfの違いですので、MSDNのページのサンプルをよく見てみてください。
そもそもバッファオーバーをガードするために生まれた_s系なのでバッファサイズを指定しない事はありえないと思ってください。

Re: 動作が停止してしまいます

Posted: 2012年8月13日(月) 12:29
by NATTO
softyaさんの言うとおりにsizeofを追加したら、無事に成功しました!
おしえてくださったみなさん本当にありがとうございました。