全角読み込み表示で詰まってます。

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

全角読み込み表示で詰まってます。

#1

投稿記事 by C権化 » 9年前

制作環境はVC++2010 ,ライブラリはDxlibを使用しています。

もしよければ、エクセルから全角文字列を読みこみ、
配列に格納、さらにその格納した配列から
構造体内の配列に代入し、その構造体内の
配列を指定座標に描画する方法への助言をいただきたいと思っています。

より、具体的にやろうと思っていたことを書きますと、
FileRead_getc関数を使って、エクセル(.csv)ファイルの
文字列、例えば「あいうえお」を読みこんで、
inputc[]を作って、そこに入れ、その後charcter.talk[0][](chat talk[2][])
に入れ、最後にDrawString(0,0,charcter.talk[0],Black)で表示させたいと思っています。
龍神録のエクセル読み込みを参考にしています。
下に抜き出したコードを張ってみます。

コード:

for(i=0;i<64;i++){
                        inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
                        if(inputc[i]=='/'){//スラッシュがあれば
                                while(FileRead_getc(fp)!='\n');//改行までループ
                                i=-1;//カウンタを最初に戻して
                                continue;
                        }
                        if(input[i]==',' || input[i]=='\n'){//カンマか改行なら
                                inputc[i]='\0';//そこまでを文字列とし
                                break;
                        }
           if(input[i]==EOF){//ファイルの終わりなら
                                goto EXFILE;//終了
                        }
           for(j=0;inputc[j]!='\0';j++)
                                ch_Talk_order.talk[0][j]=inputc[j];
                        ch_Talk_order.talk[0][j]='\0';break;

EXFILE:
        FileRead_close(fp);
}
この後、登録関数で登録したあと描画したいんですが、

コード:

 for(int k=0; k<ch_Talk_order[j].talk[0][k]!='\0';k++)
            charcter.talk[0][k]=ch_Talk_order.talk[0][k];
charcter.talk[0][k]='\0';
DrawString(0,0,charcter.talk[0],Black);

と、アバウトにはこんな感じなのですが、
DrawString(0,0,"abcde",Black)だと「abcde]と表示されるのに
上記だと表示できなくて、過去のhttp://dixq.net/forum/viewtopic.php?t=5721&p=48290
を見ても力不足でわかりませんでした。
助言、よろしければよろしくお願いします。
最後に編集したユーザー C権化 on 2010年12月16日(木) 08:26 [ 編集 1 回目 ]

アバター
bitter_fox
記事: 607
登録日時: 9年前
住所: 大阪府

Re: 全角読み込み表示で詰まってます。

#2

投稿記事 by bitter_fox » 9年前

コード:

for(i=0;i<64;i++){
        (中略)
 
EXFILE:
        FileRead_close(fp);
}
これだと毎回、FileRead_closeが呼び出されてますが・・・
多分ここが原因では無いでしょうか。
[hr][修正]
ちゃんと、break;がありますね。。。

各変数の型とかの情報が欲しいかも・・・
[追記]
えっ、break;・・・
break;だと一回しか実行されないんじゃ。。。

アバター
C権化
記事: 14
登録日時: 9年前

Re: 全角読み込み表示で詰まってます。

#3

投稿記事 by C権化 » 9年前

型はinputcならcharで、
charcter.talk[]などもchar型です。
本当のコードを乗っけるには、他のソース等ものせなければ
わからないので、必要だと思う部分を載せています。

break;ですか。
for文は、かっこ使わないと直下の一つの文にかかるんじゃありませんでしたか?
それで、ヌル文字の一つ手前まで代入して、そのあと最後にヌルを
いれようとしています。

アバター
bitter_fox
記事: 607
登録日時: 9年前
住所: 大阪府

Re: 全角読み込み表示で詰まってます。

#4

投稿記事 by bitter_fox » 9年前

C権化 さんが書きました:型はinputcならcharで、
charcter.talk[]などもchar型です。
本当のコードを乗っけるには、他のソース等ものせなければ
わからないので、必要だと思う部分を載せています。
なるほど、ありがとうございます。普通ですね・・・
C権化 さんが書きました:break;ですか。
for文は、かっこ使わないと直下の一つの文にかかるんじゃありませんでしたか?
それで、ヌル文字の一つ手前まで代入して、そのあと最後にヌルを
いれようとしています。

コード:

           for(j=0;inputc[j]!='\0';j++)
                                ch_Talk_order.talk[0][j]=inputc[j];
                        ch_Talk_order.talk[0][j]='\0';break;
