Cの文字列の扱いが得意な人へ、質問です

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
usami

Cの文字列の扱いが得意な人へ、質問です

#1

投稿記事 by usami » 16年前

たびたびお世話になっております。

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:
前回の質問は、メモリについてどんなものなのか、
まったく認識しておらず(今でも漠然)、
トンチンカンなコメントをしたように思います。
ご迷惑をおかけしました。

ランド

Re:Cの文字列の扱いが得意な人へ、質問です

#2

投稿記事 by ランド » 16年前

文章の終わりを示す、NULL('\0')が含まれていないからではないでしょうか。
char型の配列に1文字分の余裕を持たせる必要があると思います。

# memcpyを使ったことがないほど、文字列の扱いが不十分なので曖昧な回答ですが・・・

# 追記
検索してみたところ、memcpyは空文字('\0')を付加せず、
また、途中に空文字が含まれていてもコピーを続ける関数だそうです。

non

Re:Cの文字列の扱いが得意な人へ、質問です

#3

投稿記事 by non » 16年前

プログラムの意味がわかりません。

>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]);
でよいのでは。

usami

Re:Cの文字列の扱いが得意な人へ、質問です

#4

投稿記事 by usami » 16年前

その通りでした。


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);
}

……一瞬で解決(!_!)

すごく簡単な質問で、逆に申しわけなかったです。
ランドさんありがとうございました。

usami

Re:Cの文字列の扱いが得意な人へ、質問です

#5

投稿記事 by usami » 16年前

non さんのご指摘とおりです。

コードは、即興で書かせてもらったものなので、
誤植が多々あったようです。
修正しておきましょう。


今回、フォーマットについては、
未だ制作途中(仮データ)なので、
あまり考えていないのですが、
フォーマットを決定した場合は、
参考にさせていただきたいと思います。

non さん、
ご意見ありがとうございます。

zwi

Re:Cの文字列の扱いが得意な人へ、質問です

#6

投稿記事 by zwi » 16年前

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/
ここで、ちゃんと文字列を理解する事から始めましょう。

usami

Re:Cの文字列の扱いが得意な人へ、質問です

#7

投稿記事 by usami » 16年前

失礼しました。

実は現在、作成している方のパラメータが、
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);
}

zwi

Re:Cの文字列の扱いが得意な人へ、質問です

#8

投稿記事 by zwi » 16年前

ちなみにスマートに処理するには、こんな方法もあります。
char *token;
int i;
i=0;
token = strtok(str,",");
while( token!=NULL ) {
 parm=atoi(token);
 i++;
 token = strtok(NULL,",");
}

usami

Re:Cの文字列の扱いが得意な人へ、質問です

#9

投稿記事 by usami » 16年前

zwi さん、コメントありがとうございます。

トークン切り出しはわかりやすくていい思います。


あと、いろいろ考えて一番単純なのは、nonさんの、

sscanf(),ssprintf();

の利用だと思いました。

プログラムは単純であるほど、冴えていると思うので、
こうしてみると、
七面倒なやり方してたなぁと、
思いますね。

いろいろありがとうございました。

conio

Re:Cの文字列の扱いが得意な人へ、質問です

#10

投稿記事 by conio » 16年前

------------------------------------------------
もちろんおっしゃる通りです。
上記のコードに倣うなら、このように書くべきなのかな?
誤解をさせて申し訳ありません。

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 と書いて問題ないはずです。

閉鎖

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