ページ 1 / 1
CSVファイルからの読み込み
Posted: 2013年6月26日(水) 17:53
by Rittai_3D
またまたお世話になります。3Dです。今回は、前回と同じような質問です。
自分は、東方Projectのミュージックルームの再現をしています。前々回はソースに打ち込んだ文字列を指定の座標に表示するプログラムを教えて頂きましたが、今回はCSVファイルから曲のパス、曲名1、曲名2、コメントを読み込んで表示するプログラムを書いてみたのですが、うまく表示されません。CSVファイルは以下の様になっています。
読みづらいようでしたら言ってくだされば元のCSVファイルを添付します。
コード:
# この記号でコメントです
# 曲の情報
# パス、曲名1、曲名2、コメントの順番
dat/th06_01.wav,No1. 赤より紅い夢,♪赤より紅い夢,コメント1
dat/th06_02.wav,No2. ほおずきみたいに紅い魂,♪ほおずきみたいに紅い魂,コメント2
dat/th06_03.wav,No3. 妖魔夜行,♪妖魔夜行,コメント3
dat/th06_04.wav,No4. ルーネイトエルフ,♪ルーネイトエルフ,コメント4
dat/th06_05.wav,No5. おてんば恋娘,♪おてんば恋娘,コメント5
dat/th06_06.wav,No6. 上海紅茶館 ~ Chinese Tea,♪上海紅茶館 ~ Chinese Tea,コメント6
dat/th06_07.wav,No7. 明治十七年の上海アリス,♪明治十七年の上海アリス,コメント7
dat/th06_08.wav,No8. ヴワル魔法図書館,♪ヴワル魔法図書館,コメント8
dat/th06_09.wav,No9. ラクトガール ~ 少女密室,♪ラクトガール ~ 少女密室,コメント9
dat/th06_10.wav,No10. メイドと血の懐中時計,♪メイドと血の懐中時計,コメント10
dat/th06_11.wav,No11. 月時計 ~ ルナ・ダイアル,♪月時計 ~ ルナ・ダイアル,コメント11
dat/th06_12.wav,No12. ツェペシュの幼き末裔,♪ツェペシュの幼き末裔,コメント12
dat/th06_13.wav,No13. 亡き王女の為のセプテット,♪亡き王女の為のセプテット,コメント13
dat/th06_14.wav,No14. 魔法少女達の百年祭 ,♪魔法少女達の百年祭,コメント14
dat/th06_15.wav,No15. U.N.オーエンは彼女なのか?,♪U.N.オーエンは彼女なのか?,コメント15
dat/th06_16.wav,No16. 紅より儚い永遠,♪紅より儚い永遠,コメント16
dat/th06_17.wav,No17. 紅楼 ~ Eastern Dream...,♪紅楼 ~ Eastern Dream...,コメント17
そこで、このファイルを読み込んで、パスを表示するプログラムを書いてみたのですが、なぜか「フフフフフフフフ」と表示されたり、パスだけを表示したいのに全然関係無い物まで表示されてしまいます。
どうすればうまく表示出来るでしょうか?汚いコードですが宜しくお願いします。
コード:
#define _CRT_SECURE_NO_WARNINGS 1
#include "DxLib.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char path[ 16 ]; // 曲のパスを格納
char name1[ 64 ]; // 曲名1を格納
char name2[ 128 ]; // 曲名2を格納
char comme[ 64 ]; // コメントを格納.とりあえずテストの段階だから一行で
}music_t;
static music_t music[ 16 ];
int ProcessLoop() // 毎回行う事
{
if( ProcessMessage() != 0 ) return 1;
if( ClearDrawScreen() != 0 ) return 1;
return 0;
}
void Load_Script() // CSVファイルを読み込む
{
char FileName[] = "music.csv"; // 読み込むファイルの名前
int i,num=0,n=0; // forとかswitchで使う
int input[64]; // int版一文字格納
char inputc[64]; // cahr版一文字格納
FILE* fp = fopen( FileName , "r" ); // ファイルを読み込み形式で読み込む
if( fp == NULL ){ // ファイルが無かった時
MessageBox( NULL, TEXT("Script File Read Error"), TEXT("Error"), MB_OK | MB_ICONERROR );
return;
}
for(i=0 ; i<4 ; i++ ) // 最初の4行はコメントなので読み飛ばす
while( fgetc( fp ) != '\n' );
while( 1 ){
for(i=0 ; i<64 ; i++ ){
input[i] = inputc[i] =fgetc( fp );
if( input[i] == '#' ){ // コメント記号だったら
while( fgetc( fp ) != '\n' ); // \nまで飛ばす
i = -1; // カウンタを戻して
continue;
}
if( input[i] == ',' || input[i] == '\n' ){ // 改行かコンマなら
input[i] = '\0'; // そこまでを文字列として
break;
}
if( input[i] == EOF ){ // もしEOFだったら
goto EXFILE;
}
}
switch( num ){ //
case 0: strcpy( music[n].path , inputc ); break; // パスをinputcから構造体にコピー(パス)
case 1: strcpy( music[n].name1, inputc ); break; // パスをinputcから構造体にコピー(曲名1)
case 2: strcpy( music[n].name2, inputc ); break; // パスをinputcから構造体にコピー(曲名2)
case 3: strcpy( music[n].comme, inputc ); break; // パスをinputcから構造体にコピー(コメント)
}
num++;
if( num == 4 ){
num = 0;
n++;
}
}
EXFILE:
fclose( fp ); // ファイルを閉じる
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int)
{
ChangeWindowMode( TRUE ) , SetAlwaysRunFlag( TRUE ) , DxLib_Init() , SetDrawScreen( DX_SCREEN_BACK );
// ウィンドウモード、常に作動する、DXLIBの初期化、裏画面に描写
int i; // for用
Load_Script(); // CSV読み込み
while( !ProcessLoop() ){ // メインループ
for(i=0 ; i<17 ; i++ ){ // 全曲分のループ
DrawFormatString( 0, 0+18*i, GetColor(255,255,255), "%s", music[i].path ); // とりあえずテストでパスを表示
}
ScreenFlip(); //
}
DxLib_End(); // DxLibの終了
return 0;
}
[開発環境]
使用ライブラリ : Dxライブラリ
コンパイラ : Visual C++ 2008 Express Edition
OS : windows XP
#追記 とくに意味はないですが、コードタグでくくりました
Re: CSVファイルからの読み込み
Posted: 2013年6月26日(水) 18:16
by non
43行 input = inputc =fgetc( fp );
inputとinputcの2つがある意味は?
半角と全角が混ざっているので、危険な気もしますが・・・大丈夫かな?
Re: CSVファイルからの読み込み
Posted: 2013年6月26日(水) 18:21
by softya(ソフト屋)
デバッガやprintfなどで、ちゃんと動作をトレースしましたか?
構造体に確実に情報が格納される動作をしているか確認する作業をしていない気がします。
「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/blog.php?u=114&b=982&c=2
途中の動作をprintfでちゃんと確認してみてください。
あと17曲なのに配列16要素とか、path[ 16 ];とかギリギリ過ぎてバグを狙っているとしか思えないです。変な節約は自分の首を締めるだけですよ。
最初の4行コメントとか決め打ちもバグを生みそうな予感もします。4行決め打ちだから16曲なのかもしれませんが、あまり気持ちよくない仕様です。
>半角と全角が混ざっているので、危険な気もしますが・・・大丈夫かな?
たぶん、大丈夫じゃないです。
あと、改行コードが\r\nである事を理解されていない気がします。
バイナリエディタでcsvファイルの中身を覗くぐらいはして欲しい所です。
Re: CSVファイルからの読み込み
Posted: 2013年6月26日(水) 18:54
by Rittai_3D
>>non様
返信ありがとうございます。
>43行 input
= inputc =fgetc( fp );
>inputとinputcの2つがある意味は?
http://dixq.net/rp/11.html
を参考に作ったのと、strcpy()を使用したためです。エラーが出たので。
>半角と全角が混ざっているので、危険な気もしますが・・・大丈夫かな?
すべて全角にした方がいいでしょうか?
Re: CSVファイルからの読み込み
Posted: 2013年6月26日(水) 19:13
by Rittai_3D
>>softya様
返信ありがとうございます。
>デバッガやprintfなどで、ちゃんと動作をトレースしましたか?
>構造体に確実に情報が格納される動作をしているか確認する作業をしていない気がします。
>「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
> blog.php?u=114&b=982&c=2
>途中の動作をprintfでちゃんと確認してみてください。
これからデバッガを使って確認してみます。勉強の合間にやっていたのでデバッガでの確認していませんでした。すいません。あと、URLありがとうございます。もっとデバッグ力(?)をつけたいです。
>あと17曲なのに配列16要素とか、path[ 16 ];とかギリギリ過ぎてバグを狙っているとしか思えない>です。変な節約は自分の首を締めるだけですよ。
>最初の4行コメントとか決め打ちもバグを生みそうな予感もします。4行決め打ちだから16曲なのかもしれませんが、あまり気持ちよくない仕様です。
配列は単純なうち間違えです。すいません。
path[16];なのは、もともとpath[128]としていましたが、DrawFormatString()でパスが表示されるか確認した時に、フフフフと表示されてしまったので、ギリギリにしました。
最初の4行は特に意味は無いです。最初のコメントは3行でしたが、投稿するのにどこがどの部分か分かりづらいかなと思い、一行増やしただけです。
最初のコメントは、龍神録のcsvをみてそれを真似しただけです、
Re: CSVファイルからの読み込み
Posted: 2013年6月26日(水) 19:16
by softya(ソフト屋)
> すべて全角にした方がいいでしょうか?
どうすれば、全角の処理となるか理解していますか? 文字コードの把握をされていない気がします。
【追記】
>path[16];なのは、もともとpath[128]としていましたが、DrawFormatString()でパスが表示されるか確認した時に、フフフフと表示されてしまったので、ギリギリにしました。
それは対処療法でバグを蔓延させる可能性がある選択ですね。まず、原因を探りましょう。
Re: CSVファイルからの読み込み
Posted: 2013年6月26日(水) 19:22
by Rittai_3D
>>softya様
返信ありがとうございます。
>どうすれば、全角の処理となるか理解していますか? 文字コードの把握をされていない気がします。
どういう意味ですか?2バイト進めるということですか?
Re: CSVファイルからの読み込み
Posted: 2013年6月26日(水) 19:24
by non
なるほど。
じゃ、52行目をよく見てください。
漢字コードは2バイトだから、2バイト目がたまたま、半角コードと一致することがあります。
Re: CSVファイルからの読み込み
Posted: 2013年6月26日(水) 19:25
by Rittai_3D
すいませんが、期末テスト真っ只中なので、返信がかなり送れる可能性があります。
返信できる暇があれば返信しますが、テストは来週の月曜まであり、提出物がたくさん出ていますので返信が出来ないかもしれません。
Re: CSVファイルからの読み込み
Posted: 2013年6月26日(水) 19:45
by usao
なんかCSVから読みたい人がたくさんいらっしゃる(?)ようですが,
既存を読めと言われているならともかく,自分で仕様を決めていいなら
自分が読み込み処理をしやすいフォーマットにすればいいのに…と思うんですが(一行に1アイテムとか).
Re: CSVファイルからの読み込み
Posted: 2013年6月26日(水) 20:03
by softya(ソフト屋)
期末テストを優先してくださいね。
usaoさんの考えは正しいですね。
わざわざ不十分なcsv的にするのはなぜなのでしょうか? → 本物のcsvだと文字列はダブルクォートで囲まれると思うのでその処理も必要です。
【補足】あるいは、もっとシンプル化するべきだと思います。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 06:47
by Rittai_3D
>>non様
返信ありがとうございます。
>漢字コードは2バイトだから、2バイト目がたまたま、半角コードと一致することがあります。
???どういうことですか?
理解力が無くてすいません。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 07:14
by Rittai_3D
>>usao様
返信ありがとうございます。
>なんかCSVから読みたい人がたくさんいらっしゃる(?)ようですが,
>既存を読めと言われているならともかく,自分で仕様を決めていいなら
>自分が読み込み処理をしやすいフォーマットにすればいいのに…と思うんですが(一行に1アイテムとか).
最初はテキストファイルで独自フォーマットにするつもりだったのですが、読み込み迄は問題なかったのですが、一行目に○○、二行目に…の判断の方法がわからず、諦めてしまいました。とりあえずcsvから読み込んで、成功したら独自フォーマットにしようと思っていました。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 07:21
by Rittai_3D
>>softya様
返信ありがとうございます。
>usaoさんの考えは正しいですね。
>わざわざ不十分なcsv的にするのはなぜなのでしょうか? → 本物のcsvだと文字列はダブルクォ>ートで囲まれると思うのでその処理も必要です。
>【補足】あるいは、もっとシンプル化するべきだと思います。
先程書いたように、もともとテキスト形式の独自フォーマットにするつもりでしたが、判定がうまく出来ずにcsvならできるのでは?と思い、csvにしました。
シンプル化…ですか?自分はこれ以上シンプルな物が考えつきません…
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 09:26
by usao
「一行1アイテム」ってのは”あなたが現状カンマで区切ってるところを全て改行区切りにする”というだけのことですよ.
要素をどの順に書くかは自分で決めている(CSVだってそうだ)んだから読み込むときに困ることは微塵もないと思います.
「ファイルから1行分の文字列を読む」さえできれば1アイテム手に入るのだから処理が簡単ってことです.
(「文字列内を走査してカンマを見つけたらどうの」という手順が不要)
それはそれとして,提示コードについては 変数nの振る舞いを確認された方が良いと思います.
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 12:37
by かずま
C++ なら簡単なんですけどね。
コード:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
struct music_t {
string path, name1, name2, comment;
};
int LoadScript(vector<music_t>& music)
{
ifstream ifs("music.csv");
if (!ifs) { cerr << "script file open error\n"; return 1; }
string line;
while (getline(ifs, line)) {
if (line[0] == '#') continue;
istringstream iss(line);
music_t m;
getline(iss, m.path, ',');
getline(iss, m.name1, ',');
getline(iss, m.name2, ',');
getline(iss, m.comment);
music.push_back(m);
}
return 0;
}
int main()
{
vector<music_t> music;
if (LoadScript(music)) return 1;
for (int i = 0; i < music.size(); i++) {
const music_t& m = music[i];
cout << "[" << m.path << "] [" << m.name1
<< "] [" << m.name2 << "] [" << m.comment << "]\n";
}
return 0;
}
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 14:46
by Rittai_3D
>>usao様
返信ありがとうございます。
>「一行1アイテム」ってのは”あなたが現状カンマで区切ってるところを全て改行区切りにする”というだけのことですよ.
>要素をどの順に書くかは自分で決めている(CSVだってそうだ)んだから読み込むときに困ることは微塵もないと思います.
「ファイルから1行分の文字列を読む」さえできれば1アイテム手に入るのだから処理が簡単ってことです(「文字列内を走査してカンマを見つけたらどうの」という手順が不要)
解説ありがとうございます。先ほど、csvファイルをおっしゃる様に変えて来ました。
それはそれとして,提示コードについては 変数nの振る舞いを確認された方が良いと思います.
softya様の回答の中の
>「簡単RPG講座 番外編。 デバッグ入門 • C言語交流フォーラム ~ mixC++ ~」
>blog.php?u=114&b=982&c=2
でprintfデバッグをしたところ、何故かnが22までいっていました。これが原因ですかね?
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 14:58
by Rittai_3D
>>かずま様
返信ありがとうございます。
自分はC++を勉強していないので詳しい事はわかりませんが、C++でやると楽と言うことがわかります。
C言語マスターしたらC++も勉強したいです。
コードありがとうございます。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 16:50
by softya(ソフト屋)
誤解してそうなので書いておくと、usaoさんの提案は今の読み方をやめて全部fgets()やfread()など簡単な方法で読み込みましょうよって意味も含んでいます。そうすれば1バイトづつ読むことで生じる文字コード問題からも解放されるので、おすすめなのです。
たぶんサンプル等を当てにしすぎて、仕様を決めてなにもない所からソースコードを起こす事に慣れていないのが原因だと思いますので、ここを乗り越えたら作り方も分かってくると思います。
あとかずまさんのは書くのは楽できますが、根本を理解していないとデバッグで困ることになるのでC言語的なレベルで理解をおすすめします。
つまり、今を頑張りましょう。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 16:56
by Rittai_3D
皆様、たくさんの回答ありがとうございました。
おかげでちゃんと描写することが出来ました。
'\n'の判定をinput
からinputcに変えただけで簡単に出来ました。
何で出来たんだろう...?
一応解決したのでコードを張っておきます
コード:
#define _CRT_SECURE_NO_WARNINGS 1
#include "DxLib.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char path[ 256 ]; //曲のコメント(パス)
char name1[ 256 ]; //(名前1)
char name2[ 256 ]; //(名前2)
char comme[ 256 ]; //(コメント)
}music_t;
static music_t music[ 17 ];
int ProcessLoop()
{
if( ProcessMessage() != 0 ) return 1;
if( ClearDrawScreen() != 0 ) return 1;
return 0;
}
void Load_Script()
{
char FileName[] = "music.txt";
int i,num=0,n=0; // n曲
int input[64];
char inputc[64];
FILE* fp = fopen( FileName , "r" );
if( fp == NULL ){
MessageBox( NULL, TEXT("Script File Read Error"), TEXT("Error"), MB_OK | MB_ICONERROR );
return;
}
for(i=0 ; i<4 ; i++ ) // 最初の4行はコメントなので読み飛ばす
while( fgetc( fp ) != '\n' );
while( 1 ){
for(i=0 ; i<64 ; i++ ){
input[i] = inputc[i] = fgetc( fp );
if( input[i] == '#' ){
while( fgetc( fp ) != '\n' );
i = -1;
continue;
}
if( input[i] == '\n' ){
inputc[i] = '\0'; // ここを input[i] -> inputc[i]に変えました。
break;
}
if( input[i] == EOF ){
goto EXFILE;
}
}
switch( num ){
case 0: strcpy( music[n].path , inputc ); break;
case 1: strcpy( music[n].name1, inputc ); break;
case 2: strcpy( music[n].name2, inputc ); break;
case 3: strcpy( music[n].comme, inputc ); break;
}
num++;
if( num == 4 ){
num = 0;
n++;
}
}
EXFILE:
fclose( fp );
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int)
{
ChangeWindowMode( TRUE ) , SetAlwaysRunFlag( TRUE ) , DxLib_Init() , SetDrawScreen( DX_SCREEN_BACK );
int i;
Load_Script();
while( !ProcessLoop() ){
for(i=0 ; i<17 ; i++ ){
// DrawFormatString( 0, 0+16*i,GetColor(255,255,255) , "music[%2d].path = %s", i,music[i].path ); //パス
// DrawFormatString( 0, 0+16*i,GetColor(255,255,255), "music[%2d].name1 = %s", i,music[i].name1 ); //名前1
// DrawFormatString( 0, 0+16*i,GetColor(255,255,255), "music[%2d].name2 = %s", i,music[i].name2 ); //名前2
DrawFormatString( 0, 0+16*i,GetColor(255,255,255), "music[%2d].comme = %s", i,music[i].comme ); //コメント
}
ScreenFlip();
}
DxLib_End();
return 0;
}
ついでに、CSVファイルから以下のテキストファイルに変えました。
コード:
#
# 曲の情報
#一行目:パス.二行目:曲名1.三行目:曲名2.四行目:コメント
dat/th06_01.wav
No1. 赤より紅い夢
♪赤より紅い夢
コメント1
#
dat/th06_02.wav
No2. ほおずきみたいに紅い魂
♪ほおずきみたいに紅い魂
コメント2
#
dat/th06_03.wav
No3. 妖魔夜行
♪妖魔夜行
コメント3
#
dat/th06_04.wav
No4. ルーネイトエルフ
♪ルーネイトエルフ
コメント4
#
dat/th06_05.wav
No5. おてんば恋娘
♪おてんば恋娘
コメント5
#
dat/th06_06.wav
No6. 上海紅茶館 ~ Chinese Tea
♪上海紅茶館 ~ Chinese Tea
コメント6
#
dat/th06_07.wav
No7. 明治十七年の上海アリス
♪明治十七年の上海アリス
コメント7
#
dat/th06_08.wav
No8. ヴワル魔法図書館
♪ヴワル魔法図書館
コメント8
#
dat/th06_09.wav
No9. ラクトガール ~ 少女密室
♪ラクトガール ~ 少女密室
コメント9
#
dat/th06_10.wav
No10. メイドと血の懐中時計
♪メイドと血の懐中時計
コメント10
#
dat/th06_11.wav
No11. 月時計 ~ ルナ・ダイアル
♪月時計 ~ ルナ・ダイアル
コメント11
#
dat/th06_12.wav
No12. ツェペシュの幼き末裔
♪ツェペシュの幼き末裔
コメント12
#
dat/th06_13.wav
No13. 亡き王女の為のセプテット
♪亡き王女の為のセプテット
コメント13
#
dat/th06_14.wav
No14. 魔法少女達の百年祭
♪魔法少女達の百年祭
コメント14
#
dat/th06_15.wav
No15. U.N.オーエンは彼女なのか?
♪U.N.オーエンは彼女なのか?
コメント15
#
dat/th06_16.wav
No16. 紅より儚い永遠
♪紅より儚い永遠
コメント16
#
dat/th06_17.wav
No17. 紅楼 ~ Eastern Dream...
♪紅楼 ~ Eastern Dream...
コメント17
まだまだ未熟者ですが、これからも宜しくお願いします。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 16:58
by softya(ソフト屋)
3D_3D さんが書きました:皆様、たくさんの回答ありがとうございました。
おかげでちゃんと描写することが出来ました。
'\n'の判定をinputからinputcに変えただけで簡単に出来ました。
何で出来たんだろう...?
そこを今理解しておかないと、ほぼ確実に後で困ることになるでしょう。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 17:10
by Rittai_3D
>>softya様
返信ありがとうございます。
>誤解してそうなので書いておくと、usaoさんの提案は今の読み方をやめて全部fgets()やfread()など簡単な方法で読み込みましょうよって意味も含んでいます。そうすれば1バイトづつ読むことで生じる文字コード問題からも解放されるので、おすすめなのです。
ちょうど解決と重なってしまいましたが、このような方法もあるのですね。期末テストが終ったらfgets()やfread()でもやってみたいと思います。
>あとかずまさんのは書くのは楽できますが、根本を理解していないとデバッグで困ることになるのでC言語的なレベルで理解をおすすめします。
>つまり、今を頑張りましょう。
わかりました。ついでに、C言語を使えるようになるまで他の言語は使わないつもりです。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 17:25
by Rittai_3D
>>softya様
返信ありがとうございます。
>そこを今理解しておかないと、ほぼ確実に後で困ることになるでしょう。
自分なりの解釈は「文字列の終わりは'\n'の1バイト文字。intは2バイト格納するので'\r\n'で余分に判定してしまっている。charは1バイト格納するので余分な判定はしていない」です。間違えていたらすいません。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 18:41
by softya(ソフト屋)
3D_3D さんが書きました:
自分なりの解釈は「文字列の終わりは'\n'の1バイト文字。intは2バイト格納するので'\r\n'で余分に判定してしまっている。charは1バイト格納するので余分な判定はしていない」です。間違えていたらすいません。
それの直接的な答えは言いませんが、デバッガで確認してみてください。推論したら自分で検証することが一番大事です。
あとgetc()の機能を勘違してませんか?
それにint型は4バイトですよ。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 20:56
by Rittai_3D
>>softya様
返信ありがとうございます
>それの直接的な答えは言いませんが、デバッガで確認してみてください。推論したら自分で検証することが一番大事です。
わかりました。明日の朝にでも確認してみます。
>あとgetc()の機能を勘違してませんか?
ファイルから一文字読み取るですよね?なにか変ですか?
>それにint型は4バイトですよ。
あれ、何が勘違いしていたようです。すいません
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 21:03
by non
>intは2バイト格納するので'\r\n'で余分に判定してしまっている。
ここのところが、理解しているのかわからないところです。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 22:47
by Rittai_3D
>>non様
返信ありがとうございます。
>ここのところが、理解しているのかわからないところです。
そこは、自分なりに解釈した部分です。
文字列は自分の日記のコメントにもあるようにあやふやなので、理解出来るように勉強します。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 23:12
by softya(ソフト屋)
> ファイルから一文字読み取るですよね?なにか変ですか?
そこが問題なんですよ。getcのcは何だと思いますか?
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 23:22
by Rittai_3D
>>softya様
返信ありがとうございます。
>そこが問題なんですよ。getcのcは何だと思いますか?
c...
charってことですか?
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 23:24
by softya(ソフト屋)
3D_3D さんが書きました:>>softya様
返信ありがとうございます。
>そこが問題なんですよ。getcのcは何だと思いますか?
c...
charってことですか?
というのも含めてデバッガで確認してみてくださいね。
ちなみに戻り値の型はintです。
Re: CSVファイルからの読み込み
Posted: 2013年6月27日(木) 23:33
by Rittai_3D
>>softya様
返信ありがとうございます。
>というのも含めてデバッガで確認してみてくださいね。
>ちなみに戻り値の型はintです。
明日の朝、もしくはそれ以降にならないと確認が出来ません。
本当は今すぐにでも確認してみたいです。
そういえば、charは一文字格納でしたよね?getc()も一文字取得…何か繋がりがありそうな気がします。
Re: CSVファイルからの読み込み
Posted: 2013年6月29日(土) 20:23
by Rittai_3D
確認しました。
よくわからなかったです...
自分のプログラミング力が乏しいため、デバッガで確認はしましたがよくわからなかったです。
Re: CSVファイルからの読み込み
Posted: 2013年6月29日(土) 20:47
by softya(ソフト屋)
文字コードが16進数でどうなっているか把握する必要があります。
「文字コード表 シフトJIS(Shift_JIS)」
http://charset.7jp.net/sjis.html
> 自分のプログラミング力が乏しいため、デバッガで確認はしましたがよくわからなかったです。
それを向上させるためにデバッガで確認するのです。
動作(戻り値や実際ぬ動き)を目で確認して、関数のドキュメントなどを読んで両者を完全にシンクロさせましょう。
Re: CSVファイルからの読み込み
Posted: 2013年6月29日(土) 21:11
by Rittai_3D
>>softya様
返信ありがとうございます
>文字コードが16進数でどうなっているか把握する必要があります。
「文字コード表 シフトJIS(Shift_JIS)」
URLありがとうございます。確認してみます。
>それを向上させるためにデバッガで確認するのです。
>動作(戻り値や実際ぬ動き)を目で確認して、関数のドキュメントなどを読んで両者を完全にシンクロさせましょう。
わかりました。デバッグ初心者ですが、初心者なりに頑張ります。
返信は明日の朝になると思います。パソコンが使えなくなってしまったためです。
Re: CSVファイルからの読み込み
Posted: 2013年6月30日(日) 18:02
by Rittai_3D
確認しましたが、よくわからないです。
初心者なりにウォッチを使ってみたり、検索したり、printf()で出力しましたが、結果は得られませんでした。
教えて頂いたURLで調べましたが、iPhoneから見ていたので、見れない物もありました。
文字コードが16進数でどうなっているか調べてどうするのか教えてください。
失礼だと思いますが、調べる理由がわかりません。
Re: CSVファイルからの読み込み
Posted: 2013年6月30日(日) 20:15
by softya(ソフト屋)
3D_3D さんが書きました:確認しましたが、よくわからないです。
初心者なりにウォッチを使ってみたり、検索したり、printf()で出力しましたが、結果は得られませんでした。
教えて頂いたURLで調べましたが、iPhoneから見ていたので、見れない物もありました。
文字コードが16進数でどうなっているか調べてどうするのか教えてください。
失礼だと思いますが、調べる理由がわかりません。
これの確認のためなんですよ。
自分なりの解釈は「文字列の終わりは'\n'の1バイト文字。intは2バイト格納するので'\r\n'で余分に判定してしまっている。charは1バイト格納するので余分な判定はしていない」です。間違えていたらすいません。
どうですか、解釈と一致してますか?
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 16:54
by Rittai_3D
>>softya様
返信ありがとうございます。
>どうですか、解釈と一致してますか?
全く違かったようです。
inputは文字コードだけを格納して、inputcは文字コードと、その文字を格納しているように思えます。
例) aをウォッチでみると
int : 97 (0x0000002e)
char : 97'a ' (0x61'a')
となっていました。
もしかして、intはprintf()した時に、文字コードを数字から変換しているから、フフフフフフフと表示される。フフフフフは/r/nの分(?)で
charは、文字コードの後ろのシングルクオートの中をそのままprintf()するから、フフフフフは出力されない
と言うことですか?
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 17:42
by softya(ソフト屋)
> inputは文字コードだけを格納して、inputcは文字コードと、その文字を格納しているように思えます。
それはデバッガの表示動作です。両方共数値データしか保持してません。
>もしかして、intはprintf()した時に、文字コードを数字から変換しているから、フフフフフフフと表示される。フフフフフは/r/nの分(?)で
>charは、文字コードの後ろのシングルクオートの中をそのままprintf()するから、フフフフフは出力されない
変換は書式で決まります。%s,%d,%cでは動作が違うわけで元の型には左右されませんよ。
97と言う値が入っているなら、97を書式で変換したものが表示されます。
ということで、もう一度考えてみましょう。
(1)解釈→(2)検証
この作業を繰り返すことで文字コードの本質が見えてきます。がんばりましょう。
【補足】 これが、工学系(理系的)学習の基本なんですけどね。 推論する→実験して確認
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 19:12
by Rittai_3D
>>softya様
返信ありがとうございます。
getcの戻り値について調べたところ、一文字の文字コードが帰るとありました。
また、input と inputc を printf() したところ、気になったところが出てきました。
コード:
# 一曲目
inputc = dat/th06_01.wav
input = d
inputc = No.1 赤より紅い夢
input = N
inputc = コメント1
input = ・□□@ # 文字化け
# 2曲目
...
と同じような文字が全曲分出力されました。
コメントは文字化けしてしまいましたが、int型は1バイト文字の一文字だけ格納しているように思えます。
おそらく、コメントの文字化けは全角文字の為だと思います。
これであってますか?
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 19:25
by softya(ソフト屋)
それは、まだ理解不足があります。
文字列はchar型の配列ですから、inputcを%sでprintfすれば全部の文字列が見えるでしょう。
inputを%sでprintfすると型が違うので正しくprintfはされません。%sはchar型配列に限定された機能だからです。
なので本来はinputを表示する前提で話してはいけないのですが、文字コードの学習になると思うので続けます。
inputの場合、たまたまx86系CPUのint型のメモリ格納方式(リトル・エンディアン方式)の都合のおかげである条件の一文字目だけは表示されます。
さて、その条件とは何だと思いますか?
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 19:44
by Rittai_3D
>>softya様
返信ありがとうございます。
リトル・エンディアン方式についてざっくり調べましたがよくわかりませんでした。
自分が思うに、半角文字でしょうか?
実際、1文字目が半角の時は一文字出力されていましたが、全角文字のコメントは文字化けして表示されませんでしたので、そのように考えました。
文字コード難しいです…
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 20:02
by softya(ソフト屋)
リトル・エンディアンは数値のメモリへの格納方式です。ハードウェアの都合と言ったほうが良いでしょうか。
文字コードとは何の関係もないですが、バイナリファイルを扱う時は結構重要な問題です。
※ 世の中にはビック・エンディアン方式のCPUが存在するため無頓着だと互換性が取れなくなる恐れがあります。
まぁ、inputとinputcで格納されたものが配列全体ではなく、1要素毎にどうなっているかを確認して貰いたい所です。
特に文字化けしている所をですね。
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 20:17
by Rittai_3D
>>softya様
返信ありがとうございます。
何故かエラー落ちして確認出来ませんでした。
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 20:36
by softya(ソフト屋)
ちなみに身近な処でビックエンディアンなのはARMを使っているandroidです。
Javaの時はリトル変換されるみたいですが、android NDKを使う場合は、エンディアンをちゃんと意識する必要があるとの事です。
> 何故かエラー落ちして確認出来ませんでした。
VC++を再起動してもダメですか?
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 20:44
by Rittai_3D
>>softya様
返信ありがとうございます。
VC++を何回が再起動してもダメでした。
パソコンも再起動しましたが、ダメでした。
どうも、毎回エラー落ちするのがprintf()のところで、
printf("input[0] = %s\n",input[0] );
printf("inputc[0] = %s\n",inputc[0]);
としています。もしかしたら、自分の書き方が悪いのかもしれません。
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 21:07
by softya(ソフト屋)
落ちるというのは勘違いしてましてがVC++ではなく実行しているプログラムですか?
であれば、%sは既に書いた通り型が限定されます。型が違うものを表示しようとしているでエラーで確実に落ちると思います。
これがポインタの扱いを間違ったときに起きる現象ですよ。ポインタを扱うなら知ってないといけない現象です。
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 22:01
by Rittai_3D
>>softya様
返信ありがとうございます。
そうです、実行しているプログラムです。
%sの事をすっかり忘れていました。
ところで、
printf("input[0] = %c\n",input[0] );
とやっても上手く表示されません。なぜでしょうか?
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 22:09
by softya(ソフト屋)
> printf("input[0] = %c\n",input[0] );
> とやっても上手く表示されません。なぜでしょうか?
input[0]に入っているのはどんな値で、どういう風に表示されますか? そして、想定ではどう表示されるはずでしたか?
具体的でないとこちらも分からないので、私も困ります。
※ フォーラムルールでも一番悪い例に書かれている質問パターンなんですよね。
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 22:22
by non
二人で盛り上がっているところ、割り込んで申し訳ありませんが、
実験しているプログラムと、そのときの入力を示してください。
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 22:43
by Rittai_3D
>>softya様
返信ありがとうございます。
すいません、いろいろ混乱して訳のわからない事を書いてしまいました。
確認してみたら、半角の時は、ちゃんとdと表示されましたが、全角の時は、inputcもinputも点で表示されました。
(テキストファイルのパスのdatを全角にしました。)
また、半角の場合は[0]~[2]を使っていたのが[0]~[5]に増えました
Re: CSVファイルからの読み込み
Posted: 2013年7月01日(月) 23:17
by Rittai_3D
>>non様
返信ありがとうございます。全部のコードを貼った方がいいですか?
どちらにしろ、明日の夜にならないとコードは張れません。
自分のパソコンがインターネットに繋がってなく、親のパソコンを借りてコードを貼っていて、さらに10時以降はパソコンの使用が禁止されているからです。
すいません。
Re: CSVファイルからの読み込み
Posted: 2013年7月03日(水) 10:26
by Rittai_3D
申し訳ありませんが、ソースは今日の夜まで待っていただけないでしょうか?
昨日は、部活やら宿題やらでパソコンに触れませんでした。
Re: CSVファイルからの読み込み
Posted: 2013年7月03日(水) 11:17
by ilish
本当にここの掲示板の回答は胸糞悪いですね・・・
陰湿極まりない・・・・
ソフト屋って人ってもしかしらたらまだ中級者くらいなのでは?
回答しまくってるからハッカーとか変な称号ついてるけど・・・
Re: CSVファイルからの読み込み
Posted: 2013年7月03日(水) 20:00
by Rittai_3D
大変長らくお待たせしました。ソースになります。汚いです。
コード:
#define _CRT_SECURE_NO_WARNINGS 1
#include "DxLib.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char path[ 256 ]; //曲のコメント(パス)
char name1[ 256 ]; //(名前1)
char name2[ 256 ]; //(名前2)
char comme[6][ 256 ]; //(コメント)
}music_t;
// 構造体
static music_t music[ 17 ]; // 後で色々面倒になるので此処で実体を作る
int ProcessLoop() // 毎回行う必要のある事
{
if( ProcessMessage() != 0 ) return 1;
if( ClearDrawScreen() != 0 ) return 1;
return 0;
}
void Load_Script() // スクリプトの読み込み
{
char FileName[] = "music.txt"; // ファイルの名前
int i,num=0,n=0,line=0; // n曲目の判断やfor文関係
int input[64]; // 一文字読み込むのに必要
char inputc[64]; // 上に同じ
FILE* fp = fopen( FileName , "r" ); // ファイルを開く
if( fp == NULL ){ // ファイルが無い時の処理
MessageBox( NULL, TEXT("Script File Read Error"), TEXT("Error"), MB_OK | MB_ICONERROR );
return;
}
for(i=0 ; i<4 ; i++ ) // 最初の4行はコメントなので読み飛ばす
while( fgetc( fp ) != '\n' );
while( 1 ){
for(i=0 ; i<64 ; i++ ){ // 横64文字まで読み込んで
input[i] = inputc[i] = fgetc( fp );
if( input[i] == '#' ){ // コメント記号ならば
while( fgetc( fp ) != '\n' ); // その行の終わりまでループして
i = -1; // カウンタを戻して
continue;
}
if( input[i] == '\n' ){ // 改行記号なら(独自フォーマットのファイルだから改行で区切る)
inputc[i] = '\0'; // そこまでを文字列にして
break;
}
if( input[i] == EOF ){ // EOFなら(ここは、charで判断はしないほうが良い)
goto EXFILE; // ファイルクローズタグにジャンプ
}
}
switch( num ){ // 読み込んだファイルから構造体にコピーする
case 0: strcpy( music[n].path , inputc ); break; // 音楽再生の為のパス
case 1: strcpy( music[n].name1, inputc ); break; // 名前1 : No.~
case 2: strcpy( music[n].name2, inputc ); break; // 名前2 : ♪~
/* -----------------以下、コメント読み込み----------------- */
case 3: strcpy( music[n].comme[ line ], inputc );break;
case 4: strcpy( music[n].comme[ line + 1 ], inputc );break;
case 5: strcpy( music[n].comme[ line + 2 ], inputc );break;
case 6: strcpy( music[n].comme[ line + 3 ], inputc );break;
case 7: strcpy( music[n].comme[ line + 4 ], inputc );break;
case 8: strcpy( music[n].comme[ line + 5 ], inputc );break;
/* -------------------------------------------------------- */
}
num++; // num加算
if( num == 9 ){ // numの値が9(1曲分のファイル読み込みが終わったら)なら
num = 0; // numを加算
n++; // nも加算
}
for(i=0 ; i<64 ; i++ )
printf("inputc[%d] = %c = %p\n",i,input[i]);
// printf("inputc[%d] = %s\n", n,inputc);
// printf("input [%d] = %s\n", n,input);
WaitKey();
}
EXFILE: // ファイルクローズ
fclose( fp );
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int)
{
AllocConsole();
freopen( "CONOUT$", "w", stdout );
ChangeWindowMode( TRUE ) , SetAlwaysRunFlag( TRUE ) , DxLib_Init() , SetDrawScreen( DX_SCREEN_BACK ); // おきまりの処理
int i,j; // for文で使います。
Load_Script(); // スクリプト読み込む
while( !ProcessLoop() ){ // メインループ
// for(i=0 ; i<17 ; i++ ){ // 全曲分ループ
//DrawFormatString( 0, 0+16*i,GetColor(255,255,255), "music[%2d].path = %s", i,music[i].path ); // パスを表示
//DrawFormatString( 0, 0+16*i,GetColor(255,255,255), "music[%2d].name1 = %s", i,music[i].name1 ); // 名前1を表示
//DrawFormatString( 0, 0+16*i,GetColor(255,255,255), "music[%2d].name2 = %s", i,music[i].name2 ); // 名前2を表示
//for(j=0 ; j<6 ; j++ )
// DrawFormatString( 0, 0+16*j,GetColor(255,255,255), "music[0].comme[%d] = %s", j+1, music[1].comme[j] ); // コメント6行表示
// }
/* for(j=0 ; j<17 ; j++ )
printf("music[%d].path\n= %s\n= %p\n= %8X\n", j,music[j].path, music[j].path, music[j].path );
WaitKey();
*/
ScreenFlip(); // 裏画面の画像を表画面に
}
// ----------------終了処理---------------
DxLib_End();
return 0;
}
一応読み込むテキストファイルも張っておきます。
コード:
# --------------------------------------------------------------
# 曲の情報
# --------------------------------------------------------------
dat/th06_01.wav
# ここのdatを全角文字にしました。
No1. 赤より紅い夢
♪赤より紅い夢
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_02.wav
No2. ほおずきみたいに紅い魂
♪ほおずきみたいに紅い魂
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_03.wav
No3. 妖魔夜行
♪妖魔夜行
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_04.wav
No4. ルーネイトエルフ
♪ルーネイトエルフ
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_05.wav
No5. おてんば恋娘
♪おてんば恋娘
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_06.wav
No6. 上海紅茶館 ~ Chinese Tea
♪上海紅茶館 ~ Chinese Tea
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_07.wav
No7. 明治十七年の上海アリス
♪明治十七年の上海アリス
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_08.wav
No8. ヴワル魔法図書館
♪ヴワル魔法図書館
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_09.wav
No9. ラクトガール ~ 少女密室
♪ラクトガール ~ 少女密室
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_10.wav
No10. メイドと血の懐中時計
♪メイドと血の懐中時計
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_11.wav
No11. 月時計 ~ ルナ・ダイアル
♪月時計 ~ ルナ・ダイアル
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_12.wav
No12. ツェペシュの幼き末裔
♪ツェペシュの幼き末裔
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_13.wav
No13. 亡き王女の為のセプテット
♪亡き王女の為のセプテット
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_14.wav
No14. 魔法少女達の百年祭
♪魔法少女達の百年祭
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_15.wav
No15. U.N.オーエンは彼女なのか?
♪U.N.オーエンは彼女なのか?
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_16.wav
No16. 紅より儚い永遠
♪紅より儚い永遠
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
dat/th06_17.wav
No17. 紅楼 ~ Eastern Dream...
♪紅楼 ~ Eastern Dream...
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
#
# コメントは6行に増やしました。
>まぁ、inputとinputcで格納されたものが配列全体ではなく、1要素毎にどうなっているかを確認して貰いたい所です。
特に文字化けしている所をですね。
ここで質問ですが、これはprintf("%c\n",input
);とすればいいのですか?そしたら、全角文字はすべて点で表示されました。
Re: CSVファイルからの読み込み
Posted: 2013年7月03日(水) 20:34
by softya(ソフト屋)
> ここで質問ですが、これはprintf("%c\n",input);とすればいいのですか?そしたら、全角文字はすべて点で表示されました。
SHIFT-JISの場合、全角文字は2文字分で1つの文字を構成します。
なので、1文字だけ出力しても点など意味のない無い文字となってしまうことが多いです。あるいは全く無関係な文字として表示されます。
なので正しいデバッグとしては、数値を%xなどで表示するか、デバッガで確認するなどが方法です。
文字化けした%sの表示の場合は、int型は4つのchar型と同じメモリサイズですので上位桁は00で埋まっていることになります。これ文字列の終端と同じコードです。
つまり、int型の最初のinput[0]で表示は必ず止まることになります。
と言うことを実際にデバッガなので確認して頂けたらなと思います。
※ ポインタの勉強ですので。
Re: CSVファイルからの読み込み
Posted: 2013年7月03日(水) 21:07
by non
文字コードの勉強のために、このまま続けるのも良いのですが、データファイルを1行ずつで改行したのは、行をまとめて
読むためです。そうすれば、半角、全角のチェックもいらないし、ものすごく簡単になるからです。
fgetsを使って1行まとめて読み込むように変えたらどうでしょうか?
Re: CSVファイルからの読み込み
Posted: 2013年7月04日(木) 07:54
by Rittai_3D
>>softya様
返信ありがとうございます。
>つまり、int型の最初のinput[0]で表示は必ず止まることになります。
>と言うことを実際にデバッガなので確認して頂けたらなと思います。
ウォッチで確認したところ、全角文字は0xffffff82のような値になり、半角文字は0x00000074のようになりました。
ポインタの理解を深めて行きたいとおもいます。
Re: CSVファイルからの読み込み
Posted: 2013年7月04日(木) 07:57
by Rittai_3D
>>non様
返信ありがとうございます。
>文字コードの勉強のために、このまま続けるのも良いのですが、データファイルを1行ずつで改行したのは、行をまとめて
>読むためです。そうすれば、半角、全角のチェックもいらないし、ものすごく簡単になるからです。
>fgetsを使って1行まとめて読み込むように変えたらどうでしょうか?
そうですね。期末テストも終わったので、今度の土日にでも作ってみます。作りましたらコードを貼りますのでここはこうやってやった方がいいよ、などの指摘をお願いします。