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」は 2 つの別個のコンテナです。そして、最後の 10 進数値は、これらの変数に分割する必要がある数値を表します。

私の問題は、それらの整数をその後の文字で抽出し、それらを対応する文字に割り当てることです。また、数字と文字の間にマイナス記号またはスペースがある数字は無効です。一体どうやってこれを行うのですか?

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 に答える