ここの部分ですね。

これを明示的に括弧に入れてあげれば以下のようになります。

コード:

    for(j=0;inputc[j]!='\0';j++)
    {
         ch_Talk_order.talk[0][j]=inputc[j];
    }

    ch_Talk_order.talk[0][j]='\0';break;
こうなってしまい、breakが実行されるように思うのですが・・・

一重目forでは、一文字ずつ取得するのではないですか??
であれば、上の文では、一文字しか代入されず全体のforを終えてしまうように思うのですが・・・

コード:

                       if(input[i]==',' || input[i]=='\n'){//カンマか改行なら
                                inputc[i]='\0';//そこまでを文字列とし
                                break;
                        }
これだと、二つ目のifで、取得した値が改行だった場合一重目のforを飛び降りるので、一行しか取得できないのではないでしょうか?

また、
inputc=input=FileRead_getc(fp);//1文字取得する
このようにわざわざ二つに代入する必要はあるのでしょうか??

読み込むのは、たった一行で良いのでしょうか??
であれば、ifに関しての指摘は無視していただいて結構です。

アバター
bitter_fox
記事: 607
登録日時: 9年前
住所: 大阪府

Re: 全角読み込み表示で詰まってます。

#5

投稿記事 by bitter_fox » 9年前

う~ん、さっきの投稿、読み直してみたらぐちゃぐちゃで何言ってるのか自分でも解らなかったので、もう一度。

コード:

for(i=0;i<64;i++){
                        inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
                        if(inputc[i]=='/'){//スラッシュがあれば                                   // (1)
                                while(FileRead_getc(fp)!='\n');//改行までループ
                                i=-1;//カウンタを最初に戻して
                                continue;
                        }
                        if(input[i]==',' || input[i]=='\n'){//カンマか改行なら                // (2)
                                inputc[i]='\0';//そこまでを文字列とし
                                break;
                        }
           if(input[i]==EOF){//ファイルの終わりなら                              // (3)
                                goto EXFILE;//終了
                        }
           for(j=0;inputc[j]!='\0';j++)
                                ch_Talk_order.talk[0][j]=inputc[j];
                        ch_Talk_order.talk[0][j]='\0';break;
 
EXFILE:
        FileRead_close(fp);
}
まずファイルには、「abcde」が入ってるとします(日本語だと、2バイトコードで説明がめんどくさいのでアルファベットで・・・)

inputc[0]及びinput[0]には、'a'が入ります。
(1)の条件に合っていないのでスルー
(2)の条件にも合っていないのでスルー
(3)もスルー

で、forです。

j = 0のとき
inputc[0]には'a'が入っており、継続条件に合致するので、
ch_Talk_order.talk[0][0]に'a'を代入します。

j = 1のとき
inputc[1]には'\0'が入っており、継続条件に反するので、forを終わります。

ch_Talk_order.talk[0][1]に'\0'を代入する。

そして、一重目のforをbreak;によって飛び降りる。

結果としては、
ch_Talk_order.talk[0]に入ってるのは、"a"になります。

アバター
C権化
記事: 14
登録日時: 9年前

Re: 全角読み込み表示で詰まってます。

#6

投稿記事 by C権化 » 9年前

bitter_foxさん返答ありがとうございます。

csvファイルは0,100,1000,abcde,
のうようにカンマ区切りで入ってて、カンマまでを
一つの文字列としてinputc[]に代入していて、
abcdeとあった場合、aの次に\0がきてbではなく
abcdeと全部入るのでは?と思っていますが、

三ケタの数字は読みこんで代入できているので、
上であれば0,100,の部分です。
一文字で読み込みが終わってはいないと思います。

なので、input[j]は前のカンマから次のカンマの間を
文字列として持っていて、for文で文字列の最後まで
代入を、と思います。そして、例えばfor文が
一文字だけ、代入したとしても、一文字も表示してくれません。
半角にしてもです。問題はここではないのでしょうか?

自分でももっと良く考えてみます。

アバター
C権化
記事: 14
登録日時: 9年前

Re: 全角読み込み表示で詰まってます。

#7

投稿記事 by C権化 » 9年前

読みこめてはいました、エクセル
のデータが「あいうえお」だと表示されず、
「abc」など半角であれば表示されました。

全角だと、表示されません。
全角はエクセルから読みこめないのは
なぜなんでしょうか?

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

Re: 全角読み込み表示で詰まってます。

#8

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

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

non
記事: 1097
登録日時: 9年前

Re: 全角読み込み表示で詰まってます。

