たびたびお世話になっております。
DxLib現在簡単なゲームを作っているのですが、
ファイルからキャラクターのパラメータを読み込み、
それを変数へ反映させようとして、トラぶっています。
コードはこんな感じ↓
{
int file=FileRead_open("ファイル名");
int parm[6]; //パラメータ格納用。
char str[50];
FileRead_gets(str, sizeof(str), file);
//一行読み込み、仮に"000,001,002,003,004,005,";
str2[6][3];
for(int i=0;i<6;i++){
memcpy(&str2,&str[i*4],sizeof(str2[0]));
parm=atoi(str);
}
原因は、memcpyの扱い方だと思うのですが、
たとえば
str2[0][0],str2[0][1],str2[0][3],
ここについては、きちんと=0,=0,=0
と格納されているのですが、
str2[0]全体の値は、
"0x0012e5ac "000001002003004005006フフフフフフフフフフフフフフフフフフフフフフフ…(中略)"
とか、なっている。
で、結局parmには、全然意図してない、値が入ってしまう。
parm[0]=atoi(str2[0][0])*100+atoi(str2[0][1])*10+atoi(str[0][2]);
とかでは、
数が増えてきたとき、面倒そうなので、
なにかすっきりした、解決策を思いつく方は教えてください。
PS:
前回の質問は、メモリについてどんなものなのか、
まったく認識しておらず(今でも漠然)、
トンチンカンなコメントをしたように思います。
ご迷惑をおかけしました。
Cの文字列の扱いが得意な人へ、質問です
Re:Cの文字列の扱いが得意な人へ、質問です
文章の終わりを示す、NULL('\0')が含まれていないからではないでしょうか。
char型の配列に1文字分の余裕を持たせる必要があると思います。
# memcpyを使ったことがないほど、文字列の扱いが不十分なので曖昧な回答ですが・・・
# 追記
検索してみたところ、memcpyは空文字('\0')を付加せず、
また、途中に空文字が含まれていてもコピーを続ける関数だそうです。
char型の配列に1文字分の余裕を持たせる必要があると思います。
# memcpyを使ったことがないほど、文字列の扱いが不十分なので曖昧な回答ですが・・・
# 追記
検索してみたところ、memcpyは空文字('\0')を付加せず、
また、途中に空文字が含まれていてもコピーを続ける関数だそうです。
Re:Cの文字列の扱いが得意な人へ、質問です
プログラムの意味がわかりません。
>int file="ファイル名";
これはエラーでしょう。
>FileRead_gets(std, sizeof(std), file);
stdって何ですか?strかな?
>str2[6][3];
"000"を入れるなら4バイト必要では?
>//一行読み込み、仮に"000,001,002,003,004,005,006,";
データは7個あるみたいだけど?
データが1行にカンマ区切りで7個ある数値をファイルから読みたいという
ことなのでしょうか?
必ずこうだというのなら
int parm[7];
sprintf(str,"%d,%d,%d,%d,%d,%d,%d",&parm[0],&parm[1],&parm[2],&parm[3],&parm[4],&parm[5],&parm[6]);
でよいのでは。
>int file="ファイル名";
これはエラーでしょう。
>FileRead_gets(std, sizeof(std), file);
stdって何ですか?strかな?
>str2[6][3];
"000"を入れるなら4バイト必要では?
>//一行読み込み、仮に"000,001,002,003,004,005,006,";
データは7個あるみたいだけど?
データが1行にカンマ区切りで7個ある数値をファイルから読みたいという
ことなのでしょうか?
必ずこうだというのなら
int parm[7];
sprintf(str,"%d,%d,%d,%d,%d,%d,%d",&parm[0],&parm[1],&parm[2],&parm[3],&parm[4],&parm[5],&parm[6]);
でよいのでは。
Re:Cの文字列の扱いが得意な人へ、質問です
その通りでした。
str2[6][3];
for(int i=0;i<6;i++){
memcpy(&str2,&str[i*4],sizeof(str2[0][0]*2));
str2[2]='\0';
parm=atoi(str);
}
……一瞬で解決(!_!)
すごく簡単な質問で、逆に申しわけなかったです。
ランドさんありがとうございました。
str2[6][3];
for(int i=0;i<6;i++){
memcpy(&str2,&str[i*4],sizeof(str2[0][0]*2));
str2[2]='\0';
parm=atoi(str);
}
……一瞬で解決(!_!)
すごく簡単な質問で、逆に申しわけなかったです。
ランドさんありがとうございました。
Re:Cの文字列の扱いが得意な人へ、質問です
non さんのご指摘とおりです。
コードは、即興で書かせてもらったものなので、
誤植が多々あったようです。
修正しておきましょう。
今回、フォーマットについては、
未だ制作途中(仮データ)なので、
あまり考えていないのですが、
フォーマットを決定した場合は、
参考にさせていただきたいと思います。
non さん、
ご意見ありがとうございます。
コードは、即興で書かせてもらったものなので、
誤植が多々あったようです。
修正しておきましょう。
今回、フォーマットについては、
未だ制作途中(仮データ)なので、
あまり考えていないのですが、
フォーマットを決定した場合は、
参考にさせていただきたいと思います。
non さん、
ご意見ありがとうございます。
Re:Cの文字列の扱いが得意な人へ、質問です
for(int i=0;i<6;i++){
memcpy(&str2,&str[i*4],sizeof(str2[0][0]*2));
str2[2]='\0';
parm=atoi(str);
}
↑かなり間違ってます。3桁の数字なのに先頭2文字づつ処理でよいのかとか。
まず、理解して欲しいのは文字列は必ず'\0'で終わないといけません。
なので、"000"は実際は4バイトです。
コピーするときは'\0'も含めてコピーするか、元に無い場合は自分で追加で書き込んでやる必要があります。
下記サイトの初級篇の文字列処理までを読んでみてください。
http://www.nurs.or.jp/~sug/soft/tora/index.htm
いくつか文字列と配列やポインタのサイトを載せますのでまず読んでみてください。
http://www2.netf.org/pointer3.html
http://www005.upp.so-net.ne.jp/h-masuda ... c1030.html
http://www9.plala.or.jp/sgwr-t/c/sec10-3.html
http://itpro.nikkeibp.co.jp/article/COL ... 31/252216/
ここで、ちゃんと文字列を理解する事から始めましょう。
memcpy(&str2,&str[i*4],sizeof(str2[0][0]*2));
str2[2]='\0';
parm=atoi(str);
}
↑かなり間違ってます。3桁の数字なのに先頭2文字づつ処理でよいのかとか。
まず、理解して欲しいのは文字列は必ず'\0'で終わないといけません。
なので、"000"は実際は4バイトです。
コピーするときは'\0'も含めてコピーするか、元に無い場合は自分で追加で書き込んでやる必要があります。
下記サイトの初級篇の文字列処理までを読んでみてください。
http://www.nurs.or.jp/~sug/soft/tora/index.htm
いくつか文字列と配列やポインタのサイトを載せますのでまず読んでみてください。
http://www2.netf.org/pointer3.html
http://www005.upp.so-net.ne.jp/h-masuda ... c1030.html
http://www9.plala.or.jp/sgwr-t/c/sec10-3.html
http://itpro.nikkeibp.co.jp/article/COL ... 31/252216/
ここで、ちゃんと文字列を理解する事から始めましょう。
Re:Cの文字列の扱いが得意な人へ、質問です
失礼しました。
実は現在、作成している方のパラメータが、
2桁の数字だったので、
そのコードと混乱して、
違う方を乗せてしまったようなのです。
もちろんおっしゃる通りです。
上記のコードに倣うなら、このように書くべきなのかな?
誤解をさせて申し訳ありません。
str2[6][4];
for(int i=0;i<6;i++){
memcpy(&str2,&str[i*4],sizeof(str2[0][0]*3));
str2[2]='\0';
parm=atoi(str);
}
実は現在、作成している方のパラメータが、
2桁の数字だったので、
そのコードと混乱して、
違う方を乗せてしまったようなのです。
もちろんおっしゃる通りです。
上記のコードに倣うなら、このように書くべきなのかな?
誤解をさせて申し訳ありません。
str2[6][4];
for(int i=0;i<6;i++){
memcpy(&str2,&str[i*4],sizeof(str2[0][0]*3));
str2[2]='\0';
parm=atoi(str);
}
Re:Cの文字列の扱いが得意な人へ、質問です
ちなみにスマートに処理するには、こんな方法もあります。
char *token; int i; i=0; token = strtok(str,","); while( token!=NULL ) { parm=atoi(token); i++; token = strtok(NULL,","); }
Re:Cの文字列の扱いが得意な人へ、質問です
zwi さん、コメントありがとうございます。
トークン切り出しはわかりやすくていい思います。
あと、いろいろ考えて一番単純なのは、nonさんの、
sscanf(),ssprintf();
の利用だと思いました。
プログラムは単純であるほど、冴えていると思うので、
こうしてみると、
七面倒なやり方してたなぁと、
思いますね。
いろいろありがとうございました。
トークン切り出しはわかりやすくていい思います。
あと、いろいろ考えて一番単純なのは、nonさんの、
sscanf(),ssprintf();
の利用だと思いました。
プログラムは単純であるほど、冴えていると思うので、
こうしてみると、
七面倒なやり方してたなぁと、
思いますね。
いろいろありがとうございました。
Re:Cの文字列の扱いが得意な人へ、質問です
------------------------------------------------
もちろんおっしゃる通りです。
上記のコードに倣うなら、このように書くべきなのかな?
誤解をさせて申し訳ありません。
str2[6][4];
for(int i=0;i<6;i++){
memcpy(&str2,&str[i*4],sizeof(str2[0][0]*3));
str2[2]='\0';
parm=atoi(str);
}
------------------------------------------------
これも違うと思います。
3文字の後にナル文字を付加させるのであれば、str2[3]='\0';だと思いますし、
atoi関数は文字列を渡さないといけないので、strだと文字列ではないのでエラーになるかと。
atoi関数のところは、parm=atoi(str2);としてみてはどうでしょうか。
あとchar型は1バイトで確定しているので、sizeofは使わなくても、
普通に3文字であれば 3 と書いて問題ないはずです。
もちろんおっしゃる通りです。
上記のコードに倣うなら、このように書くべきなのかな?
誤解をさせて申し訳ありません。
str2[6][4];
for(int i=0;i<6;i++){
memcpy(&str2,&str[i*4],sizeof(str2[0][0]*3));
str2[2]='\0';
parm=atoi(str);
}
------------------------------------------------
これも違うと思います。
3文字の後にナル文字を付加させるのであれば、str2[3]='\0';だと思いますし、
atoi関数は文字列を渡さないといけないので、strだと文字列ではないのでエラーになるかと。
atoi関数のところは、parm=atoi(str2);としてみてはどうでしょうか。
あとchar型は1バイトで確定しているので、sizeofは使わなくても、
普通に3文字であれば 3 と書いて問題ないはずです。