/////////////////////////////////////////////////////////////////////////////// // numbers.cpp // // Copyright 2008 David Jenkins. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #if defined(_MSC_VER) //disbale warning C4996: 'std::xxx' was declared deprecated # pragma warning(disable:4996) #endif #include #include #include #include // for 'map_list_of()' #include #include /////////////////////////////////////////////////////////////////////////////// // Match all named numbers in a string and return their integer values // // For example, given the input string: // "one two sixty three thousand ninety five eleven" // the program will output: // "one = 1" // "two = 2" // "sixty three thousand ninety five = 63095" // "eleven = 11" void example1() { using namespace boost::xpressive; using namespace boost::assign; // initialize the maps for named numbers std::map< std::string, int > ones_map = map_list_of("one",1)("two",2)("three",3)("four",4)("five",5) ("six",6)("seven",7)("eight",8)("nine",9); std::map< std::string, int > teens_map = map_list_of("ten",10)("eleven",11)("twelve",12)("thirteen",13) ("fourteen",14)("fifteen",15)("sixteen",16)("seventeen",17) ("eighteen",18)("nineteen",19); std::map< std::string, int > tens_map = map_list_of("twenty",20)("thirty",30)("fourty",40) ("fifty",50)("sixty",60)("seventy",70)("eighty",80)("ninety",90); std::map< std::string, int > specials_map = map_list_of("zero",0)("dozen",12)("score",20); // n is the integer result local n(0); // temp stores intermediate values local temp(0); // initialize the regular expressions for named numbers sregex tens_rx = // use skip directive to skip whitespace between words skip(_s) ( ( a3 = teens_map ) | ( a2 = tens_map ) >> !( a1 = ones_map ) | ( a1 = ones_map ) ) [ n += (a3|0) + (a2|0) + (a1|0) ]; sregex hundreds_rx = skip(_s) ( tens_rx >> !( as_xpr("hundred") [ n *= 100 ] >> !tens_rx ) ) ; sregex specials_rx = // regex for special number names like dozen skip(_s) ( // Note: this uses two attribues, a1 and a2, and it uses // a default attribute value of 1 for a1. ( !( a1 = ones_map ) >> ( a2 = specials_map ) ) [ n = (a1|1) * a2 ] >> !( "and" >> tens_rx ) ) ; sregex number_rx = bow >> skip(_s|punct) ( specials_rx // special numbers | ( // normal numbers !( hundreds_rx >> "million" ) [ temp += n * 1000000, n = 0 ] >> !( hundreds_rx >> "thousand" ) [ temp += n * 1000, n = 0 ] >> !hundreds_rx ) [n += temp, temp = 0 ] ); // this is the input string std::string str( "one two three eighteen twenty two " "nine hundred ninety nine twelve " "eight hundred sixty three thousand ninety five " "sixty five hundred ten " "two million eight hundred sixty three thousand ninety five " "zero sixty five hundred thousand " "extra stuff " "two dozen " "four score and seven"); // the MATCHING results of iterating through the string are: // one = 1 // two = 2 // three = 3 // eighteen = 18 // twenty two = 22 // nine hundred ninety nine = 999 // twelve = 12 // eight hundred sixty three thousand ninety five = 863095 // sixty five hundred ten = 6510 // two million eight hundred sixty three thousand ninety five = 2863095 // zero = 0 // sixty five hundred thousand = 6500000 // two dozen = 24 // four score and seven = 87 sregex_token_iterator cur( str.begin(), str.end(), number_rx ); sregex_token_iterator end; for( ; cur != end; ++cur ) { if ((*cur).length() > 0) std::cout << *cur << " = " << n.get() << '\n'; n.get() = 0; } std::cout << '\n'; // the NON-MATCHING results of iterating through the string are: // extra = unmatched // stuff = unmatched sregex_token_iterator cur2( str.begin(), str.end(), number_rx, -1 ); for( ; cur2 != end; ++cur2 ) { if ((*cur2).length() > 0) std::cout << *cur2 << " = unmatched" << '\n'; } } /////////////////////////////////////////////////////////////////////////////// // main int main() { std::cout << "\n\nExample 1:\n\n"; example1(); std::cout << "\n\n" << std::flush; return 0; }