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

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

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

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

Q&A

解決済

3回答

156閲覧

ファイル操作について!

miiichat

総合スコア72

C++

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

0グッド

0クリップ

投稿2019/04/12 13:37

編集2019/04/16 04:46

いつもありがとうございます!

文字列操作が難しくて...

f d/d/d d/d/d d/d/d
f d//d d//d d//d
f d// d// d//
(頂点/テクスチャ/法線)

などいろんなパターンのデータに対応して
ファイルから取得したいです。

fscanf_s を使ってみましたが、
f d/d/d d/d/d d/d/d
の場合は大丈夫ですが、
f d//d d//d d//d
がうまくいきません...

ほかのやり方があれば教えてください!

回答よろしくお願いいたします。

objfile

1# Blender v2.79 (sub 0) OBJ File: '' 2# www.blender.org 3mtllib tesetobj.mtl 4o Cube 5v 1.000000 -1.000000 -1.000000 6v 1.000000 -1.000000 1.000000 7v -1.000000 -1.000000 1.000000 8v -1.000000 -1.000000 -1.000000 9v 1.000000 1.000000 -0.999999 10v 0.999999 1.000000 1.000001 11v -1.000000 1.000000 1.000000 12v -1.000000 1.000000 -1.000000 13vn 0.0000 -1.0000 0.0000 14vn 0.0000 1.0000 0.0000 15vn 1.0000 0.0000 0.0000 16vn -0.0000 -0.0000 1.0000 17vn -1.0000 -0.0000 -0.0000 18vn 0.0000 0.0000 -1.0000 19usemtl Material 20s off 21f 1//1 2//1 3//1 22f 5//2 8//2 7//2 23f 1//3 5//3 6//3 24f 2//4 6//4 7//4 25f 3//5 7//5 8//5 26f 5//6 1//6 4//6 27
if (strcmp(key, "f") == 0) {           for (int i = 0; i < 3; i++) { Face[i].x = -1; Face[i].y = -1; Face[i].z = -1; } fscanf_s(fp, "%d/%d/%d %d/%d/%d %d/%d/%d", &Face[0].x, &Face[0].y,&Face[0].z, &Face[1].x , &Face[1].y , &Face[1].z, &Face[2].x, &Face[2].y, &Face[2].z); printf("%d,%d,%d\n", Face[0].x, Face[0].y, Face[0].z); printf("%d,%d,%d\n", Face[1].x, Face[1].y, Face[1].z); printf("%d,%d,%d\n", Face[2].x, Face[2].y, Face[2].z); }

main

1#include <stdio.h> 2#include <vector> 3#include<iostream> 4#include<Windows.h> 5using std::vector; 6 7struct Vector3f { 8 float x; 9 float y; 10 float z; 11}vec3d; 12 13struct Vector4l 14{ 15 int x; 16 int y; 17 int z; 18} vec4l; 19 20int main() 21{ 22 FILE *fp; 23 const char *file = "data.txt"; 24 char key[255] = { 0 }; 25 vector <Vector3f> Vertex; 26 Vector4l Face[3]; 27 28 29 fopen_s(&fp, file, "r"); 30 if (fp == NULL) 31 { 32 printf("%sのオープンに失敗しました。\n", file); 33 printf("Enterキーで終了。\n"); 34 getchar(); 35 return 0; 36 } 37 38 39 fseek(fp, SEEK_SET, 0); 40 41 while (!feof(fp)) 42 { 43 ZeroMemory(key, sizeof(key)); 44 fscanf_s(fp, "%s", key, sizeof(key)); 45 46 if (strcmp(key, "v") == 0) 47 { 48 fscanf_s(fp, "%f%f%f", &vec3d.x, &vec3d.y, &vec3d.z); 49 Vertex.push_back(vec3d); 50 } 51 52 if (strcmp(key, "f") == 0) 53 { 54          for (int i = 0; i < 3; i++) 55 { 56 Face[i].x = -1; 57 Face[i].y = -1; 58 Face[i].z = -1; 59 } 60 fscanf_s(fp, "%d/%d/%d %d/%d/%d %d/%d/%d", &Face[0].x, &Face[0].y,&Face[0].z, 61 &Face[1].x , &Face[1].y , &Face[1].z, 62 &Face[2].x, &Face[2].y, &Face[2].z); 63 printf("%d,%d,%d\n", Face[0].x, Face[0].y, Face[0].z); 64 printf("%d,%d,%d\n", Face[1].x, Face[1].y, Face[1].z); 65 printf("%d,%d,%d\n", Face[2].x, Face[2].y, Face[2].z); 66 } 67 } 68 69 fclose(fp); 70 71 getchar(); 72}

