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

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

ただいまの
回答率

88.81%

ファイル操作について!

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 507

miiichat

score 70

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

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

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
がうまくいきません...

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

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

# Blender v2.79 (sub 0) OBJ File: ''
# www.blender.org
mtllib tesetobj.mtl
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn 0.0000 0.0000 -1.0000
usemtl Material
s off
f 1//1 2//1 3//1
f 5//2 8//2 7//2
f 1//3 5//3 6//3
f 2//4 6//4 7//4
f 3//5 7//5 8//5
f 5//6 1//6 4//6
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);
            }
#include <stdio.h>
#include <vector>
#include<iostream>
#include<Windows.h>
using std::vector;

struct Vector3f {
      float x;
      float y;
      float z;
}vec3d;

struct Vector4l
{
      int x;
      int y;
      int z;
} vec4l;

int main()
{
      FILE *fp;
      const char *file = "data.txt";
      char key[255] = { 0 };
      vector <Vector3f> Vertex;
      Vector4l Face[3];


      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));
            fscanf_s(fp, "%s", key, sizeof(key));

            if (strcmp(key, "v") == 0)
            {
                  fscanf_s(fp, "%f%f%f", &vec3d.x, &vec3d.y, &vec3d.z);
                  Vertex.push_back(vec3d);
            }

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

      fclose(fp);

      getchar();
}
1,-858993460,-858993460
-858993460,-858993460,-858993460
-858993460,-858993460,-858993460
5,-858993460,-858993460
-858993460,-858993460,-858993460
-858993460,-858993460,-858993460
1,-858993460,-858993460
-858993460,-858993460,-858993460
-858993460,-858993460,-858993460
2,-858993460,-858993460
-858993460,-858993460,-858993460
-858993460,-858993460,-858993460
3,-858993460,-858993460
-858993460,-858993460,-858993460
-858993460,-858993460,-858993460
5,-858993460,-858993460
-858993460,-858993460,-858993460
-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 が入る
・同じ行が何度も表示

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • episteme

    2019/04/12 22:41

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

    キャンセル

  • cateye

    2019/04/12 22:42

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

    キャンセル

回答 3

checkベストアンサー

+2

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

#include <iostream>
#include <string>

std::string split(std::string& str) {
  std::string::size_type pos = str.find_first_of("/ ");
  std::string head = str.substr(0,pos);
  str.erase(0,pos+1);
  return head;
}

// おためし

int main() {
  std::string input = "f 1/2/3 1/2/ 1//3 /2/3 1// /2/ //3 ///";
  while ( !input.empty() ) {
    std::string token = split(input);
    std::cout << '[' << token << "]  ";
  }
  std::cout << std::endl;
}

/* 実行結果
[f]  [1]  [2]  [3]  [1]  [2]  []  [1]  []  [3]  []  [2]  [3]  [1]  []  []  []  [
2]  []  []  []  [3]  []  []  []
*/

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/16 02:33

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

    キャンセル

  • 2019/04/16 03:09

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

    キャンセル

  • 2019/04/16 13:45

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

    キャンセル

+1

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

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/16 02:35

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

    キャンセル

0

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.81%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る