#9

投稿記事 by non » 9年前

DX-Libの関数リファレンスによると
以下抜粋
宣言 int FileRead_getc( int FileHandle ) ;
概略  ファイルから一文字読み出す
引数 int FileHandle : ファイルハンドル
戻り値  -1以外:読み出した文字コード
  -1:エラー発生
解説  FileRead_open関数で開いたファイルから一文字読み込みます。
 正常に読み込めるのは1バイト文字だけで、一文字2バイトの全角文字などは正常に読み込めません。(1バイト目だけが返ってきます)

************
と書かれてます。
non

アバター
C権化
記事: 14
登録日時: 9年前

Re: 全角読み込み表示で詰まってます。

#10

投稿記事 by C権化 » 9年前

返答ありがとうございます。
>>softyaさん
コードを簡単に作ってみました。添付ファイルとしてエクセルも仮ですがいれておきました。

コード:

#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
			 LPSTR lpCmdLine, int nCmdShow )
{	ChangeWindowMode(TRUE);//ウィンドウモード
	int Cr,i,j,fp;
	char talk[64];

	if( DxLib_Init() == -1 )	// DXライブラリ初期化処理
	{
		 return -1;	// エラーが起きたら直ちに終了
	}

	// 白色の値を取得
	Cr = GetColor( 255 , 255 , 255 ) ;

	// 文字列の描画

        char fname[32]={"../dat/Talk.csv"};
        int input[64];
        char inputc[64];

        fp = FileRead_open(fname);//ファイル読み込み
        if(fp == NULL){
                printfDx("read error\n");
				
        }
        while(1){
                for(i=0;i<64;i++){
                        inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
                  
                        if(input[i]==',' || input[i]=='\n'){//カンマか改行なら
                                inputc[i]='\0';//そこまでを文字列とし
                                break;
                        }
                        if(input[i]==EOF){//ファイルの終わりなら
                                goto EXFILE;//終了
                        }					
                }
               for(j=0; inputc[j]!='\0';j++)
										talk[j]=inputc[j];
								talk[j]='\0';
        }
EXFILE:
        FileRead_close(fp);


	DrawString(0,0,talk,Cr);

	WaitKey() ;		// キーの入力待ち(『WaitKey』を使用)

	DxLib_End() ;		// DXライブラリ使用の終了処理

	return 0 ;		// ソフトの終了
}

>>nonさん
過去のhttp://dixq.net/forum/viewtopic.php?t=5721&p=48290
の管理人様の返答だと可能だとあったのでできるではないかと
思っています。

追記____________
自分でエクセルの文字列を「あいう」にしたらあいうと表示されました。
そうするとなにが問題なのか?読み込みじゃないのでしょうか。
さらにスイッチで配列を二次元にしてみましたが
成功しました。なにが・・・違うのか。

コード:

#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
			 LPSTR lpCmdLine, int nCmdShow )
{	ChangeWindowMode(TRUE);//ウィンドウモード
	int Cr,i,j,fp;
	char talk[2][64];

	if( DxLib_Init() == -1 )	// DXライブラリ初期化処理
	{
		 return -1;	// エラーが起きたら直ちに終了
	}

	// 白色の値を取得
	Cr = GetColor( 255 , 255 , 255 ) ;

	// 文字列の描画

        char fname[32]={"../dat/Talk.csv"};
        int input[64];
        char inputc[64];

        fp = FileRead_open(fname);//ファイル読み込み
        if(fp == NULL){
                printfDx("read error\n");
				
        }
		int num=0;
        while(1){
                for(i=0;i<64;i++){
                        inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
                  
                        if(input[i]==',' || input[i]=='\n'){//カンマか改行なら
                                inputc[i]='\0';//そこまでを文字列とし
                                break;
                        }
                        if(input[i]==EOF){//ファイルの終わりなら
                                goto EXFILE;//終了
                        }					
                }
			switch(num){
			case 0:
               for(j=0; inputc[j]!='\0';j++)
					talk[0][j]=inputc[j];
			   talk[0][j]='\0';break;
			case 1:
				for(j=0; inputc[j]!='\0';j++)
					talk[1][j]=inputc[j];
			   talk[1][j]='\0';break;
			}
			num++;
        }
EXFILE:
        FileRead_close(fp);


	DrawString(0,0,talk[0],Cr);
	DrawString(0,20,talk[1],Cr);

	WaitKey() ;		// キーの入力待ち(『WaitKey』を使用)

	DxLib_End() ;		// DXライブラリ使用の終了処理

	return 0 ;		// ソフトの終了
}