result

11,-858993460,-858993460 2-858993460,-858993460,-858993460 3-858993460,-858993460,-858993460 45,-858993460,-858993460 5-858993460,-858993460,-858993460 6-858993460,-858993460,-858993460 71,-858993460,-858993460 8-858993460,-858993460,-858993460 9-858993460,-858993460,-858993460 102,-858993460,-858993460 11-858993460,-858993460,-858993460 12-858993460,-858993460,-858993460 133,-858993460,-858993460 14-858993460,-858993460,-858993460 15-858993460,-858993460,-858993460 165,-858993460,-858993460 17-858993460,-858993460,-858993460 18-858993460,-858993460,-858993460

###追記

一行でやるとうまくいきますが、、

#include <stdio.h> #include <stdlib.h> #include <vector> #include<iostream> #include<Windows.h> #include <string.h> #include <string> using std::vector; using std::string; int main() { vector <int> Face; string str = "f 1//1 2//1 3//1"; str.erase(0, 2); while (!str.empty()) { int i = str.find_first_of("/ "); string head = str.substr(0, i); if (head == "") { Face.push_back(-1); } else { int num = atoi(head.c_str()); Face.push_back(num); } if (i == -1) { str.erase(0, 1); } else { str.erase(0, i + 1); } } for (int i = 0;i < Face.size();i++) { std::cout << Face[i] << std::endl; } getchar(); }

#####result

1 -1 1 2 -1 1 3 -1 1
#include <stdio.h> #include <stdlib.h> #include <vector> #include<iostream> #include<Windows.h> #include <string.h> #include <string> using std::vector; using std::string; int main() { FILE *fp; const char *file = "data.txt"; char key[255] = { 0 }; vector <int> Face; fopen_s(&fp, file, "r"); if (fp == NULL) { printf("%sのオープンに失敗しました。\n", file); printf("Enterキーで終了。\n"); getchar(); return 0; } fseek(fp, SEEK_SET, 0); while (!feof(fp)) { ZeroMemory(key, sizeof(key)); fgets(key, 255, fp); if (strncmp(key, "f", 1) == 0) { string str= key; str.erase(0, 2); while (!str.empty()) { int i = str.find_first_of("/ "); string head = str.substr(0, i); if (head == "") { Face.push_back(-1); } else { int num = atoi(head.c_str()); Face.push_back(num); } if (i == -1) { str.erase(0, 1); } else { str.erase(0, i + 1); } } } }          for (int i = 0;i < Face.size();i++) { std::cout << Face[i] << std::endl; } fclose(fp); getchar(); }

#####result

1 -1 1 2 -1 1 3 -1 1 0 ←これ 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 3 -1 5 7 -1 5 8 -1 5 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 3 -1 5 7 -1 5 8 -1 5 0 5 -1 6 1 -1 6 4 -1 6 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 3 -1 5 7 -1 5 8 -1 5 0 5 -1 6 1 -1 6 4 -1 6 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 3 -1 5 7 -1 5 8 -1 5 0 5 -1 6 1 -1 6 4 -1 6 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 3 -1 5 7 -1 5 8 -1 5 0 5 -1 6 1 -1 6 4 -1 6 01 -1 1 2 -1 1 3 -1 1 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 3 -1 5 7 -1 5 8 -1 5 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 3 -1 5 7 -1 5 8 -1 5 0 5 -1 6 1 -1 6 4 -1 6 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 3 -1 5 7 -1 5 8 -1 5 0 5 -1 6 1 -1 6 4 -1 6 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 3 -1 5 7 -1 5 8 -1 5 0 5 -1 6 1 -1 6 4 -1 6 0 1 -1 1 2 -1 1 3 -1 1 0 5 -1 2 8 -1 2 7 -1 2 0 1 -1 3 5 -1 3 6 -1 3 0 2 -1 4 6 -1 4 7 -1 4 0 3 -1 5 7 -1 5 8 -1 5 0 5 -1 6 1 -1 6 4 -1 6 0

