質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

779閲覧

sscanfで変数に格納した値を変数のアドレス先に格納

hikarhikar

総合スコア18

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/03/23 05:03

編集2020/03/23 16:41

ファイルから特定の値を読み取り変数のアドレス先に格納し、その値を違う変数のアドレス先に格納したいのですが、色々試したのですが、考えたような結果になりません。
ネットでも調べてみたのですが、これといった情報がなかったので、質問させていただきました。

c++

1 while (fgets(buf, 25, pFileObj) != NULL) { 2 buf2 = buf; 3 if (*buf2 == 'v') { 4 if (*(++buf2) != 'n' && *(buf2)!='t') { 5 sscanf(buf2, "%s %f %f %f", 6 chr, 7 &vertex[vertexDataSize * 3], 8 &vertex[vertexDataSize * 3 + 1], 9 &vertex[vertexDataSize * 3 + 2]); 10 11 vertexDataSize++; 12 } 13 } 14 else if (*buf2 == 'f') { 15 sscanf(buf2, "%s %d/%d/%d %d/%d/%d %d/%d/%d", 16 chr, 17 &i1, 18 &i2, 19 &i3, 20 21 &i4, 22 &i5, 23 &i6, 24 25 &i7, 26 &i8, 27 &i9); 28 29 iptr1 = &lines[vertexDataSize * 3]; 30 iptr2 = &lines[vertexDataSize * 3 + 1]; 31 iptr3 = &lines[vertexDataSize * 3 + 2]; 32 33 i1 = i1 - 1; 34 i4 = i4 - 1; 35 i7 = i7 - 1; 36 37 38 iptr4 = &i1; 39 iptr5 = &i4; 40 iptr6 = &i7; 41 42 *iptr1 = *iptr4; 43 *iptr2 = *iptr5; 44 *iptr3 = *iptr6; 45 46 47 lineDataSize++; 48 } 49 50 51 }

上のソースコードで、else if (*buf2 == 'f')から始まる部分が分からないのですが、
テキストファイルの一部
上の写真の一行目なら、f 5/1/1 3/2/1 1/3/1 だと思うのですが、
この 5/1/1の5と、3/2/1の3と、1/3/1の1を-1してlinesのアドレス先に格納したい(格納する値4 2 0)のですが、どのようにすればいいのでしょうか?

お手数をおかけしますがどなたかわかる方教えてください。<(_ _)>

追記です。

c++

