ページ 11

外部ファイルから二次元配列に格納出来ません(T T)

Posted: 2013年5月14日(火) 19:28
by ダン
何度も何度もやり直し、それでもできず、もう挫折寸前で泣きそうです。お助けください。
内容は、基底クラスで文字列ファイルの読み込み、
数字変換して用意した二次元配列への格納。
継承クラスでその二次元配列の中身を確認してみる、といった流れです。
が、ファイルのデータ内容が二次元配列の中にちゃんと入っていないようで
確認するとその値の数が合いません。。。。
なにが悪いのでしょうか??以下、ソースです。

コード:


<●StageDataBase.h(基底クラス>
#include "DxLib.h"
#include<fstream>
#include<string>
#include <iostream>
#pragma once
using namespace std;

#define LINE 8
#define COL 8

class StageDataBase
{
public:
	StageDataBase(void);
	~StageDataBase(void);

void LoadMapData(int,int,string);

protected:
	int line;
	int count;
	int sum;
	int nokorinoketa;
	int hairetu[LINE][COL];
};

<●StageDataBase.cpp>
#include "StageDataBase.h"

StageDataBase::StageDataBase(void){
	line = 0;
	count = 0;
	sum = 0;
	nokorinoketa=0;
}

StageDataBase::~StageDataBase(void){}

void StageDataBase::LoadMapData(int y,int x,string s){

	ifstream ifs(s);
	string buf[LINE];
	while(ifs && getline(ifs,buf[line])){
		line++;}
	
	for(int i=0; i<y; i++){
		for(int j=0; j<x; j++){
			if(j < x-1){
				sum = buf[i][count]-48;
				count++;
			
				while(isdigit(buf[i][count])){
					sum = sum*10 + (buf[i][count])-48;
					count++;
				}
			hairetu[i][j] = sum;

			count++;
			}
			if(j == x-1){//最後の数字
				nokorinoketa = buf[i].size()-count;
				sum = buf[i][count] - 48;
				while(nokorinoketa > 1){
					count++;
					sum = sum*10 + (buf[i][count])-48;
					nokorinoketa--;
				}
				hairetu[i][j] = sum;
			}
		}
		count=0;		
	}
}

------------------------------------------------------------------------------------------------
<●GameStage.h(継承クラス>
#include "StageDataBase.h"

class GameStage: public StageDataBase {
public:
	GameStage(void);
	~GameStage(void);

    void Initialize();   
    void Update();      
    void Draw();         
};


<●GameStage.cpp>
#include "GameStage.h"
#include "DxLib.h"

GameStage::GameStage(void) {
	 StageDataBase::LoadMapData(LINE,COL,"maptest.csv");}

GameStage::~GameStage(void){}

void GameStage::Initialize(){}

void GameStage::Update(){}

void GameStage::Draw(){

	int c=0;   //表示位置をズラすための変数
//中身を確認するために、各値に反応させDrawさせてみるもファイル内の数と合わない、、、
	for(int i=0; i<8; i++){
		for(int j=0; j<8; j++){		
			if(hairetu[i][j] == 35){
				DrawString(c,10,"35",GetColor(255,255,255));
			}
			if(hairetu[i][j] == 74){
				DrawString(c,50,"74",GetColor(255,255,255));
			}
			if(hairetu[i][j] ==3){
				DrawString(c,70,"3",GetColor(255,255,255));
			}
			if(hairetu[i][j] == 62){
				DrawString(c,100,"62",GetColor(255,255,255));
			}
		}
		c += 20;
	}
}
読み込んでいるファイルはこちらになります
http://ux.getuploader.com/zipcodezipcod ... aptest.csv
内容↓
0,0,0,0,9,0,0,45
0,3,3,62,3,3,62,0
0,3,3,3,3,3,3,0
0,3,62,3,35,35,3,44
0,3,62,3,35,35,3,0
0,3,62,3,35,35,3,0
0,3,3,3,3,3,3,0
0,0,0,43,74,3,0,0

今回のソースは制作中のものから問題の部分だけを抽出していますので
抜け、消し忘れ等あるかもしれませんが、ご了承ください。

Re: 外部ファイルから二次元配列に格納出来ません(T T)

Posted: 2013年5月14日(火) 19:55
by h2so5
ソースコードが非常に分かりにくいのでデバッグをきちんと行うためにも整理したほうがよいと思います。
  1. インデントは揃えてください。
  2. line, count, sum, nokorinoketa などはメンバ関数にする必要がないのでローカル変数にしてください。
    メンバ関数にすると初期化忘れなどのバグが起きやすくなります。
  3. あちこちにマジックナンバーの48があって分かりにくいので文字定数や関数を使いましょう。
  4. 外部ファイルの読み込み処理をチェックするのに、継承を使用する必要性がありません。
    コードが追いにくくなるだけです。基底クラスだけあればチェックできるはずです。
  5. 回りくどい中身の確認の仕方はせずに、配列の中身を全部標準出力に出したほうが早いです。

Re: 外部ファイルから二次元配列に格納出来ません(T T)

Posted: 2013年5月14日(火) 20:46
by softya(ソフト屋)
まず、簡単なmainだけのコンソールアプリのプログラムで読み込みに成功させた方が良いと思います。
それをクラスに移植するのです。

Re: 外部ファイルから二次元配列に格納出来ません(T T)

Posted: 2013年5月14日(火) 20:46
by nil
現在は基底クラスのデストラクタはこれといった役割を持っていないようですが、
それでも一応virtualにしておいたほうがいいと思います。

Re: 外部ファイルから二次元配列に格納出来ません(T T)

Posted: 2013年5月14日(火) 21:44
by かずま
ダン さんが書きました:

コード:

	string buf[LINE];
	while(ifs && getline(ifs,buf[line])){
getline は 8回成功し、buf[0]~buf[7] に行が入ります。
まだ ifs は true です。
9回目の getline は 存在しない buf[8] を参照して、はい、さようなら。

緊急対策として string buf[LINE+1] にしてみてください。
ちゃんとした修正は自分で考えてください。

Re: 外部ファイルから二次元配列に格納出来ません(T T)

Posted: 2013年5月14日(火) 23:06
by ダン
解決出来ました!
すごく勉強になりました、皆様ありがとうございます!!

Re: 外部ファイルから二次元配列に格納出来ません(T T)

Posted: 2013年5月14日(火) 23:35
by softya(ソフト屋)
あとで過去ログ検索した人の役に立つように、解決コードの投稿をお願いします。

Re: 外部ファイルから二次元配列に格納出来ません(T T)

Posted: 2013年5月15日(水) 10:11
by かずま
質問者の解決コードを待ちますが、
あとで過去ログ検索した人の役に立つように、
別のコードを示します。
整数を読み込んで、区切りのコンマを読み飛ばす
というのを素直に書けば、

コード:

void StageDataBase::LoadMapData(int y, int x, string s)
{
    char comma;
    ifstream ifs(s.c_str());
    for (int i = 0; i < y; i++)
        for (int j = 0; j < x; j++) {
            ifs >> hairetu[i][j];
            if (j < x-1) ifs >> comma;
        }
}
これは、あくまでも参考ににしてもらうコードです。
エラーチェックを全くしていないので適宜追加してください。
・ファイルをオープンできない
・データが不足
・整数でないものがある
・書式が想定外(たとえば行末の改行の前にもコンマがあるなど)
・オーバーフロー