numbers.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // numbers.cpp
  3. //
  4. // Copyright 2008 David Jenkins. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #if defined(_MSC_VER)
  8. //disbale warning C4996: 'std::xxx' was declared deprecated
  9. # pragma warning(disable:4996)
  10. #endif
  11. #include <iostream>
  12. #include <string>
  13. #include <map>
  14. #include <boost/assign/list_of.hpp> // for 'map_list_of()'
  15. #include <boost/xpressive/xpressive.hpp>
  16. #include <boost/xpressive/regex_actions.hpp>
  17. ///////////////////////////////////////////////////////////////////////////////
  18. // Match all named numbers in a string and return their integer values
  19. //
  20. // For example, given the input string:
  21. // "one two sixty three thousand ninety five eleven"
  22. // the program will output:
  23. // "one = 1"
  24. // "two = 2"
  25. // "sixty three thousand ninety five = 63095"
  26. // "eleven = 11"
  27. void example1()
  28. {
  29. using namespace boost::xpressive;
  30. using namespace boost::assign;
  31. // initialize the maps for named numbers
  32. std::map< std::string, int > ones_map =
  33. map_list_of("one",1)("two",2)("three",3)("four",4)("five",5)
  34. ("six",6)("seven",7)("eight",8)("nine",9);
  35. std::map< std::string, int > teens_map =
  36. map_list_of("ten",10)("eleven",11)("twelve",12)("thirteen",13)
  37. ("fourteen",14)("fifteen",15)("sixteen",16)("seventeen",17)
  38. ("eighteen",18)("nineteen",19);
  39. std::map< std::string, int > tens_map =
  40. map_list_of("twenty",20)("thirty",30)("fourty",40)
  41. ("fifty",50)("sixty",60)("seventy",70)("eighty",80)("ninety",90);
  42. std::map< std::string, int > specials_map =
  43. map_list_of("zero",0)("dozen",12)("score",20);
  44. // n is the integer result
  45. local<long> n(0);
  46. // temp stores intermediate values
  47. local<long> temp(0);
  48. // initialize the regular expressions for named numbers
  49. sregex tens_rx =
  50. // use skip directive to skip whitespace between words
  51. skip(_s)
  52. (
  53. ( a3 = teens_map )
  54. |
  55. ( a2 = tens_map ) >> !( a1 = ones_map )
  56. |
  57. ( a1 = ones_map )
  58. )
  59. [ n += (a3|0) + (a2|0) + (a1|0) ];
  60. sregex hundreds_rx =
  61. skip(_s)
  62. (
  63. tens_rx >>
  64. !(
  65. as_xpr("hundred") [ n *= 100 ]
  66. >> !tens_rx
  67. )
  68. )
  69. ;
  70. sregex specials_rx = // regex for special number names like dozen
  71. skip(_s)
  72. (
  73. // Note: this uses two attribues, a1 and a2, and it uses
  74. // a default attribute value of 1 for a1.
  75. ( !( a1 = ones_map ) >> ( a2 = specials_map ) )
  76. [ n = (a1|1) * a2 ]
  77. >> !( "and" >> tens_rx )
  78. )
  79. ;
  80. sregex number_rx =
  81. bow
  82. >>
  83. skip(_s|punct)
  84. (
  85. specials_rx // special numbers
  86. |
  87. ( // normal numbers
  88. !( hundreds_rx >> "million" ) [ temp += n * 1000000, n = 0 ]
  89. >>
  90. !( hundreds_rx >> "thousand" ) [ temp += n * 1000, n = 0 ]
  91. >>
  92. !hundreds_rx
  93. )
  94. [n += temp, temp = 0 ]
  95. );
  96. // this is the input string
  97. std::string str( "one two three eighteen twenty two "
  98. "nine hundred ninety nine twelve "
  99. "eight hundred sixty three thousand ninety five "
  100. "sixty five hundred ten "
  101. "two million eight hundred sixty three thousand ninety five "
  102. "zero sixty five hundred thousand "
  103. "extra stuff "
  104. "two dozen "
  105. "four score and seven");
  106. // the MATCHING results of iterating through the string are:
  107. // one = 1
  108. // two = 2
  109. // three = 3
  110. // eighteen = 18
  111. // twenty two = 22
  112. // nine hundred ninety nine = 999
  113. // twelve = 12
  114. // eight hundred sixty three thousand ninety five = 863095
  115. // sixty five hundred ten = 6510
  116. // two million eight hundred sixty three thousand ninety five = 2863095
  117. // zero = 0
  118. // sixty five hundred thousand = 6500000
  119. // two dozen = 24
  120. // four score and seven = 87
  121. sregex_token_iterator cur( str.begin(), str.end(), number_rx );
  122. sregex_token_iterator end;
  123. for( ; cur != end; ++cur )
  124. {
  125. if ((*cur).length() > 0)
  126. std::cout << *cur << " = " << n.get() << '\n';
  127. n.get() = 0;
  128. }
  129. std::cout << '\n';
  130. // the NON-MATCHING results of iterating through the string are:
  131. // extra = unmatched
  132. // stuff = unmatched
  133. sregex_token_iterator cur2( str.begin(), str.end(), number_rx, -1 );
  134. for( ; cur2 != end; ++cur2 )
  135. {
  136. if ((*cur2).length() > 0)
  137. std::cout << *cur2 << " = unmatched" << '\n';
  138. }
  139. }
  140. ///////////////////////////////////////////////////////////////////////////////
  141. // main
  142. int main()
  143. {
  144. std::cout << "\n\nExample 1:\n\n";
  145. example1();
  146. std::cout << "\n\n" << std::flush;
  147. return 0;
  148. }