2010-05-12 4 views
2

저는 C++을 처음 접했고이 행에서 데이터를 추출하는 좋은 방법을 찾고있었습니다.C++ 3D .obj 파일의 토큰 화

내가 tokenise해야 할 수도 있습니다 샘플 라인은

f 11/65/11 16/70/16 17/69/17

내가 도움이 될 수있는 문자열로 구분와 같은 벡터로 문자열을 분할하는 tokenisation 방법이있다

static void Tokenise(const string& str, vector<string>& tokens, const string& delimiters = " ")

내가 할 수있는 유일한 방법은 ""를 구분 기호로 사용하여 토큰 화하고 결과 벡터에서 첫 번째 항목을 제거한 다음 각 부분을 토큰 화하는 것입니다. 이 모든 작업을 하나의 방법으로 수행 할 수 있습니까?

답변

3

나는 질문 ++ C로 태그되어 볼 수 있지만 scanf

int indices[3][3]; 
sscanf(buffer, "f %d/%d/%d %d/%d/%d %d/%d/%d", &indices[0][0], &indices[0][1],...); 
+0

그 일을하는 것도 좋은 방법입니다. 나는 앞으로 C 함수를 명심하고, 이것을 구현할지도 모른다. 쉽게 가장 깔끔한 솔루션입니다. – Ben

+0

.obj를 파싱하는 데있어 최소한 읽기 쉽고 쓰기 쉬운 솔루션 인 것 같습니다. 약 50 줄의 코드로 끝나고 전체 파일 형식을 구문 분석합니다. tokenizer-lexer-parser 라우트를 사용하지 마십시오. 그것은 이것처럼 단순한 무언가를 뒤얽힌 것입니다. –

1

샘플 라인을 보면 '와'/ '두 구분 기호를 사용할 수 있으며 모든 숫자를 얻을 수 있습니다.

static void Tokenise(const string& str, vector<string>& tokens, const string& delimiters = " /")

+0

감사합니다. 그러나 제 토큰 기능은 그렇게 작동하지 않습니다. 앞으로 더 명확해질 것입니다. – Ben

2

당신은 Boost.Tokenizer를 살펴보고 특히이해야이 작업을 수행 할 수있는 절대적으로 가장 쉬운 방법은 다음과 같습니다

// char_sep_example_1.cpp 
#include <iostream> 
#include <boost/tokenizer.hpp> 
#include <string> 

int main() 
{ 
    std::string str = ";;Hello|world||-foo--bar;yow;baz|"; 
    typedef boost::tokenizer<boost::char_separator<char> > 
    tokenizer; 
    boost::char_separator<char> sep("-;|"); 
    tokenizer tokens(str, sep); 
    for (tokenizer::iterator tok_iter = tokens.begin(); 
     tok_iter != tokens.end(); ++tok_iter) 
    std::cout << "<" << *tok_iter << "> "; 
    std::cout << "\n"; 
    return EXIT_SUCCESS; 
} 
+0

감사합니다. Boost를이 과제의 일부로 사용할 수 있다면 교사에게 문의 할 것입니다. – Ben

+0

왜 downvote? 맞습니다 ... –

3
#include <iostream> 
#include <sstream> 
#include <string> 
#include <vector> 

class parse_error : public std::exception {}; 

template< typename Target > 
inline Target convert_to(const std::string& value) 
{ 
    std::istringstream iss(value); 
    Target target; 
    iss >> target >> std::ws; 
    if(!iss || !iss.eof()) throw parse_error(); 
    return target; 
} 

template< typename T > 
inline T read_delimited_value(std::istream& is, char delim) 
{ 
    std::string value; 
    std::getline(is,value,delim); 
    if(!is) throw parse_error(); 
    return convert_to<T>(value); 
} 

template< typename It > 
inline void output(std::ostream& os, It begin, It end) 
{ 
    while(begin!=end) 
    os << *begin++ << ' '; 
} 

int main() 
{ 
    std::vector<int> values; 
    const std::string line = "f 11/65/11 16/70/16 17/69/17"; 

    std::istringstream iss(line); 
    std::string value; 

    std::getline(iss,value,' '); 
    if(value!="f" || !iss) throw parse_error(); 

    while(iss.good()) { 
    values.push_back(read_delimited_value<int>(iss,'/')); 
    values.push_back(read_delimited_value<int>(iss,'/')); 
    values.push_back(read_delimited_value<int>(iss,' ')); 
    } 

    if(!iss.eof()) throw parse_error(); 

    output(std::cout, values.begin(), values.end()); 
    std::cout << '\n'; 

    return 0; 
} 
+0

누구든지이 투표를 잘못했다면 나에게 그게 잘못 됐는지 말해 주시겠습니까? – sbi

+0

템플릿으로 된 중재자를 사용하여 Upvoted 중 하나! –

+0

나는 이것을 잘 따라 가기에 약간 신선한 프로그래밍이다. 그러나 나는 이것을 알아 내기 위해 일반적인 프로그래밍과 템플리트에 대해 읽을 것이다. 나는 이것이 "올바른"방법이라고 생각하지만, 오랫동안 그런 것처럼 보입니다. 감사합니다 :) – Ben

0

eas 첫 번째 빈 또는 직후 F까지 첫 번째 부분을 ILY (당신이 그럼 당신은 첫 번째 빈 공간에 다음에 '/'당신의 토큰 화 기능을 사용할 수 있습니다

istringstream iss(line); 
std::getline(iss, restStr ,' ') 

으로 첫 번째 빈 후 나머지를 얻을 수 있습니다, 또는 하나의 루프에서 std :: getline 및 istringstreams 집합을 사용하면됩니다.

int main() 
{ 
    std::string s = "f 1/2/3 4/4/2"; 

    std::istringstream issLine(s); 

    std::string result; 

    // remove the first "f" 
    std::getline(issLine, result, ' '); 

    // parse blanks 
    while(std::getline(issLine, result, ' ')) 
    { 
     std::istringstream issToken(result); 
     std::string token; 

     //parse content 
     while(std::getline(issToken, token, '/')) 
     { 
      std::cout << token << ','; 
      // add your data in whatever you want 
     } 
     std::cout << std::endl; 
    } 
}