2009-08-25 4 views
2

Par exemple, je dois trouver l'heure dans le format mentionné dans le titre (mais % -tags l'ordre peut être différent) dans une chaîne "The date is 2009-August-25." Comment est-ce que je peux faire que le programme interprète les étiquettes et quelle construction est préférable d'utiliser pour les stocker parmi des informations sur la façon d'agir avec certaines parties de la chaîne de date?Besoin d'analyser une chaîne, ayant un masque (quelque chose comme ce "% yr-% mh-% dy"), donc je reçois les valeurs int

Répondre

1

Premier coup d'oeil dans la bibliothèque boost::date_time. Il a IO system sorcière peut être ce que vous voulez, mais je vois un manque de recherche.

Pour effectuer une recherche personnalisée, vous avez besoin de boost::xpressive. Il contient tout ce dont vous aurez besoin. Regardons dans mon exemple écrit à la hâte. D'abord, vous devez analyser votre motif personnalisé, ce qui est facile avec Xpressive. Regardez d'abord en-tête dont vous avez besoin:

#include <string> 
#include <iostream> 
#include <map> 
#include <boost/xpressive/xpressive_static.hpp> 
#include <boost/xpressive/regex_actions.hpp> 

//make example shorter but less clear 
using namespace boost::xpressive; 

deuxième définition carte de vos balises spéciales:

std::map<std::string, int > number_map; 
number_map["%yr"] = 0; 
number_map["%mh"] = 1; 
number_map["%dy"] = 2; 
number_map["%%"] = 3; // escape a % 

étape suivante consiste à créer une sorcière regex va analyser notre modèle avec les balises et enregistrer les valeurs de la carte dans la variable tag_id quand il trouver balise ou enregistrer -1 autrement:

int tag_id; 
sregex rx=((a1=number_map)|(s1=+~as_xpr('%')))[ref(tag_id)=(a1|-1)]; 

Plus d'informations et regarder la description here et here. permet maintenant analyser un certain modèle:

std::string pattern("%yr-%mh-%dy"); // this will be parsed 

    sregex_token_iterator begin(pattern.begin(), pattern.end(), rx), end; 
    if(begin == end) throw std::runtime_error("The pattern is empty!"); 

Le sregex_token_iterator va parcourir nos jetons, et chaque fois qu'il sera mis tag_id varible. Tout ce que nous avons à faire est de construire une regex en utilisant ces jetons. Nous allons construire ce regex en utilisant des parties correspondantes d'étiquette de regex statique définie dans le tableau:

sregex regex_group[] = { 
    range('1','9') >> repeat<3,3>(_d), // 4 digit year 
    as_xpr("January") | "February" | "August", // not all month XD so lazy 
    repeat<2,2>(range('0','9'))[ // two digit day 
    check(as<int>(_) >= 1 && as<int>(_) <= 31) ], //only bettwen 1 and 31 
    as_xpr('%') // match escaped % 
}; 

Enfin, permet de commencer à construire notre regex spécial. Le premier match construira la première partie de celui-ci. Si l'étiquette est adaptée et tag_id est non négatif que nous choisissons regex de tableau, sinon le match est probablement le delimiter et nous construisons sorcière regex correspond il:

sregex custom_regex = (tag_id>=0) ? regex_group[tag_id] : as_xpr(begin->str()); 

Ensuite, nous allons itérer de commencer à la fin et ajouter ensuite regex :

while(++begin != end) 
{ 
    if(tag_id>=0) 
    { 
     sregex nextregex = custom_regex >> regex_group[tag_id]; 
     custom_regex = nextregex; 
    } 
    else 
    { 
     sregex nextregex = custom_regex >> as_xpr(begin->str()); 
     custom_regex = nextregex; 
    } 
} 

maintenant, notre regex est prêt, permet de trouver des dates: -]

std::string input = "The date is 2009-August-25."; 

smatch mydate; 
if(regex_search(input, mydate, custom_regex)) 
    std::cout << "Found " << mydate.str() << "." << std::endl; 

La bibliothèque Xpressive est très puissant et rapide. C'est aussi une belle utilisation des motifs.

Si vous aimez cet exemple, faites-moi savoir dans un commentaire ou des points ;-)

1

Je transformer la chaîne étiquetée dans une expression régulière avec capture pour les 3 champs et la rechercher. La complexité de l'expression régulière dépend de ce que vous voulez accepter pour% yr. Vous pouvez aussi avoir une expression moins stricte et ensuite vérifier les valeurs valides, cela peut conduire à de meilleurs messages d'erreur ("Invalid month: Augsut" au lieu de "date introuvable") ou à des faux positifs en fonction du contexte.

Questions connexes