C ++ Строковый токенизация из 3D .obj файлов - PullRequest
2 голосов
/ 12 мая 2010

Я довольно новичок в C ++ и искал хороший способ вытащить данные из этой строки.

Пример строки, которая может понадобиться для токенизации:

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

У меня есть метод токенизации, который разбивает строки на вектор, разделенные строкой, что может быть полезно

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

Единственный способ, которым я могу думать, это сделать токен с "" в качестве разделителя, удалить первый элемент из результирующего вектора, а затем токенизировать каждую часть отдельно. Есть ли хороший способ сделать все это в одном?

Ответы [ 5 ]

3 голосов
/ 12 мая 2010
#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;
}
3 голосов
/ 12 мая 2010

Я вижу, что вопрос помечен как C ++, но самый простой способ сделать это с помощью scanf

int indices[3][3];
sscanf(buffer, "f %d/%d/%d %d/%d/%d %d/%d/%d", &indices[0][0], &indices[0][1],...);
2 голосов
/ 12 мая 2010

Вы должны взглянуть на 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;
}
1 голос
/ 12 мая 2010

Судя по выборке, вы можете использовать два разделителя '' и '/' и получите все свои числа.

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

0 голосов
/ 21 мая 2010

Вы можете легко удалить первую часть до первого пробела или сразу после f (вы можете получить остаток после первого пробела с помощью

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