1void loadOBJ() 2{ 3 FILE* pFileObj, * pFileMtl; 4 5 fopen_s(&pFileMtl, "OBJファイル//NewblockF.txt", "r"); 6 fopen_s(&pFileObj, "OBJファイル//ねずこ.txt", "r"); 7 8 if((pFileObj == nullptr) || (pFileMtl == nullptr)) { 9 printf("file erro\n"); 10 return; 11 } 12 printf("opennd file\n"); 13 14 char chr[25]; 15 int i1, i2, i3,i4,i5,i6,i7,i8,i9; 16 char buf[25]; 17 18 while (fgets(buf, 25, pFileObj) != NULL) { 19 char* buf2 = buf; 20 if (*buf2 == 'v') { 21 if ((*(++buf2) != 'n') && (*buf2 !='t')) { 22 sscanf(buf, "%s %f %f %f", 23 chr, 24 &vertex[vertexDataSize * 3], 25 &vertex[vertexDataSize * 3 + 1], 26 &vertex[vertexDataSize * 3 + 2]); 27 28 vertexDataSize++; 29 } 30 } 31 else if (*buf2 == 'f') { 32 sscanf(buf, "%s %d/%d/%d %d/%d/%d %d/%d/%d", 33 chr, 34 &i1, 35 &i2, 36 &i3, 37 38 &i4, 39 &i5, 40 &i6, 41 42 &i7, 43 &i8, 44 &i9); 45 /**/ 46 int* iptr1 = &lines[lineDataSize * 3]; 47 int* iptr2 = &lines[lineDataSize * 3 + 1]; 48 int* iptr3 = &lines[lineDataSize * 3 + 2]; 49 50 i1 = i1 - 1; 51 i4 = i4 - 1; 52 i7 = i7 - 1; 53 54 55 int* iptr4 = &i1; 56 int* iptr5 = &i4; 57 int* iptr6 = &i7; 58 59 *iptr1 = *iptr4; 60 *iptr2 = *iptr5; 61 *iptr3 = *iptr6; 62 63 64 lineDataSize++; 65 } 66 67 68 }

多くの情報をいただき、このようにしてみたのですが、少ないテキスト文字を読み取る(4角形ブロック)とうまくいくのですが、多くの文字を読み込む(人間モデル)だと失敗してしまうのはなぜでしょうか?

for (int i = 0; i < vertexDataSize; i++) { printf("%f %f %f\n", vertex[i * 3], vertex[i * 3 + 1], vertex[i * 3 + 2]); } for (int i = 0; i < lineDataSize; i++) { printf("%d %d %d\n", lines[i * 3], lines[i * 3 + 1], lines[i * 3 + 2]); }

このソースコードを最後に書いて実行してみると、このように描画され、配列に格納されている値も正常に格納されています。

四角形txtファイル

四角形

ですが、このオブジェを人間モデルに変えて実行すると、

人間モデルtxtファイル

人間モデル
値
まず、読み込まれた値が、一番最初から、-nan 0.000000 0.000000 と訳の分からない値が読み込まれていて、それが終わったと思ったら、テキストの値とは全く異なった値が、読み込まれてしまいました。
そして、

for (int i = 0; i < lineDataSize; i++) { printf("%d %d %d\n", lines[i * 3], lines[i * 3 + 1], lines[i * 3 + 2]); }

これだけにすると、値が描画されず、おそらく、先ほどの右ウィンドウに描画されていた値は、
if (*buf2 == 'v')の部分で読み取っている値だと思うのですが、そのあとのelse if (*buf2 == 'f')が
動作していないようです。

色々考えてはみたのですが、うまくいかなかったので、お手数をおかけしますがどなたかわかる方教えてください<(_ _)>。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2020/03/23 05:47

本題じゃ無いですが、 if (*(++buf2) != 'n' && 't') { は if (*(++buf2) != 'n' && *buf2 != 't') { の誤りでは?
hikarhikar

2020/03/23 12:35

ご返信ありがとうございます。 不備な点申し訳ありませんでした。 教えていただいたとおりにやったところ、修正前までの描画とまた違うオブジェが描画されました。 (人''▽`)ありがとうございました。 ですが、やはり描画したいものとは異なった物が描画されてしまいます。 もしよろしければ、本題の方もご返信よろしくおねがいします。
thkana

2020/03/23 23:40

データと処理との不整合の可能性もある(というよりほとんどそれ)のですから、読み込ませているデータも提示すべきかと。 「データは他でも確認して"正しい"」と考えているのかも知れませんが、問題は「不整合」なので、単独で正しいとか間違っているということではありません。データとプログラムを両方突き合わせて初めて議論になります。
hikarhikar

2020/03/24 00:47

ご返信ありがとうございます。 え~と、一応モデルのテキストファイルのデータを見ていただけるよう、データをドライブに落として、URLを上にはったのですが、このデータ以外の提示ですと何を提示すればよろしいのでしょうか?
thkana

2020/03/24 01:10

すみません、リンクを見落としてました
hikarhikar

2020/03/24 10:00

そうだったのですね、他のことでご指摘をいただいたので、またこちらのサイトを利用する機会があったら、詳細を明確にして書いていきたいと思います。
guest

回答4

0

誤回答のため削除します。元の回答へのコメントに転記。

投稿2020/03/24 10:30

編集2020/03/24 10:35
thkana

総合スコア7639

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2020/03/24 10:33

あ、やっちまった...前の回答へのコメントです。
hikarhikar

2020/03/24 10:39

あっ、了解です! できるだけ、情報を集め、試行錯誤繰り返し、それでもわからなかったら、またこちらのサイトを利用させていただきます。頑張ります!(>_<) 何から何まで(人''▽`)ありがとうございました。
guest

0

ベストアンサー

既に気がつかれていますが、行バッファのサイズが足りない場所がありました。十分なバッファサイズを確保してください。

ねずこ.txtでvertexDataSizeは32580, lineDataSizeは56230まで行くようです。配列はそれぞれその3倍以上がちゃんと確保されていますね?

それと、

読み込まれた値が、一番最初から、-nan 0.000000 0.000000 と訳の分からない値

これについては、vertexDataSizeの値が関数に入るまでに初期化されていないことを疑っています。

C

1#include <stdio.h> 2void* nullptr = (void*)0; 3int vertexDataSize = 0; 4int lineDataSize = 0; 5float vertex[35000*3]={0}; 6int lines[60000*3]={0}; 7#define BUFLEN 64 8void loadOBJ() 9{ 10 FILE *pFileObj, *pFileMtl ; 11 12 // fopen_s(&pFileMtl, "NewblockF.txt", "r"); 13 fopen_s(&pFileObj, "ねずこ.txt", "r"); 14 pFileMtl = pFileObj; 15 16 if ((pFileObj == nullptr) || (pFileMtl == nullptr)) { 17 printf("file error\n"); 18 return; 19 } 20 printf("opennd file\n"); 21 22 char chr[BUFLEN]; 23 int i1, i2, i3,i4,i5,i6,i7,i8,i9; 24 char buf[BUFLEN]; 25 26 printf("%d vertexDataSize=%d lineDataSize=%d\n", __LINE__, vertexDataSize, 27 lineDataSize); ///// ... (A) 28 while (fgets(buf, BUFLEN, pFileObj) != NULL) { 29 char* buf2 = buf; 30 if (*buf2 == 'v') { 31 if ((*(++buf2) != 'n') && (*buf2 != 't')) { 32 sscanf(buf, "%s %f %f %f", chr, &vertex[vertexDataSize * 3], 33 &vertex[vertexDataSize * 3 + 1], 34 &vertex[vertexDataSize * 3 + 2]); 35 36 printf("%d : %d %s %f %f %f\n", __LINE__, vertexDataSize, chr, vertex[vertexDataSize * 3], 37 vertex[vertexDataSize * 3+1], vertex[vertexDataSize * 3+2] );///// 38 vertexDataSize++; 39 } 40 } else if (*buf2 == 'f') { 41 printf("%d : %s\n",__LINE__,buf);///// 42 sscanf(buf, "%s %d/%d/%d %d/%d/%d %d/%d/%d", chr, &i1, &i2, &i3, 43 44 &i4, &i5, &i6, 45 46 &i7, &i8, &i9); 47 /**/ 48 //無駄な操作はやめましょう 49 lines[lineDataSize * 3]=i1-1; 50 lines[lineDataSize * 3 + 1]=i4-1; 51 lines[lineDataSize * 3 + 2]=i7-1; 52 printf("%d : %d %d %d %d %d %d %d %d %d\n", __LINE__, i1, i2, i3, i4, 53 i5, i6, i7, i8, i9);///// 54 printf("%d : %d %s %d %d %d\n", __LINE__, lineDataSize, chr, 55 lines[lineDataSize * 3], lines[lineDataSize * 3 + 1], 56 lines[lineDataSize * 3 + 2] ); ///// 57 lineDataSize++; 58 } 59 } 60 printf("%d vertexDataSize=%d lineDataSize=%d\n", __LINE__, vertexDataSize, 61 lineDataSize); ///// 62 for (int i = 0; i < vertexDataSize; i++) { ///// 63 printf("%d %d: %f %f %f\n", __LINE__, i, vertex[i * 3], vertex[i * 3 + 1], 64 vertex[i * 3 + 2]); ///// 65 } ///// 66 for (int i = 0; i < lineDataSize; i++) { ///// 67 printf("%d %d: %d %d %d\n", __LINE__, i, lines[i * 3], lines[i * 3 + 1], 68 lines[i * 3 + 2]); ///// 69 } ///// 70} 71 72int main(void) { 73 loadOBJ(); 74 return 0; 75}

として、テストデータを喰わせてみましたが、質問の症状は再現しませんでした。/////のついているのがデバッグ用に追加したprintfです。__LINE__はソース中の行数を得るマクロです。
あなたのプログラムにはめ込んで、各所の値を比較しながら追ってみて下さい。予想通りなら、(A)のところで既に異常な値が観察できるのでは。

結果だけみておかしいと言っていないで、途中の経過で適宜状態をチェックしましょう。

投稿2020/03/24 05:09

編集2020/03/24 05:11
thkana

総合スコア7639

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hikarhikar

2020/03/24 10:36

ご返信ありがとうございます。<(_ _)> thkanaさんに教えていただいたことを参考にさせていただき、やってみたところ、モデルを覆うようにして、ブロックが描画されてしまいましたが、それ以外はうまく描画されました! 読み込むデータを格納するためのバッファの存在を軽視していました。 (*´▽`*)ありがとうございます。 上にも書きましたが、モデルを覆うような形でブロックが描画されてしまい、今現在試行錯誤を繰り返しているのですが、原因が何かも分からないので、新しく質問させていただくかもしれないので、もしよろしければそちらの方もよろしくおねがいします。 いろいろとありがとうございました。(*´▽`*)
thkana

2020/03/24 10:36

サイズが小さいとうまくいくというなら、linesの配列の大きさが十分でない、という可能性もあるかな。 とにかく、情報を集めましょう。
thkana

2020/03/24 10:40

あ、バタバタしてごめんなさい。 試行錯誤という言葉、あまり「めちゃくちゃやってあたりを狙う」という意味にしないで下さいね。適切な試行をして、錯誤からちゃんとデータをとって、次回にちゃんと役立てましょう。 決して「うまくいった/いかなかった」で1/0判定をしないように。
hikarhikar

2020/03/24 14:02

はい。丁寧に問題を一つ一つ潰していきたいと思います。 何から何まで(人''▽`)ありがとうございました。
guest

0

C

1int* target = &lines[lineDataSize++ * 3]; 2int n = sscanf(buf2, "%*s %d/%*d/%*d %d/%*d/%*d %d/%*d/%*d", target, target+1, target+2); 3for(; n-- > 0;) target[n]--;

こんな感じに簡潔に書きたいってこと?
それとも、linesなのにlineDataSize3じゃなくてvertexDataSize3を使用していたことを指摘したほうがいい系?

投稿2020/03/23 12:58

編集2020/03/23 13:23
majiponi

総合スコア1720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hikarhikar

2020/03/23 16:45

ご返信ありがとうございます。ご指摘ありがとうございます。 教えていただいた箇所を直したら、四角形だけ描画できました。 モデルを変えるとうまく動作しないので 上に追記で編集させていただいたので、もしよかったら、教えてください<(_ _)>
majiponi

2020/03/23 22:34 編集

うーん、もしかして、vertexの型って、double? もしそうなら、sscanfの書式設定が間違ってる。%lfが正しい。 あと、各行の長さは、23文字以内? (改行文字とヌル文字のせいで入力できるのが2文字減る)
hikarhikar

2020/03/24 01:03

ご返答ありがとうございます。 一応上にテキストファイルを見ていただけるようにドライブにデータを落としてURLを貼らしていただいたのですが、データに f 22069/6125/5732 22109/6165/5772 22100/6156/5763 このような一行があるのですが、これは数字一文字がmajiponiさんのおっしゃるsscanfで読み込める一文字だとしたら、おもいっきり文字数をオーバーしていました... ちなみに、vertexは float型です。 #define ARRAY_MAX 100000 float vertex[ARRAY_MAX];
guest

0

こういう話ですか?

C++

1else if (*buf2 == 'f') { 2 //このsscanfで読み込めているのだとして… 3 sscanf(buf2, "%s %d/%d/%d %d/%d/%d %d/%d/%d", 4 chr, 5 &i1, 6 &i2, 7 &i3, 8 9 &i4, 10 &i5, 11 &i6, 12 13 &i7, 14 &i8, 15 &i9); 16 //このように格納したいという話? 17 lines[vertexDataSize * 3] = i1 - 1; 18 lines[vertexDataSize * 3 + 1] = i4 - 1; 19 lines[vertexDataSize * 3 + 2] = i7 - 1; 20 21 lineDataSize++; 22}

投稿2020/03/23 05:27

fana

総合スコア11658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hikarhikar

2020/03/23 12:28

ご返信ありがとうございます。 不備な点申し訳ありませんでした。 fanaさんのおっしゃるとおりです。 その点をふまえてどのようにすればいいのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問