###問題
・一行の後に 0 が入る
・同じ行が何度も表示

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

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

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

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

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

episteme

2019/04/12 13:41

何をどうしたいのか/そのためにどんなコードを書いたか/期待する結果と実際の結果 をちゃんと説明せよ。やりなおし。
cateye

2019/04/12 13:42

えっと、何がしたいんでしょう?
guest

回答3

0

ベストアンサー

要は文字列を '/' または ' ' を区切りとして切り出せばいいのかい?

C++

1#include <iostream> 2#include <string> 3 4std::string split(std::string& str) { 5 std::string::size_type pos = str.find_first_of("/ "); 6 std::string head = str.substr(0,pos); 7 str.erase(0,pos+1); 8 return head; 9} 10 11// おためし 12 13int main() { 14 std::string input = "f 1/2/3 1/2/ 1//3 /2/3 1// /2/ //3 ///"; 15 while ( !input.empty() ) { 16 std::string token = split(input); 17 std::cout << '[' << token << "] "; 18 } 19 std::cout << std::endl; 20} 21 22/* 実行結果 23[f] [1] [2] [3] [1] [2] [] [1] [] [3] [] [2] [3] [1] [] [] [] [ 242] [] [] [] [3] [] [] [] 25*/

後は好きに加工しておくれ。

投稿2019/04/12 14:20

episteme

総合スコア16614

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

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

miiichat

2019/04/15 17:33

回答ありがとうございます! 回答を参考に書いてみました。 一行だとうまくいきますが、objfileだとうまくいきません、、
episteme

2019/04/15 18:09

getlineで一行ずつ読み取ってくるだけだと思うがねぇ,,,
miiichat

2019/04/16 04:45

解決しました、、ミスでした。 ありがとうございました!!
guest

0

ほとんど、C のコードみたいなので、、

fgets()で一行、読み込む。
区切りの空白は、一文字みたいなので、(とりあえず、決め打ち)
空白と、行末の改行を null(0x0) に置き換え、

で、最初の "f" で該当行の判定。
次のnull(0x0)の次から、null(0x0)までを一区切りと見なして、切り出し(コピー、、しなくてもいいけど)、
'/'文字を null(0x0)に置き換え、null(0x0)に出会う度、数字の変換を行う。
(atoi() とかで) この時、"//" は、nullの連続になる筈なので、それは、 0とする。 -- これを3回繰り返す。

-- で、一行分の処理とする。

こんなところでしょうか。
他にも方法はありそうですが、古き良き、Cのコードでの一つの方法です。
(具体的なコードは、今日はパスで)

投稿2019/04/12 14:25

pepperleaf

総合スコア6383

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

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

miiichat

2019/04/15 17:35

回答ありがとうございます! /で区切ってやる方法でやってみましたが、うまくいきません、、
guest

0

fscanf(fscanf_s)は処理が複雑なので、慣れるまでは望ましくないです(まあ慣れたら別方法(fgetsとsscanfの組み合わせ)使いたくなりますけどね)。

まず、ファイル読み込みはまるごと一行(またはファイル全部)にすると楽。**ファイルを文字列解析しながら読み取るよりも、メモリにまるごと読み込んでから文字列解析したほうがずっと楽ですし、柔軟に対応できます。**バグの影響も小さくなります。

そもそもfscanfで文字列解析するならば、fscanf系の仕様を全部知っておくことが必要です。しかも「fgetsとsscanfの組み合わせ」という安全な定石でほぼ代用できます。

ただ、本質問で目的としていることがよくわからないので、そこから先は回答できません。

投稿2019/04/12 16:35

HogeAnimalLover

総合スコア4830

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問