添付ファイル
sample.zip
(48.83 MiB) ダウンロード数: 28 回

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

Re: 全角読み込み表示で詰まってます。

#11

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

やりたいと思われる処理のコードでなるべく綺麗に書き換えてみました。
重大なポイントとして、バイナリエディタでcsvを見てみると分かるのですが、復帰改行の処理がちゃんとされていませんでした。
詳しくは私のRPG講座をお読みください。

コード:

#include "DxLib.h"
#define	BUF_SIZE	64

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nCmdShow )
{
	ChangeWindowMode(TRUE);//ウィンドウモード
	int Cr,i,j,fp;

	if( DxLib_Init() == -1 )    // DXライブラリ初期化処理
	{
		return -1; // エラーが起きたら直ちに終了
	}

	// 白色の値を取得
	Cr = GetColor( 255 , 255 , 255 ) ;

	// 文字列の描画

	char fname[32]={"../dat/Talk.csv"};

	fp = FileRead_open(fname);//ファイル読み込み
	if(fp == NULL){
		printfDx("read error\n");

	}
	int py = 0;			//表示y座標。
	int bLoop = TRUE;	//ループを繰り返す。
	while(bLoop){
		int input[BUF_SIZE];
		char inputc[BUF_SIZE];
		
		for(i=0;i<(BUF_SIZE-1);i++){	//バッファが溢れて文字列終端処理ができないので-1しました。
			
			inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する

			if(input[i]=='\r'){//復帰なら
				//もう一度
				inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
			}
			if(input[i]==',' || input[i]=='\n'){//カンマか改行なら
				break;
			}
			if(input[i]==EOF){//ファイルの終わりなら
				bLoop = FALSE;//ループを止める。
				break;
			}
		}
		inputc[i]='\0';//そこまでを文字列とします。
		DrawString(0,py,inputc,Cr);
		
		//	表示位置を下にずらす。
		py += 16;
	}
	FileRead_close(fp);


	WaitKey() ;     // キーの入力待ち(『WaitKey』を使用)

	DxLib_End() ;       // DXライブラリ使用の終了処理

	return 0 ;      // ソフトの終了
}
【追記】
元のコードで改行なしにEOFだと文字列の終端処理がされないルートがあることと、ファイルオープンエラーだとゴミが表示される、最後の文字列しか表示されない。復帰コードが表示されるなどを修正しています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

non
記事: 1097
登録日時: 9年前

Re: 全角読み込み表示で詰まってます。

#12

投稿記事 by non » 9年前

失礼しました。確かに動くことを確認しました。
すでにsoftyaさんから、ご指摘の通り、改行がファイルでは0D 0A すなわち \r\n の2バイトで格納される
訳ですが、FileRead_getcはfscanfとは違い、そのまま1文字ずつ読み込まれるようです。
それでも、出力はされるのですが、0Dが文字化けしてピリオドが最後についているようです。
このままで、”あいうえお”にしても、ピリオドはついても問題なく動くはずです。動かない理由があるとすれば、
改行が2つ以上データファイルに入っていることが考えられます。
C権化さんのプログラムでは最後の1行しか表示していないですからね。
non

アバター
C権化
記事: 14
登録日時: 9年前

Re: 全角読み込み表示で詰まってます。

#13

投稿記事 by C権化 » 9年前

<<softyaさん、nonさん
返答ありがとうございます。コードまで、ありがとうございます。
サンプルは望むうごきをするのに関わらず、同じ構成にした
本体がうごきません・・・

実際は読み込みはswitchで複数回、違う変数に代入していまして、

コード:

