一种特定的字符串格式,其中数字和字符一起表示某个项目

时间:2010-03-13 07:06:14

标签: c++ string integer extraction

我有一个字符串看起来像“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”是两个独立的容器。最后一个十进制值表示一个需要分解为这些变量数的数字。

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

3 个答案:

答案 0 :(得分: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];

答案 1 :(得分: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;
}

答案 2 :(得分: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时,至少会捕获任何格式错误。