3

我有一个看起来像这样的字符串"a 3e,6s,1d,3g,22r,7c 3g,5r,9c 19.3",我该如何遍历它并提取整数并将它们分配给其相应的字母变量?(我有整数变量 d、r、e、g、s 和 c)。字符串中的第一个字母代表一个函数,“3e,6s,1d,3g,22r,7c”“3g,5r,9c”是两个独立的容器。最后一个十进制值表示一个需要分解为这些可变数字的数字。

我的问题是提取那些带有后面字母的整数并将它们分配到相应的字母中。任何带负号或数字与字母之间有空格的数字均无效。我到底该怎么做?

4

3 回答 3

3

如何使用正则表达式将不同部分解析为变量。之后,您可以将解析的变量转换为您的目标类型。

使用分组的正则表达式可能看起来像那个丑陋的怪物:

^([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];
于 2010-03-13T10:20:28.610 回答
2

一个简单的状态机似乎是解决这个问题的方法。我不确定您给出的规则是否足够完整,特别是我不了解空格的功能,或者您所说的“单独的容器”是什么意思。您应该添加更多代码来测试无效状态,但这应该可以帮助您入门。

// 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;
}
于 2010-03-13T07:37:01.790 回答
1

字符串格式的描述不是很清楚,但我想我还是可以回答你的问题(用字母提取整数并将(?)它们添加到正确的 int 变量中)。

所以从这个字符串开始:

char* 是 = "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 时,至少会捕获任何格式错误。

于 2010-03-13T21:49:44.577 回答