1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
///////////////////////////////////////////////////////////////////////////////
// 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 <iostream>
#include <string>
#include <map>
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>
///////////////////////////////////////////////////////////////////////////////
// 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<long> n(0);
// temp stores intermediate values
local<long> 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;
}
|