Конкретный формат строки с числом и символом вместе представляет определенный элемент - PullRequest
3 голосов
/ 13 марта 2010

У меня есть строка, которая выглядит так их соответствующая буква переменной? (у меня есть целочисленные переменные d, r, e, g, s и c). Первая буква в строке представляет функцию, "3e, 6s, 1d, 3g, 22r, 7c" и "3g, 5r, 9c" - два отдельных контейнера И последнее десятичное значение представляет число, которое нужно разбить на эти переменные числа.

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

Ответы [ 3 ]

3 голосов
/ 13 марта 2010

Как насчет использования регулярного выражения для разбора различных частей на переменные. После этого вы можете преобразовать проанализированные переменные в целевые типы.

Регулярное выражение, использующее группировку, может выглядеть примерно так: уродливый монстр:

^([a-zA-Z]) (-?\d{1,2}) ?e,(-?\d{1,2}) ?s,(-?\d{1,2}) ?d,(-?\d{1,2}) ?g,(-?\d{1,2}) ?r,(-?\d{1,2}) ?c (-?\d{1,2}) ?g,(-?\d{1,2}) ?r,(-?\d{1,2}) ?c ([0-9.]{1,4})

Возможно, еще не идеально, но это начало.

Вот пример кода для начала работы:

#include <regex>

using std::string;
using std::tr1::cmatch;
using std::tr1::regex;

const regex pattern("\\.([^\\.]+)$");
cmatch result;

string dateiname("test.abc");
string erweiterung;

if(regex_search(dateiname.c_str(), result, pattern) == true)
    erweiterung = result[1];
2 голосов
/ 13 марта 2010

Простой конечный автомат кажется подходящим способом. Я не уверен, что приведенные вами правила являются достаточно полными. В частности, я не понимаю функцию пробелов или то, что вы подразумеваете под «отдельными контейнерами». Вы должны добавить больше кода для проверки на недопустимые состояния, но это должно помочь вам начать.

// the string we want to parse.
char * psz = "a 3e,6s,1d,3g,22r,7c 3g,5r,9c 19.3";

// this is the states that our parser can be in.
enum {
   state_init,
   state_number,
   state_letter,
   state_comma,
   state_space,
   state_decimal,
   };

// storage for our letter values
int letter_vals['z' - 'a' + 1] = 0;

int val = 0; 
int state = state_init;
while (psz[0])
{
   char ch = psz[0];
   if (ch >= '0' && ch <= '9')
   {
      if (state == state_decimal)
      {
         // this is the last value that needs special treatment.
         double dval = (double)val + (ch / 10.0);
      }
      else if (state == state_number)
      {
         val = (val * 10) + ch - '0';
      }
      else
      {
         // we expect state to be state_space or state_comma here
         val = ch;
      }

      state = state_num;
   }
   else if (ch >= 'a' && ch <= 'z')
   {
      if (state == state_num)
      {
         letter_vals[ch - 'a'] = val;
         val = 0;
      }
      else if (state == state_init)
      {
         // ch is our "function"
      }
      else
      {
         // this is a letter that isn't after a number 
      }
      state = state_letter;
   }
   else if (ch == ',')
   {
      // state should be state_letter here
      state = state_comma;
   }
   else if (ch == ' ')
   {
      if (state == state_number)
      {
         // a space in the middle of the number or after a number is invalid!
      }
      else if (state == state_letter)
      {
         // this is a space after a letter, this means what?
      }
      else if (state == state_space)
      {
         // are multiple spaces invalid?
      }
      state = state_space;
   }
   else if (ch == '.')
   {
      if (state == state_number)
      {
         // this is normal 
      } 
      else
      {
         // this is an invalid state, a decimal not inside a number.
      }
      state = state_decimal;
   }
   else if (ch == '-')
   {
      // this is an invalid character
   }
   else
   {
      // this is an invalid letter.
   }


   ++psz;
}
1 голос
/ 14 марта 2010

Описание формата строки не совсем понятно, но я думаю, что могу ответить на ваш вопрос в любом случае (извлекая целые числа с буквами и добавляя (?) Их в соответствующую переменную int).

Итак, начиная с этой строки:

char * was = "3e, 6s, 1d, 3g, 22r, 7c"; // была == странная задница строка

вероятно, проще всего его токенизировать, используя strtok .

char* token = strtok (was,",");
while (token != NULL) {
    assign(token); // first token is 3e, second 6s etc...
    token = strtok (NULL, ",");
}

Теперь вы можете использовать sscanf , чтобы найти число и букву.

void assign(char* token) {
    char letter;
    int number;
    if (0 != sscanf(token, "%d%c", number, letter)) {
        // the first token produces letter 'e' and number '3'
        // now you can switch on letter and add number 
        // to the proper variable in each case
    } else {
        //matching failure!!
    }
}

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

Кроме того, любые ошибки формата будут обнаружены как минимум при вызове sscanf.

...