быстрый способ разбора конфигурации - PullRequest
1 голос
/ 06 апреля 2009

Скажем, у вас есть

char *=  "name:454";

Какой самый лучший способ разобрать имя и номер, таким образом

std: идентификатор строки будет равен "name";

double d будет равно 454;

STL, пожалуйста, без повышения.

Ответы [ 7 ]

4 голосов
/ 06 апреля 2009

Вы хотите посмотреть на функцию strtok, используя ':' в качестве токена. Вот пример:

#include <stdio.h>
#include <string.h>

int main ()
{
    char str[] = "name:454";
    char* c = strtok(str, ":");

    while (c != NULL)
    {
        printf("%s\n", c);
        c = strtok(NULL, ":");
    }

    return 0;
}
2 голосов
/ 06 апреля 2009

Не то решение, которое вы просили; тем не мение, рано или поздно вам понадобится разобрать более сложные выражения (подсказка - раньше, чем вы ожидаете), после чего вам понадобятся регулярные выражения - так почему бы не начать сейчас Ваше выражение захватывает:

^(\w+):(\d+)$

Я не фанатик наддува, но их библиотека регулярных выражений хороша.

2 голосов
/ 06 апреля 2009
1 голос
/ 06 апреля 2009
#include <iostream>
#include <sstream>
#include <string>

int main() {
  /* output storage */
  std::string id; 
  double d;
  /* convert input to a STL string */
  std::string s("name:454");
  size_t off = std::string::npos;
  /* smart replace: parsing is easier with a space */    
  if ((off = s.find(':')) != std::string::npos) { // error check: all or none 
    s = s.replace(off, 1, 1, ' ');
    std::istringstream iss(s);
    iss >> id >> d;
    std::cout << "id = " << id << " ; d = " << d << '\n';
  }
  return 0;
}

Хотя, я бы просто написал свой собственный парсер или использовал бы скорость сканера C.

0 голосов
/ 07 апреля 2009
template < typename T >
T valueFromString( const std::string &src )
{
    std::stringstream s( src );
    T result = T();
    s >> result;
    return result;
}

std::string wordByNumber( const std::string &src, size_t n, const std::string &delims )
{
    std::string::size_type word_begin = 0;
    for ( size_t i = 0; i < n; ++i )
    {
        word_begin = src.find_first_of( delims, word_begin );
    }
    std::string::size_type word_end = src.find_first_of( delims, word_begin );

    word_begin = std::string::npos == word_begin || word_begin == src.length() ? 0 : word_begin + 1;
    word_end = std::string::npos == word_end ? src.length() : word_end;
    return src.substr( word_begin, word_end - word_begin);
}


char *a = "asdfsd:5.2";
std::cout << wordByNumber( a, 0, ":" ) << ", " << valueFromString< double > ( wordByNumber( a, 1, ":" ) );

PS: в предыдущей ревизии я публиковал wordByNumber - пропускал соседние разделители (например, :: :), в текущей ревизии они рассматриваются как пустое слово.

0 голосов
/ 07 апреля 2009

Другая возможность заключается в использовании уже написанного парсера для простого формата, такого как INI.

Вот один из них: http://code.jellycan.com/SimpleIni/

Я посмотрел код для SimpleIni, и он не очень C ++ и STL'ish, но вас это действительно волнует?

0 голосов
/ 07 апреля 2009

Я бы написал свой. Основная идея - читать по одному символу за раз из потока. Если это не двоеточие, добавьте его в строку идентификатора. Если это так, пропустите его, а затем используйте оператор istream >>, чтобы загрузить целое число, двойное число с плавающей запятой или все, что нужно. Тогда вы, вероятно, поместите результат в std :: map.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...