#include "DxLib.h"
#define BUF_SIZE    64

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
			 LPSTR lpCmdLine, int nCmdShow )
{	ChangeWindowMode(TRUE);//ウィンドウモード
	int Cr,i,j,fp;
	char talk[2][BUF_SIZE];
	char p_talk[2][BUF_SIZE];

	if( DxLib_Init() == -1 )	// DXライブラリ初期化処理
	{
		 return -1;	// エラーが起きたら直ちに終了
	}

	// 白色の値を取得
	Cr = GetColor( 255 , 255 , 255 ) ;

	// 文字列の描画

        char fname[32]={"../dat/Talk.csv"};
		fp = FileRead_open(fname);//ファイル読み込み
        if(fp == NULL){
                printfDx("read error\n");
				
        }
		int py=0;
		int bLoop =TRUE;
        
		int num=0;
        while(bLoop){
		int input[BUF_SIZE];
        char inputc[BUF_SIZE];
                for(i=0;i<BUF_SIZE-1;i++){
				     inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
					    if(input[i]=='\r'){//復帰なら
						 //もう一度
						 inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
					    }

                        if(input[i]==',' || input[i]=='\n'){//カンマか改行なら
                                break;
                        }
                        if(input[i]==EOF){//ファイルの終わりなら
                                bLoop = FALSE;
								break;
                        }					
                }
				 inputc[i]='\0';//そこまでを文字列とし
			switch(num){
			case 0:
               for(j=0; inputc[j]!='\0';j++)
					talk[0][j]=inputc[j];
			   talk[0][j]='\0';break;
			case 1:
				for(j=0; inputc[j]!='\0';j++)
					talk[1][j]=inputc[j];
			   talk[1][j]='\0';break;
			}
			num++;
        }

	for(j=0; talk[0][j]!='\0';j++)
		p_talk[0][j]=talk[0][j];
	p_talk[0][j]='\0';
	for(j=0; talk[1][j]!='\0';j++)
		p_talk[1][j]=talk[1][j];
	p_talk[1][j]='\0';

	DrawString(0,0,p_talk[0],Cr);
	DrawString(0,20,p_talk[1],Cr);

	FileRead_close(fp);
	WaitKey() ;		// キーの入力待ち(『WaitKey』を使用)

	DxLib_End() ;		// DXライブラリ使用の終了処理

	return 0 ;		// ソフトの終了
}
softyaさんのコードを参考にswitch使用版を作りまして、こちらも正しくうごきます。
実際読み込もうとしているエクセルを添付してみます。
追記________________
エクセルデータをいろいろかえてみたところ
1,[abcd]のような半角は問題なく表示され
2,[あいう]のような全角は表示されず、
3,[abあdc]のように、半角後、全角だと[ab]の表示されます。
これは全角の前で読み込みが終わっているということなのでしょうか?
添付ファイル
ch_Talk1.csv
(150 バイト) ダウンロード数: 29 回

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

Re: 全角読み込み表示で詰まってます。

#14

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

妙に複雑なことをしているのでシンプルに書き換えてみました。
これでちゃんと動くようですが、問題があるのでしょうか?

コード:

#include "DxLib.h"
#define BUF_SIZE    64

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine, int nCmdShow )
{
	ChangeWindowMode(TRUE);//ウィンドウモード
	int Cr,i,j,fp;
	char talk[2][BUF_SIZE];
	char p_talk[2][BUF_SIZE];

	if( DxLib_Init() == -1 )    // DXライブラリ初期化処理
	{
		return -1; // エラーが起きたら直ちに終了
	}

	// 白色の値を取得
	Cr = GetColor( 255 , 255 , 255 ) ;

	// 文字列の描画

	char fname[32]={"../dat/ch_Talk1.csv"};
	fp = FileRead_open(fname);//ファイル読み込み
	if(fp == NULL){
		printfDx("read error\n");

	}
	int py=0;
	int bLoop =TRUE;

	int num=0;
	while(bLoop){
		int input[BUF_SIZE];
		char inputc[BUF_SIZE];
		for(i=0;i<BUF_SIZE-1;i++){
			inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
			if(input[i]=='\r'){//復帰なら
				//もう一度
				inputc[i]=input[i]=FileRead_getc(fp);//1文字取得する
			}

			if(input[i]==',' || input[i]=='\n'){//カンマか改行なら
				break;
			}
			if(input[i]==EOF){//ファイルの終わりなら
				bLoop = FALSE;
				break;
			}                   
		}
		inputc[i]='\0';//そこまでを文字列とし
		if( num < 2 ) {
			strcpy( talk[num], inputc ) ;
		}
		num++;
	}
	DrawString(0,0,talk[0],Cr);
	DrawString(0,20,talk[1],Cr);

	FileRead_close(fp);
	WaitKey() ;     // キーの入力待ち(『WaitKey』を使用)

	DxLib_End() ;       // DXライブラリ使用の終了処理

	return 0 ;      // ソフトの終了
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
C権化
記事: 14
登録日時: 9年前

Re: 全角読み込み表示で詰まってます。

#15

投稿記事 by C権化 » 9年前

softyaさんのコードのように、for文からstrcpyに変えたら
成功しました。ありがとうございました!
解決に協力してくださったみなさまありがうございました。


しかし、サンプルではfor文でも全角を表示できていたのは
なぜなのだろうか。

閉鎖

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