エクセルで文字列読み込み

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

エクセルで文字列読み込み

#1

投稿記事 by namari » 11年前

http://dixq.net/rp/11.html
を参考に会話イベントをすべてCSVの中に収めたいです。
そのために、上記のアドレスを改変して、以下のように書いたところをデバッガで確認すると、
文字化けした文字列しか取得できていません。

コード:

//load.cpp
                (これより前は貼ったアドレスのまま)
                switch(num){
                        case 0: sprintf(happening[happ_num].message[n].mess,"%s",inputc);
                        case 1:...
//struct.h
typedef struct{
	char mess[MESS_MAX];//メッセージ本体
(その他いろいろな変数)
}message_t;

typedef struct{
	message_t message[MESSAGE_MAX];//そのメッセージのイベント会話順
}happening_t;
上記アドレスは数字しか取得していないので、多分このコードだと文字列は対象外なのでしょうが、バグが出る理由がイマイチわかりません。
happening[happ_num].message[1]以降で明らかに読み込み場所がずれているので、
happening[happ_num].message[0].mess部分読み込み時に途中で区切ってしまったのでしょうか・・・。
それとも文字型と文字列型がごっちゃになっているとかでしょうか

ちなみにセルに入っている文字列は"ここにはメッセージが表示されます"です。

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

Re: エクセルで文字列読み込み

#2

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

文字化けする原因はまだよくわかりませんが、とりあえず本番のコードではきちんとsprintfの後にbreak;を入れていますか?
あと、この場合はsprintfではなくlstrcpyAを使えばいいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: エクセルで文字列読み込み

#3

投稿記事 by namari » 11年前

みけCAT さんが書きました:文字化けする原因はまだよくわかりませんが、とりあえず本番のコードではきちんとsprintfの後にbreak;を入れていますか?
あと、この場合はsprintfではなくlstrcpyAを使えばいいと思います。
あっbreak;は入ってます。コピーし損ねてましたね。

コード:

case 0: lstrcpyA(happening[happ_num].message[n].mess,inputc);         break;
こうしてみましたが結果は変わらなかったです・・・。

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

Re: エクセルで文字列読み込み

#4

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

試しに以下のコードをgcc 4.8.1でコンパイルし、実行したところ、出力は期待したとおりでしたが、
デバッガ(GDB 7.6.1)で85行目でbreakし、happening[happ_num].message[0].messをprintしたところ、文字化けが確認されました。
デバッガだけに頼らず、printfDxなど他の方法でデータを確認してみてください。
また、問題の切り分けのために、半角(ASCIIに含まれる)文字のみのメッセージでテストしてみてください。

コード:

#include <cstdio>
#include <cstdlib>

FILE* hack_file;

int FileRead_open(const char* fname) {
	hack_file = fopen(fname, "r");
	if (hack_file == NULL) return 0;
	return 1;
}

int FileRead_getc(int) {
	return getc(hack_file);
}

void FileRead_close(int) {
	fclose(hack_file);
}

void printfDx(const char* str) {
	fputs(str, stdout);
}

const int MESS_MAX = 128;
const int MESSAGE_MAX = 1000;

typedef struct{
	char mess[MESS_MAX];//メッセージ本体
	char hoge[MESS_MAX];
	int fuga;
	char foo[MESS_MAX];
}message_t;
 
typedef struct{
	message_t message[MESSAGE_MAX];//そのメッセージのイベント会話順
}happening_t;

happening_t happening[1];
const int happ_num = 0;

void load_story(){
	int n,num,i,fp;
	char fname[32]="test.csv"; //{"../dat/csv/storyH0.csv"};
	int input[64];
	char inputc[64];

	fp = FileRead_open(fname);//ファイル読み込み
	if(fp == NULL){
		printfDx("read error\n");
		return;
	}
	for(i=0;i<2;i++)//最初の2行読み飛ばす
		while(FileRead_getc(fp)!='\n');

	n=0 , num=0;
	while(1){
		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;//終了
			}
		}
		switch(num){
			case 0: sprintf(happening[happ_num].message[n].mess,"%s",inputc);break;
			case 1: sprintf(happening[happ_num].message[n].hoge,"%s",inputc);break;
			case 2: happening[happ_num].message[n].fuga=atoi(inputc);break;
			case 3: sprintf(happening[happ_num].message[n].foo,"%s",inputc);break;
		}
		num++;
		if(num==4){
			num=0;
			n++;
		}
	}
EXFILE:
	FileRead_close(fp);
}

int main(void) {
	load_story();
	for (int i = 0; i < MESSAGE_MAX; i++) {
		if (happening[happ_num].message[i].hoge[0] == '\0') break;
		printf("no  = %d\n", i);
		printf("mess = %s\n", happening[happ_num].message[i].mess);
		printf("mess = %s\n", happening[happ_num].message[i].hoge);
		printf("fuga = %d\n", happening[happ_num].message[i].fuga);
		printf("foo  = %s\n", happening[happ_num].message[i].foo);
		puts("----------");
	}
	return 0;
}
※このコードはDXライブラリを使用しません
添付ファイル
test.csv
テストに使用したデータ
(187 バイト) ダウンロード数: 139 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: エクセルで文字列読み込み

#5

投稿記事 by namari » 11年前

>>みけCATさん
>また、問題の切り分けのために、半角(ASCIIに含まれる)文字のみのメッセージでテストしてみてください。

半角文字だけの文字列では読み込まれました!
ユニコードが読めてないんですかね。
文字列のどこかでセルが終了したと誤って読まれてしまっていたとかでしょうかね・・・

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

Re: エクセルで文字列読み込み

#6

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

namari さんが書きました:ユニコードが読めてないんですかね。
文字列のどこかでセルが終了したと誤って読まれてしまっていたとかでしょうかね・・・
内容はDXライブラリ(と推測)でCSVファイルを読みこむ話なのに、
タイトルが「エクセルで文字列読み込み」である時点で用語の理解が自分とは同じではない気がしますが、
もし「ユニコード」が文字コードのUnicodeのことであれば、プログラムが理解できていない可能性があります。
読み込むファイルをテキストエディタかnkfなどでShift_JISに変換してから読み込んでみてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: エクセルで文字列読み込み

#7

投稿記事 by namari » 11年前

すみません。最初に
>happening[happ_num].message[1]以降で明らかに読み込み場所がずれているので、
と書きましたが、これは別の問題でした。一行読み込みを終えるのを

コード:

                if(num==18){
                        num=0;
                        n++;
                }
のままにしていました。
自分の変数数と同じにしたらズレはなくなりました。
文字読み込みの文字化けもなくなりました・・・。
ズレのせいで読み込み位置がおかしかったのでしょう。
文字列の苦手意識のせいかかなり視野が狭まっていたようです。
みけCATさんありがとうございました。

>内容はDXライブラリ(と推測)でCSVファイルを読みこむ話なのに、
>タイトルが「エクセルで文字列読み込み」である時点で用語の理解が自分とは同じではない気がしますが、
csvファイル=エクセルと思ってました・・・。
あとそもそもタイトルの助詞からしておかしいですね。せめてエクセルからですね。

閉鎖

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