免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: toddytao
打印 上一主题 下一主题

Linux 下实现计算器程序,高手请进!! [复制链接]

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
11 [报告]
发表于 2011-08-09 14:46 |只看该作者
增加:阿拉伯数字解析,增加英文多项运算符后的“with”解析。

  1. /* eng_cac.c */

  2. /* english caculator */

  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>

  6. int skip_space(const char *p, int *io_index)
  7. {
  8.         int index;

  9.         if (p == NULL || io_index == NULL) {
  10.                 return -1;
  11.         }
  12.         index = *io_index;
  13.         if (index < 0) {
  14.                 return -1;
  15.         }
  16.         if (!isspace(p[index])) {
  17.                 return -1;
  18.         }
  19.         do {
  20.                 ++index;
  21.         }while (isspace(p[index]));
  22.         *io_index = index;
  23.         return 0;
  24. }

  25. int get_word(const char *p, int *io_index, int *o_start, int *o_len)
  26. {
  27.         int index;

  28.         if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
  29.                 return -1;
  30.         }
  31.         index = *io_index;
  32.         if (index < 0) {
  33.                 return -1;
  34.         }
  35.         if (isalpha(p[index])) {
  36.                 do {
  37.                         ++index;
  38.                 }while (isalpha(p[index]));
  39.                 *o_start = *io_index;
  40.                 *o_len = index - *io_index;
  41.                 *io_index = index;
  42.                 return 0;
  43.         }else if (ispunct(p[index])) {
  44.                 ++index;
  45.                 *o_start = *io_index;
  46.                 *o_len = 1;
  47.                 *io_index = index;
  48.                 return 0;
  49.         }else {
  50.                 return -1;
  51.         }
  52. }

  53. int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
  54. {
  55.         int i;

  56.         if (tok == NULL || tok_tab == NULL) {
  57.                 return -1;
  58.         }
  59.         if (len <= 0 || tab_len <= 0) {
  60.                 return -1;
  61.         }
  62.         for (i = 0; i < tab_len; ++i) {
  63.                 if (strncmp(tok, tok_tab[i], len) == 0) {
  64.                         return i;
  65.                 }
  66.         }
  67.         return -1;
  68. }

  69. int skip_word(const char *p, int *io_index, const char *s)
  70. {
  71.         int index;
  72.         int start, len;

  73.         if (p == NULL || io_index == NULL || s == NULL) {
  74.                 return -1;
  75.         }
  76.         index = *io_index;
  77.         if (index < 0) {
  78.                 return -1;
  79.         }
  80.         skip_space(p, &index);
  81.         if (get_word(p, &index, &start, &len) == 0) {
  82.                 if (strncmp(p + start, s, len) == 0) {
  83.                         *io_index = index;
  84.                         return 0;
  85.                 }
  86.         }
  87.         return -1;
  88. }

  89. int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
  90. {
  91.         static const char *digit20[20] = {
  92.                 "zero",
  93.                 "one",
  94.                 "two",
  95.                 "three",
  96.                 "four",
  97.                 "five",
  98.                 "six",
  99.                 "seven",
  100.                 "eight",
  101.                 "nine",
  102.                 "ten",
  103.                 "eleven",
  104.                 "twelve",
  105.                 "thirteen",
  106.                 "fourteen",
  107.                 "fifteen",
  108.                 "sixteen",
  109.                 "seventeen",
  110.                 "eighteen",
  111.                 "nineteen",
  112.         };
  113.         int index;
  114.         int start;
  115.         int len;
  116.         int tok;

  117.         if (p == NULL || io_index == NULL || o_value == NULL) {
  118.                 return -1;
  119.         }
  120.         index = *io_index;
  121.         if (index < 0) {
  122.                 return -1;
  123.         }
  124.         skip_space(p, &index);
  125.         if (get_word(p, &index, &start, &len) == 0) {
  126.                 tok = get_token(p + start, len, digit20, 20);
  127.                 if (tok != -1) {
  128.                         *o_value = tok;
  129.                         *io_index = index;
  130.                         return 0;
  131.                 }
  132.         }
  133.         return -1;
  134. }

  135. int get_english_digit_decade(const char *p, int *io_index, int *o_value)
  136. {
  137.         static const char *decades[8] = {
  138.                 "twenty",
  139.                 "thirty",
  140.                 "forty",
  141.                 "fifty",
  142.                 "sixty",
  143.                 "seventy",
  144.                 "eighty",
  145.                 "ninety",
  146.         };
  147.         int index;
  148.         int start, len;
  149.         int value;
  150.         int retn;

  151.         if (p == NULL || io_index == NULL || o_value == NULL) {
  152.                 return -1;
  153.         }
  154.         index = *io_index;
  155.         if (index < 0) {
  156.                 return -1;
  157.         }
  158.         skip_space(p, &index);
  159.         if (get_word(p, &index, &start, &len) == 0) {
  160.                 retn = get_token(p + start, len, decades, 8);
  161.                 if (retn != -1) {
  162.                         value = retn * 10 + 20;
  163.                         *o_value = value;
  164.                         *io_index = index;
  165.                         return 0;
  166.                 }
  167.         }
  168.         return -1;
  169. }

  170. int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
  171. {
  172.         int index;
  173.         int value;
  174.         int digit;
  175.         int decade_yes;

  176.         if (p == NULL || io_index == NULL || o_value == NULL) {
  177.                 return -1;
  178.         }
  179.         index = *io_index;
  180.         if (index < 0) {
  181.                 return -1;
  182.         }
  183.         decade_yes = 0;
  184.         if (get_english_digit_decade(p, &index, &value) == -1) {
  185.                 value = 0;
  186.         }else {
  187.                 decade_yes = 1;
  188.         }
  189.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  190.                 if (decade_yes && digit == 0) {
  191.                         return -1;
  192.                 }
  193.                 value += digit;
  194.         }else {
  195.                 if (!decade_yes) {
  196.                         return -1;
  197.                 }
  198.         }
  199.         *o_value = value;
  200.         *io_index = index;
  201.         return 0;
  202. }

  203. int get_digit_base(const char *p, int *io_index, int *o_base)
  204. {
  205.         static const char *more[] = {
  206.                 "hundred",
  207.                 "thousand",
  208.                 "million",
  209.                 "billion",
  210.         };
  211.         static const int base[] = {
  212.                 100,
  213.                 1000,
  214.                 1000000,
  215.                 1000000000,
  216.         };
  217.         int index;
  218.         int start,len;
  219.         int retn;

  220.         if (p == NULL || io_index == NULL || o_base == NULL) {
  221.                 return -1;
  222.         }
  223.         index = *io_index;
  224.         if (index < 0) {
  225.                 return -1;
  226.         }
  227.         skip_space(p, &index);
  228.         if (get_word(p, &index, &start, &len) == 0) {
  229.                 retn = get_token(p + start, len, more, 4);
  230.                 if (retn != -1) {
  231.                         *o_base = base[retn];
  232.                         *io_index = index;
  233.                         return 0;
  234.                 }
  235.         }
  236.         return -1;
  237. }

  238. int get_english_digit(const char *p, int *io_index, int *o_value)
  239. {
  240.         int index;
  241.         int value;
  242.         int sum;
  243.         int base;

  244.         if (p == NULL || io_index == NULL || o_value == NULL) {
  245.                 return -1;
  246.         }
  247.         index = *io_index;
  248.         if (index < 0) {
  249.                 return -1;
  250.         }
  251.         sum = 0;
  252.         for (;;) {
  253.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  254.                         if (sum > 0 && value == 0) {
  255.                                 return -1;
  256.                         }
  257.                         sum += value;
  258.                         if (get_digit_base(p, &index, &base) == 0) {
  259.                                 if (sum == 0) {
  260.                                         return -1;
  261.                                 }
  262.                                 sum *= base;
  263.                                 if (skip_word(p, &index, "and") == 0) {
  264.                                         continue;
  265.                                 }
  266.                         }
  267.                         *o_value = sum;
  268.                         *io_index = index;
  269.                         return 0;
  270.                 }else if (sum == 0) {
  271.                         if (skip_word(p, &index, "a") == 0) {
  272.                                 if (get_digit_base(p, &index, &base) == 0) {
  273.                                         sum = base;
  274.                                         if (skip_word(p, &index, "and") == 0) {
  275.                                                 continue;
  276.                                         }
  277.                                         *o_value = sum;
  278.                                         *io_index = index;
  279.                                         return 0;
  280.                                 }
  281.                         }
  282.                 }
  283.                 return -1;
  284.         }
  285. }

  286. int get_operator1(const char *p, int *io_index, int *o_op)
  287. {
  288.         static const char *op_list[] = {
  289.                 "positive",
  290.                 "+",
  291.                 "negative",
  292.                 "-",
  293.         };
  294.         int index;
  295.         int start, len;
  296.         int retn;
  297.        
  298.         if (p == NULL || io_index == NULL || o_op == NULL) {
  299.                 return -1;
  300.         }
  301.         index = *io_index;
  302.         if (index < 0) {
  303.                 return -1;
  304.         }
  305.         skip_space(p, &index);
  306.         if (get_word(p, &index, &start, &len) == 0) {
  307.                 retn = get_token(p + start, len, op_list, 8);
  308.                 if (retn != -1) {
  309.                         *o_op = retn / 2;
  310.                         *io_index = index;
  311.                         return 0;
  312.                 }
  313.         }
  314.         return -1;
  315. }

  316. int get_operator2(const char *p, int *io_index, int *o_op)
  317. {
  318.         static const char *op_list[] = {
  319.                 "plus",
  320.                 "+",
  321.                 "minus",
  322.                 "-",
  323.                 "multiply",
  324.                 "*",
  325.                 "divide",
  326.                 "/",
  327.         };
  328.         int index;
  329.         int start, len;
  330.         int retn;

  331.         if (p == NULL || io_index == NULL || o_op == NULL) {
  332.                 return -1;
  333.         }
  334.         index = *io_index;
  335.         if (index < 0) {
  336.                 return -1;
  337.         }
  338.         skip_space(p, &index);
  339.         if (get_word(p, &index, &start, &len) == 0) {
  340.                 retn = get_token(p + start, len, op_list, 8);
  341.                 if (retn != -1) {
  342.                         if ((retn & 1) == 0) {
  343.                                 skip_word(p, &index, "with");
  344.                         }
  345.                         *o_op = retn / 2;
  346.                         *io_index = index;
  347.                         return 0;
  348.                 }
  349.         }
  350.         return -1;
  351. }

  352. int get_number(const char *p, int *io_index, int *o_value)
  353. {
  354.         int index;
  355.         int value;
  356.         int negative;

  357.         if (p == NULL || io_index == NULL || o_value == NULL) {
  358.                 return -1;
  359.         }
  360.         index = *io_index;
  361.         if (index < 0) {
  362.                 return -1;
  363.         }
  364.         value = 0;
  365.         negative = 0;
  366.         skip_space(p, &index);
  367.         if (p[index] == '-') {
  368.                 ++index;
  369.                 negative = 1;
  370.         }else if (p[index] == '+') {
  371.                 ++index;
  372.         }
  373.         skip_space(p, &index);
  374.         if (isdigit(p[index])) {
  375.                 value = 0;
  376.                 do {
  377.                         value = value * 10 + p[index] - '0';
  378.                         index++;
  379.                 }while (isdigit(p[index]));
  380.                 if (negative) {
  381.                         value = - value;
  382.                 }
  383.                 *o_value = value;
  384.                 *io_index = index;
  385.                 return 0;
  386.         }
  387.         return -1;
  388. }

  389. int get_digit(const char *p, int *io_index, int *o_value)
  390. {
  391.         int index;
  392.         int value;

  393.         if (p == NULL || io_index == NULL || o_value == NULL) {
  394.                 return -1;
  395.         }
  396.         index = *io_index;
  397.         if (index < 0) {
  398.                 return -1;
  399.         }
  400.         if (get_english_digit(p, &index, &value) == 0
  401.                 || get_number(p, &index, &value) == 0) {
  402.                 *o_value = value;
  403.                 *io_index = index;
  404.                 return 0;
  405.         }
  406.         return -1;
  407. }

  408. int main(void)
  409. {
  410.         char cmd_line[1024];
  411.         int op; /* operator */
  412.         int d1, d2; /* oprand number */
  413.         int result; /* store the expression result */
  414.         int index;

  415.         puts("English Caculator\n");
  416.         puts("Please enter an expression");
  417.         puts("CTRL-Z to exit");
  418.         for (;;) {
  419.                 printf("\n: ");
  420.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  421.                         return 0;
  422.                 }
  423.                 index = 0;
  424.                 if (get_digit(cmd_line, &index, &d1) == 0) {
  425.                         /* two oprands operation */
  426.                         if (get_operator2(cmd_line, &index, &op) != 0) {
  427.                                 printf("Invalid Operator\n");
  428.                                 continue;
  429.                         }
  430.                         if (get_digit(cmd_line, &index, &d2) != 0) {
  431.                                 printf("Invalid English Number\n");
  432.                                 continue;
  433.                         }
  434.                         switch (op) {
  435.                         case 0:
  436.                                 result = d1 + d2;
  437.                                 break;
  438.                         case 1:
  439.                                 result = d1 - d2;
  440.                                 break;
  441.                         case 2:
  442.                                 result = d1 * d2;
  443.                                 break;
  444.                         case 3:
  445.                                 result = d1 / d2;
  446.                                 break;
  447.                         default:
  448.                                 printf("unknown operator\n");
  449.                                 continue;
  450.                         }
  451.                 }else {
  452.                         /* one oprand operation */
  453.                         if (get_operator1(cmd_line, &index, &op) != 0) {
  454.                                 printf("Invalid Operator\n");
  455.                                 continue;
  456.                         }
  457.                         if (get_digit(cmd_line, &index, &d1) != 0) {
  458.                                 printf("Invalid English Number\n");
  459.                                 continue;
  460.                         }
  461.                         switch (op) {
  462.                         case 0:
  463.                                 result = d1;
  464.                                 break;
  465.                         case 1:
  466.                                 result = -d1;
  467.                                 break;
  468.                         default:
  469.                                 printf("unknown operator\n");
  470.                                 continue;
  471.                         }
  472.                 }
  473.                 printf("%d\n", result);
  474.         }
  475. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
12 [报告]
发表于 2011-08-09 15:01 |只看该作者
支持级联表达式运算,优先级与计算器相同,从左到右。

  1. /* eng_cac.c */

  2. /* english caculator */

  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>

  6. int skip_space(const char *p, int *io_index)
  7. {
  8.         int index;

  9.         if (p == NULL || io_index == NULL) {
  10.                 return -1;
  11.         }
  12.         index = *io_index;
  13.         if (index < 0) {
  14.                 return -1;
  15.         }
  16.         if (!isspace(p[index])) {
  17.                 return -1;
  18.         }
  19.         do {
  20.                 ++index;
  21.         }while (isspace(p[index]));
  22.         *io_index = index;
  23.         return 0;
  24. }

  25. int get_word(const char *p, int *io_index, int *o_start, int *o_len)
  26. {
  27.         int index;

  28.         if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
  29.                 return -1;
  30.         }
  31.         index = *io_index;
  32.         if (index < 0) {
  33.                 return -1;
  34.         }
  35.         if (isalpha(p[index])) {
  36.                 do {
  37.                         ++index;
  38.                 }while (isalpha(p[index]));
  39.                 *o_start = *io_index;
  40.                 *o_len = index - *io_index;
  41.                 *io_index = index;
  42.                 return 0;
  43.         }else if (ispunct(p[index])) {
  44.                 ++index;
  45.                 *o_start = *io_index;
  46.                 *o_len = 1;
  47.                 *io_index = index;
  48.                 return 0;
  49.         }else {
  50.                 return -1;
  51.         }
  52. }

  53. int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
  54. {
  55.         int i;

  56.         if (tok == NULL || tok_tab == NULL) {
  57.                 return -1;
  58.         }
  59.         if (len <= 0 || tab_len <= 0) {
  60.                 return -1;
  61.         }
  62.         for (i = 0; i < tab_len; ++i) {
  63.                 if (strncmp(tok, tok_tab[i], len) == 0) {
  64.                         return i;
  65.                 }
  66.         }
  67.         return -1;
  68. }

  69. int skip_word(const char *p, int *io_index, const char *s)
  70. {
  71.         int index;
  72.         int start, len;

  73.         if (p == NULL || io_index == NULL || s == NULL) {
  74.                 return -1;
  75.         }
  76.         index = *io_index;
  77.         if (index < 0) {
  78.                 return -1;
  79.         }
  80.         skip_space(p, &index);
  81.         if (get_word(p, &index, &start, &len) == 0) {
  82.                 if (strncmp(p + start, s, len) == 0) {
  83.                         *io_index = index;
  84.                         return 0;
  85.                 }
  86.         }
  87.         return -1;
  88. }

  89. int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
  90. {
  91.         static const char *digit20[20] = {
  92.                 "zero",
  93.                 "one",
  94.                 "two",
  95.                 "three",
  96.                 "four",
  97.                 "five",
  98.                 "six",
  99.                 "seven",
  100.                 "eight",
  101.                 "nine",
  102.                 "ten",
  103.                 "eleven",
  104.                 "twelve",
  105.                 "thirteen",
  106.                 "fourteen",
  107.                 "fifteen",
  108.                 "sixteen",
  109.                 "seventeen",
  110.                 "eighteen",
  111.                 "nineteen",
  112.         };
  113.         int index;
  114.         int start;
  115.         int len;
  116.         int tok;

  117.         if (p == NULL || io_index == NULL || o_value == NULL) {
  118.                 return -1;
  119.         }
  120.         index = *io_index;
  121.         if (index < 0) {
  122.                 return -1;
  123.         }
  124.         skip_space(p, &index);
  125.         if (get_word(p, &index, &start, &len) == 0) {
  126.                 tok = get_token(p + start, len, digit20, 20);
  127.                 if (tok != -1) {
  128.                         *o_value = tok;
  129.                         *io_index = index;
  130.                         return 0;
  131.                 }
  132.         }
  133.         return -1;
  134. }

  135. int get_english_digit_decade(const char *p, int *io_index, int *o_value)
  136. {
  137.         static const char *decades[8] = {
  138.                 "twenty",
  139.                 "thirty",
  140.                 "forty",
  141.                 "fifty",
  142.                 "sixty",
  143.                 "seventy",
  144.                 "eighty",
  145.                 "ninety",
  146.         };
  147.         int index;
  148.         int start, len;
  149.         int value;
  150.         int retn;

  151.         if (p == NULL || io_index == NULL || o_value == NULL) {
  152.                 return -1;
  153.         }
  154.         index = *io_index;
  155.         if (index < 0) {
  156.                 return -1;
  157.         }
  158.         skip_space(p, &index);
  159.         if (get_word(p, &index, &start, &len) == 0) {
  160.                 retn = get_token(p + start, len, decades, 8);
  161.                 if (retn != -1) {
  162.                         value = retn * 10 + 20;
  163.                         *o_value = value;
  164.                         *io_index = index;
  165.                         return 0;
  166.                 }
  167.         }
  168.         return -1;
  169. }

  170. int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
  171. {
  172.         int index;
  173.         int value;
  174.         int digit;
  175.         int decade_yes;

  176.         if (p == NULL || io_index == NULL || o_value == NULL) {
  177.                 return -1;
  178.         }
  179.         index = *io_index;
  180.         if (index < 0) {
  181.                 return -1;
  182.         }
  183.         decade_yes = 0;
  184.         if (get_english_digit_decade(p, &index, &value) == -1) {
  185.                 value = 0;
  186.         }else {
  187.                 decade_yes = 1;
  188.         }
  189.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  190.                 if (decade_yes && digit == 0) {
  191.                         return -1;
  192.                 }
  193.                 value += digit;
  194.         }else {
  195.                 if (!decade_yes) {
  196.                         return -1;
  197.                 }
  198.         }
  199.         *o_value = value;
  200.         *io_index = index;
  201.         return 0;
  202. }

  203. int get_digit_base(const char *p, int *io_index, int *o_base)
  204. {
  205.         static const char *more[] = {
  206.                 "hundred",
  207.                 "thousand",
  208.                 "million",
  209.                 "billion",
  210.         };
  211.         static const int base[] = {
  212.                 100,
  213.                 1000,
  214.                 1000000,
  215.                 1000000000,
  216.         };
  217.         int index;
  218.         int start,len;
  219.         int retn;

  220.         if (p == NULL || io_index == NULL || o_base == NULL) {
  221.                 return -1;
  222.         }
  223.         index = *io_index;
  224.         if (index < 0) {
  225.                 return -1;
  226.         }
  227.         skip_space(p, &index);
  228.         if (get_word(p, &index, &start, &len) == 0) {
  229.                 retn = get_token(p + start, len, more, 4);
  230.                 if (retn != -1) {
  231.                         *o_base = base[retn];
  232.                         *io_index = index;
  233.                         return 0;
  234.                 }
  235.         }
  236.         return -1;
  237. }

  238. int get_english_digit(const char *p, int *io_index, int *o_value)
  239. {
  240.         int index;
  241.         int value;
  242.         int sum;
  243.         int base;

  244.         if (p == NULL || io_index == NULL || o_value == NULL) {
  245.                 return -1;
  246.         }
  247.         index = *io_index;
  248.         if (index < 0) {
  249.                 return -1;
  250.         }
  251.         sum = 0;
  252.         for (;;) {
  253.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  254.                         if (sum > 0 && value == 0) {
  255.                                 return -1;
  256.                         }
  257.                         sum += value;
  258.                         if (get_digit_base(p, &index, &base) == 0) {
  259.                                 if (sum == 0) {
  260.                                         return -1;
  261.                                 }
  262.                                 sum *= base;
  263.                                 if (skip_word(p, &index, "and") == 0) {
  264.                                         continue;
  265.                                 }
  266.                         }
  267.                         *o_value = sum;
  268.                         *io_index = index;
  269.                         return 0;
  270.                 }else if (sum == 0) {
  271.                         if (skip_word(p, &index, "a") == 0) {
  272.                                 if (get_digit_base(p, &index, &base) == 0) {
  273.                                         sum = base;
  274.                                         if (skip_word(p, &index, "and") == 0) {
  275.                                                 continue;
  276.                                         }
  277.                                         *o_value = sum;
  278.                                         *io_index = index;
  279.                                         return 0;
  280.                                 }
  281.                         }
  282.                 }
  283.                 return -1;
  284.         }
  285. }

  286. int get_operator1(const char *p, int *io_index, int *o_op)
  287. {
  288.         static const char *op_list[] = {
  289.                 "positive",
  290.                 "+",
  291.                 "negative",
  292.                 "-",
  293.         };
  294.         int index;
  295.         int start, len;
  296.         int retn;
  297.        
  298.         if (p == NULL || io_index == NULL || o_op == NULL) {
  299.                 return -1;
  300.         }
  301.         index = *io_index;
  302.         if (index < 0) {
  303.                 return -1;
  304.         }
  305.         skip_space(p, &index);
  306.         if (get_word(p, &index, &start, &len) == 0) {
  307.                 retn = get_token(p + start, len, op_list, 8);
  308.                 if (retn != -1) {
  309.                         *o_op = retn / 2;
  310.                         *io_index = index;
  311.                         return 0;
  312.                 }
  313.         }
  314.         return -1;
  315. }

  316. int get_operator2(const char *p, int *io_index, int *o_op)
  317. {
  318.         static const char *op_list[] = {
  319.                 "plus",
  320.                 "+",
  321.                 "minus",
  322.                 "-",
  323.                 "multiply",
  324.                 "*",
  325.                 "divide",
  326.                 "/",
  327.         };
  328.         int index;
  329.         int start, len;
  330.         int retn;

  331.         if (p == NULL || io_index == NULL || o_op == NULL) {
  332.                 return -1;
  333.         }
  334.         index = *io_index;
  335.         if (index < 0) {
  336.                 return -1;
  337.         }
  338.         skip_space(p, &index);
  339.         if (get_word(p, &index, &start, &len) == 0) {
  340.                 retn = get_token(p + start, len, op_list, 8);
  341.                 if (retn != -1) {
  342.                         if ((retn & 1) == 0) {
  343.                                 skip_word(p, &index, "with");
  344.                         }
  345.                         *o_op = retn / 2;
  346.                         *io_index = index;
  347.                         return 0;
  348.                 }
  349.         }
  350.         return -1;
  351. }

  352. int get_number(const char *p, int *io_index, int *o_value)
  353. {
  354.         int index;
  355.         int value;

  356.         if (p == NULL || io_index == NULL || o_value == NULL) {
  357.                 return -1;
  358.         }
  359.         index = *io_index;
  360.         if (index < 0) {
  361.                 return -1;
  362.         }
  363.         skip_space(p, &index);
  364.         if (isdigit(p[index])) {
  365.                 value = 0;
  366.                 do {
  367.                         value = value * 10 + p[index] - '0';
  368.                         index++;
  369.                 }while (isdigit(p[index]));
  370.                 *o_value = value;
  371.                 *io_index = index;
  372.                 return 0;
  373.         }
  374.         return -1;
  375. }

  376. int get_digit(const char *p, int *io_index, int *o_value)
  377. {
  378.         int index;
  379.         int value;

  380.         if (p == NULL || io_index == NULL || o_value == NULL) {
  381.                 return -1;
  382.         }
  383.         index = *io_index;
  384.         if (index < 0) {
  385.                 return -1;
  386.         }
  387.         if (get_english_digit(p, &index, &value) == 0
  388.                 || get_number(p, &index, &value) == 0) {
  389.                 *o_value = value;
  390.                 *io_index = index;
  391.                 return 0;
  392.         }
  393.         return -1;
  394. }

  395. int main(void)
  396. {
  397.         char cmd_line[1024];
  398.         int op; /* operator */
  399.         int d1, d2; /* oprand number */
  400.         int result; /* store the expression result */
  401.         int index;

  402.         puts("English Caculator\n");
  403.         puts("Please enter an expression");
  404.         puts("CTRL-Z to exit");
  405.         for (;;) {
  406.                 printf("\n: ");
  407.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  408.                         return 0;
  409.                 }
  410.                 index = 0;
  411.                 if (get_digit(cmd_line, &index, &d1) == -1) {
  412.                         /* one oprand operation */
  413.                         if (get_operator1(cmd_line, &index, &op) != 0) {
  414.                                 printf("Invalid Operator\n");
  415.                                 continue;
  416.                         }
  417.                         if (get_digit(cmd_line, &index, &d1) != 0) {
  418.                                 printf("Invalid English Number\n");
  419.                                 continue;
  420.                         }
  421.                         switch (op) {
  422.                         case 0:
  423.                                 result = d1;
  424.                                 break;
  425.                         case 1:
  426.                                 result = -d1;
  427.                                 break;
  428.                         default:
  429.                                 printf("unknown operator\n");
  430.                                 continue;
  431.                         }
  432.                         d1 = result;
  433.                 }
  434.                 /* conjunction operation */
  435.                 for (;;) {
  436.                         /* two oprands operation */
  437.                         if (get_operator2(cmd_line, &index, &op) != 0) {
  438.                                 printf("%d\n", result);
  439.                                 break; /* end of conjunction */
  440.                         }
  441.                         if (get_digit(cmd_line, &index, &d2) != 0) {
  442.                                 printf("Invalid English Number\n");
  443.                                 break;
  444.                         }
  445.                         switch (op) {
  446.                         case 0:
  447.                                 result = d1 + d2;
  448.                                 break;
  449.                         case 1:
  450.                                 result = d1 - d2;
  451.                                 break;
  452.                         case 2:
  453.                                 result = d1 * d2;
  454.                                 break;
  455.                         case 3:
  456.                                 result = d1 / d2;
  457.                                 break;
  458.                         default:
  459.                                 printf("unknown operator\n");
  460.                                 continue;
  461.                         }
  462.                         d1 = result;
  463.                 }
  464.         }
  465. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
13 [报告]
发表于 2011-08-09 15:13 |只看该作者
支持单项运算作为运算操作数。

  1. /* eng_cac.c */

  2. /* english caculator */

  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>

  6. int skip_space(const char *p, int *io_index)
  7. {
  8.         int index;

  9.         if (p == NULL || io_index == NULL) {
  10.                 return -1;
  11.         }
  12.         index = *io_index;
  13.         if (index < 0) {
  14.                 return -1;
  15.         }
  16.         if (!isspace(p[index])) {
  17.                 return -1;
  18.         }
  19.         do {
  20.                 ++index;
  21.         }while (isspace(p[index]));
  22.         *io_index = index;
  23.         return 0;
  24. }

  25. int get_word(const char *p, int *io_index, int *o_start, int *o_len)
  26. {
  27.         int index;

  28.         if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
  29.                 return -1;
  30.         }
  31.         index = *io_index;
  32.         if (index < 0) {
  33.                 return -1;
  34.         }
  35.         if (isalpha(p[index])) {
  36.                 do {
  37.                         ++index;
  38.                 }while (isalpha(p[index]));
  39.                 *o_start = *io_index;
  40.                 *o_len = index - *io_index;
  41.                 *io_index = index;
  42.                 return 0;
  43.         }else if (ispunct(p[index])) {
  44.                 ++index;
  45.                 *o_start = *io_index;
  46.                 *o_len = 1;
  47.                 *io_index = index;
  48.                 return 0;
  49.         }else {
  50.                 return -1;
  51.         }
  52. }

  53. int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
  54. {
  55.         int i;

  56.         if (tok == NULL || tok_tab == NULL) {
  57.                 return -1;
  58.         }
  59.         if (len <= 0 || tab_len <= 0) {
  60.                 return -1;
  61.         }
  62.         for (i = 0; i < tab_len; ++i) {
  63.                 if (strncmp(tok, tok_tab[i], len) == 0) {
  64.                         return i;
  65.                 }
  66.         }
  67.         return -1;
  68. }

  69. int skip_word(const char *p, int *io_index, const char *s)
  70. {
  71.         int index;
  72.         int start, len;

  73.         if (p == NULL || io_index == NULL || s == NULL) {
  74.                 return -1;
  75.         }
  76.         index = *io_index;
  77.         if (index < 0) {
  78.                 return -1;
  79.         }
  80.         skip_space(p, &index);
  81.         if (get_word(p, &index, &start, &len) == 0) {
  82.                 if (strncmp(p + start, s, len) == 0) {
  83.                         *io_index = index;
  84.                         return 0;
  85.                 }
  86.         }
  87.         return -1;
  88. }

  89. int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
  90. {
  91.         static const char *digit20[20] = {
  92.                 "zero",
  93.                 "one",
  94.                 "two",
  95.                 "three",
  96.                 "four",
  97.                 "five",
  98.                 "six",
  99.                 "seven",
  100.                 "eight",
  101.                 "nine",
  102.                 "ten",
  103.                 "eleven",
  104.                 "twelve",
  105.                 "thirteen",
  106.                 "fourteen",
  107.                 "fifteen",
  108.                 "sixteen",
  109.                 "seventeen",
  110.                 "eighteen",
  111.                 "nineteen",
  112.         };
  113.         int index;
  114.         int start;
  115.         int len;
  116.         int tok;

  117.         if (p == NULL || io_index == NULL || o_value == NULL) {
  118.                 return -1;
  119.         }
  120.         index = *io_index;
  121.         if (index < 0) {
  122.                 return -1;
  123.         }
  124.         skip_space(p, &index);
  125.         if (get_word(p, &index, &start, &len) == 0) {
  126.                 tok = get_token(p + start, len, digit20, 20);
  127.                 if (tok != -1) {
  128.                         *o_value = tok;
  129.                         *io_index = index;
  130.                         return 0;
  131.                 }
  132.         }
  133.         return -1;
  134. }

  135. int get_english_digit_decade(const char *p, int *io_index, int *o_value)
  136. {
  137.         static const char *decades[8] = {
  138.                 "twenty",
  139.                 "thirty",
  140.                 "forty",
  141.                 "fifty",
  142.                 "sixty",
  143.                 "seventy",
  144.                 "eighty",
  145.                 "ninety",
  146.         };
  147.         int index;
  148.         int start, len;
  149.         int value;
  150.         int retn;

  151.         if (p == NULL || io_index == NULL || o_value == NULL) {
  152.                 return -1;
  153.         }
  154.         index = *io_index;
  155.         if (index < 0) {
  156.                 return -1;
  157.         }
  158.         skip_space(p, &index);
  159.         if (get_word(p, &index, &start, &len) == 0) {
  160.                 retn = get_token(p + start, len, decades, 8);
  161.                 if (retn != -1) {
  162.                         value = retn * 10 + 20;
  163.                         *o_value = value;
  164.                         *io_index = index;
  165.                         return 0;
  166.                 }
  167.         }
  168.         return -1;
  169. }

  170. int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
  171. {
  172.         int index;
  173.         int value;
  174.         int digit;
  175.         int decade_yes;

  176.         if (p == NULL || io_index == NULL || o_value == NULL) {
  177.                 return -1;
  178.         }
  179.         index = *io_index;
  180.         if (index < 0) {
  181.                 return -1;
  182.         }
  183.         decade_yes = 0;
  184.         if (get_english_digit_decade(p, &index, &value) == -1) {
  185.                 value = 0;
  186.         }else {
  187.                 decade_yes = 1;
  188.         }
  189.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  190.                 if (decade_yes && digit == 0) {
  191.                         return -1;
  192.                 }
  193.                 value += digit;
  194.         }else {
  195.                 if (!decade_yes) {
  196.                         return -1;
  197.                 }
  198.         }
  199.         *o_value = value;
  200.         *io_index = index;
  201.         return 0;
  202. }

  203. int get_digit_base(const char *p, int *io_index, int *o_base)
  204. {
  205.         static const char *more[] = {
  206.                 "hundred",
  207.                 "thousand",
  208.                 "million",
  209.                 "billion",
  210.         };
  211.         static const int base[] = {
  212.                 100,
  213.                 1000,
  214.                 1000000,
  215.                 1000000000,
  216.         };
  217.         int index;
  218.         int start,len;
  219.         int retn;

  220.         if (p == NULL || io_index == NULL || o_base == NULL) {
  221.                 return -1;
  222.         }
  223.         index = *io_index;
  224.         if (index < 0) {
  225.                 return -1;
  226.         }
  227.         skip_space(p, &index);
  228.         if (get_word(p, &index, &start, &len) == 0) {
  229.                 retn = get_token(p + start, len, more, 4);
  230.                 if (retn != -1) {
  231.                         *o_base = base[retn];
  232.                         *io_index = index;
  233.                         return 0;
  234.                 }
  235.         }
  236.         return -1;
  237. }

  238. int get_english_digit(const char *p, int *io_index, int *o_value)
  239. {
  240.         int index;
  241.         int value;
  242.         int sum;
  243.         int base;

  244.         if (p == NULL || io_index == NULL || o_value == NULL) {
  245.                 return -1;
  246.         }
  247.         index = *io_index;
  248.         if (index < 0) {
  249.                 return -1;
  250.         }
  251.         sum = 0;
  252.         for (;;) {
  253.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  254.                         if (sum > 0 && value == 0) {
  255.                                 return -1;
  256.                         }
  257.                         sum += value;
  258.                         if (get_digit_base(p, &index, &base) == 0) {
  259.                                 if (sum == 0) {
  260.                                         return -1;
  261.                                 }
  262.                                 sum *= base;
  263.                                 if (skip_word(p, &index, "and") == 0) {
  264.                                         continue;
  265.                                 }
  266.                         }
  267.                         *o_value = sum;
  268.                         *io_index = index;
  269.                         return 0;
  270.                 }else if (sum == 0) {
  271.                         if (skip_word(p, &index, "a") == 0) {
  272.                                 if (get_digit_base(p, &index, &base) == 0) {
  273.                                         sum = base;
  274.                                         if (skip_word(p, &index, "and") == 0) {
  275.                                                 continue;
  276.                                         }
  277.                                         *o_value = sum;
  278.                                         *io_index = index;
  279.                                         return 0;
  280.                                 }
  281.                         }
  282.                 }
  283.                 return -1;
  284.         }
  285. }

  286. int get_operator1(const char *p, int *io_index, int *o_op)
  287. {
  288.         static const char *op_list[] = {
  289.                 "positive",
  290.                 "+",
  291.                 "negative",
  292.                 "-",
  293.         };
  294.         int index;
  295.         int start, len;
  296.         int retn;
  297.        
  298.         if (p == NULL || io_index == NULL || o_op == NULL) {
  299.                 return -1;
  300.         }
  301.         index = *io_index;
  302.         if (index < 0) {
  303.                 return -1;
  304.         }
  305.         skip_space(p, &index);
  306.         if (get_word(p, &index, &start, &len) == 0) {
  307.                 retn = get_token(p + start, len, op_list, 8);
  308.                 if (retn != -1) {
  309.                         *o_op = retn / 2;
  310.                         *io_index = index;
  311.                         return 0;
  312.                 }
  313.         }
  314.         return -1;
  315. }

  316. int get_operator2(const char *p, int *io_index, int *o_op)
  317. {
  318.         static const char *op_list[] = {
  319.                 "plus",
  320.                 "+",
  321.                 "minus",
  322.                 "-",
  323.                 "multiply",
  324.                 "*",
  325.                 "divide",
  326.                 "/",
  327.         };
  328.         int index;
  329.         int start, len;
  330.         int retn;

  331.         if (p == NULL || io_index == NULL || o_op == NULL) {
  332.                 return -1;
  333.         }
  334.         index = *io_index;
  335.         if (index < 0) {
  336.                 return -1;
  337.         }
  338.         skip_space(p, &index);
  339.         if (get_word(p, &index, &start, &len) == 0) {
  340.                 retn = get_token(p + start, len, op_list, 8);
  341.                 if (retn != -1) {
  342.                         if ((retn & 1) == 0) {
  343.                                 skip_word(p, &index, "with");
  344.                         }
  345.                         *o_op = retn / 2;
  346.                         *io_index = index;
  347.                         return 0;
  348.                 }
  349.         }
  350.         return -1;
  351. }

  352. int get_number(const char *p, int *io_index, int *o_value)
  353. {
  354.         int index;
  355.         int value;

  356.         if (p == NULL || io_index == NULL || o_value == NULL) {
  357.                 return -1;
  358.         }
  359.         index = *io_index;
  360.         if (index < 0) {
  361.                 return -1;
  362.         }
  363.         skip_space(p, &index);
  364.         if (isdigit(p[index])) {
  365.                 value = 0;
  366.                 do {
  367.                         value = value * 10 + p[index] - '0';
  368.                         index++;
  369.                 }while (isdigit(p[index]));
  370.                 *o_value = value;
  371.                 *io_index = index;
  372.                 return 0;
  373.         }
  374.         return -1;
  375. }

  376. int get_digit(const char *p, int *io_index, int *o_value)
  377. {
  378.         int index;
  379.         int value;

  380.         if (p == NULL || io_index == NULL || o_value == NULL) {
  381.                 return -1;
  382.         }
  383.         index = *io_index;
  384.         if (index < 0) {
  385.                 return -1;
  386.         }
  387.         if (get_english_digit(p, &index, &value) == 0
  388.                 || get_number(p, &index, &value) == 0) {
  389.                 *o_value = value;
  390.                 *io_index = index;
  391.                 return 0;
  392.         }
  393.         return -1;
  394. }

  395. int get_oprand(const char *p, int *io_index, int *o_value)
  396. {
  397.         int index;
  398.         int op;
  399.         int d1;
  400.         int result;

  401.         if (p == NULL || io_index == NULL || o_value == NULL) {
  402.                 return -1;
  403.         }
  404.         index = *io_index;
  405.         if (index < 0) {
  406.                 return -1;
  407.         }
  408.         /* one oprand operation */
  409.         if (get_operator1(p, &index, &op) == 0) {
  410.                 if (get_digit(p, &index, &d1) != 0) {
  411.                         return -1;
  412.                 }
  413.                 switch (op) {
  414.                 case 0:
  415.                         result = d1;
  416.                         break;
  417.                 case 1:
  418.                         result = -d1;
  419.                         break;
  420.                 default:
  421.                         return -1;
  422.                 }
  423.         }else {
  424.                 if (get_digit(p, &index, &result) != 0) {
  425.                         return -1;
  426.                 }
  427.         }
  428.         *o_value = result;
  429.         *io_index = index;
  430.         return 0;
  431. }

  432. int main(void)
  433. {
  434.         char cmd_line[1024];
  435.         int op; /* operator */
  436.         int d1, d2; /* oprand number */
  437.         int result; /* store the expression result */
  438.         int index;

  439.         puts("English Caculator\n");
  440.         puts("Please enter an expression");
  441.         puts("CTRL-Z to exit");
  442.         for (;;) {
  443.                 printf("\n: ");
  444.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  445.                         return 0;
  446.                 }
  447.                 index = 0;
  448.                 if (get_oprand(cmd_line, &index, &result) == -1) {
  449.                         printf("Invalid Expression\n");
  450.                         continue;
  451.                 }
  452.                 /* conjunction operation */
  453.                 for (;;) {
  454.                         /* two oprands operation */
  455.                         d1 = result;
  456.                         if (get_operator2(cmd_line, &index, &op) != 0) {
  457.                                 printf("%d\n", result);
  458.                                 break; /* end of conjunction */
  459.                         }
  460.                         if (get_oprand(cmd_line, &index, &d2) == -1) {
  461.                                 printf("Invalid Expression\n");
  462.                                 break;
  463.                         }
  464.                         switch (op) {
  465.                         case 0:
  466.                                 result = d1 + d2;
  467.                                 break;
  468.                         case 1:
  469.                                 result = d1 - d2;
  470.                                 break;
  471.                         case 2:
  472.                                 result = d1 * d2;
  473.                                 break;
  474.                         case 3:
  475.                                 result = d1 / d2;
  476.                                 break;
  477.                         default:
  478.                                 printf("unknown operator\n");
  479.                                 continue;
  480.                         }
  481.                 }
  482.         }
  483. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
14 [报告]
发表于 2011-08-09 15:50 |只看该作者
调整输出,以适应命令行重定向输入。可输入表达式文件。

  1. /* eng_cac.c */

  2. /* english caculator */

  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>

  6. int skip_space(const char *p, int *io_index)
  7. {
  8.         int index;

  9.         if (p == NULL || io_index == NULL) {
  10.                 return -1;
  11.         }
  12.         index = *io_index;
  13.         if (index < 0) {
  14.                 return -1;
  15.         }
  16.         if (!isspace(p[index])) {
  17.                 return -1;
  18.         }
  19.         do {
  20.                 ++index;
  21.         }while (isspace(p[index]));
  22.         *io_index = index;
  23.         return 0;
  24. }

  25. int get_word(const char *p, int *io_index, int *o_start, int *o_len)
  26. {
  27.         int index;

  28.         if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
  29.                 return -1;
  30.         }
  31.         index = *io_index;
  32.         if (index < 0) {
  33.                 return -1;
  34.         }
  35.         if (isalpha(p[index])) {
  36.                 do {
  37.                         ++index;
  38.                 }while (isalpha(p[index]));
  39.                 *o_start = *io_index;
  40.                 *o_len = index - *io_index;
  41.                 *io_index = index;
  42.                 return 0;
  43.         }else if (ispunct(p[index])) {
  44.                 ++index;
  45.                 *o_start = *io_index;
  46.                 *o_len = 1;
  47.                 *io_index = index;
  48.                 return 0;
  49.         }else {
  50.                 return -1;
  51.         }
  52. }

  53. int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
  54. {
  55.         int i;

  56.         if (tok == NULL || tok_tab == NULL) {
  57.                 return -1;
  58.         }
  59.         if (len <= 0 || tab_len <= 0) {
  60.                 return -1;
  61.         }
  62.         for (i = 0; i < tab_len; ++i) {
  63.                 if (strncmp(tok, tok_tab[i], len) == 0) {
  64.                         return i;
  65.                 }
  66.         }
  67.         return -1;
  68. }

  69. int skip_word(const char *p, int *io_index, const char *s)
  70. {
  71.         int index;
  72.         int start, len;

  73.         if (p == NULL || io_index == NULL || s == NULL) {
  74.                 return -1;
  75.         }
  76.         index = *io_index;
  77.         if (index < 0) {
  78.                 return -1;
  79.         }
  80.         skip_space(p, &index);
  81.         if (get_word(p, &index, &start, &len) == 0) {
  82.                 if (strncmp(p + start, s, len) == 0) {
  83.                         *io_index = index;
  84.                         return 0;
  85.                 }
  86.         }
  87.         return -1;
  88. }

  89. int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
  90. {
  91.         static const char *digit20[20] = {
  92.                 "zero",
  93.                 "one",
  94.                 "two",
  95.                 "three",
  96.                 "four",
  97.                 "five",
  98.                 "six",
  99.                 "seven",
  100.                 "eight",
  101.                 "nine",
  102.                 "ten",
  103.                 "eleven",
  104.                 "twelve",
  105.                 "thirteen",
  106.                 "fourteen",
  107.                 "fifteen",
  108.                 "sixteen",
  109.                 "seventeen",
  110.                 "eighteen",
  111.                 "nineteen",
  112.         };
  113.         int index;
  114.         int start;
  115.         int len;
  116.         int tok;

  117.         if (p == NULL || io_index == NULL || o_value == NULL) {
  118.                 return -1;
  119.         }
  120.         index = *io_index;
  121.         if (index < 0) {
  122.                 return -1;
  123.         }
  124.         skip_space(p, &index);
  125.         if (get_word(p, &index, &start, &len) == 0) {
  126.                 tok = get_token(p + start, len, digit20, 20);
  127.                 if (tok != -1) {
  128.                         *o_value = tok;
  129.                         *io_index = index;
  130.                         return 0;
  131.                 }
  132.         }
  133.         return -1;
  134. }

  135. int get_english_digit_decade(const char *p, int *io_index, int *o_value)
  136. {
  137.         static const char *decades[8] = {
  138.                 "twenty",
  139.                 "thirty",
  140.                 "forty",
  141.                 "fifty",
  142.                 "sixty",
  143.                 "seventy",
  144.                 "eighty",
  145.                 "ninety",
  146.         };
  147.         int index;
  148.         int start, len;
  149.         int value;
  150.         int retn;

  151.         if (p == NULL || io_index == NULL || o_value == NULL) {
  152.                 return -1;
  153.         }
  154.         index = *io_index;
  155.         if (index < 0) {
  156.                 return -1;
  157.         }
  158.         skip_space(p, &index);
  159.         if (get_word(p, &index, &start, &len) == 0) {
  160.                 retn = get_token(p + start, len, decades, 8);
  161.                 if (retn != -1) {
  162.                         value = retn * 10 + 20;
  163.                         *o_value = value;
  164.                         *io_index = index;
  165.                         return 0;
  166.                 }
  167.         }
  168.         return -1;
  169. }

  170. int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
  171. {
  172.         int index;
  173.         int value;
  174.         int digit;
  175.         int decade_yes;

  176.         if (p == NULL || io_index == NULL || o_value == NULL) {
  177.                 return -1;
  178.         }
  179.         index = *io_index;
  180.         if (index < 0) {
  181.                 return -1;
  182.         }
  183.         decade_yes = 0;
  184.         if (get_english_digit_decade(p, &index, &value) == -1) {
  185.                 value = 0;
  186.         }else {
  187.                 decade_yes = 1;
  188.         }
  189.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  190.                 if (decade_yes && digit == 0) {
  191.                         return -1;
  192.                 }
  193.                 value += digit;
  194.         }else {
  195.                 if (!decade_yes) {
  196.                         return -1;
  197.                 }
  198.         }
  199.         *o_value = value;
  200.         *io_index = index;
  201.         return 0;
  202. }

  203. int get_digit_base(const char *p, int *io_index, int *o_base)
  204. {
  205.         static const char *more[] = {
  206.                 "hundred",
  207.                 "thousand",
  208.                 "million",
  209.                 "billion",
  210.         };
  211.         static const int base[] = {
  212.                 100,
  213.                 1000,
  214.                 1000000,
  215.                 1000000000,
  216.         };
  217.         int index;
  218.         int start,len;
  219.         int retn;

  220.         if (p == NULL || io_index == NULL || o_base == NULL) {
  221.                 return -1;
  222.         }
  223.         index = *io_index;
  224.         if (index < 0) {
  225.                 return -1;
  226.         }
  227.         skip_space(p, &index);
  228.         if (get_word(p, &index, &start, &len) == 0) {
  229.                 retn = get_token(p + start, len, more, 4);
  230.                 if (retn != -1) {
  231.                         *o_base = base[retn];
  232.                         *io_index = index;
  233.                         return 0;
  234.                 }
  235.         }
  236.         return -1;
  237. }

  238. int get_english_digit(const char *p, int *io_index, int *o_value)
  239. {
  240.         int index;
  241.         int value;
  242.         int sum;
  243.         int base;

  244.         if (p == NULL || io_index == NULL || o_value == NULL) {
  245.                 return -1;
  246.         }
  247.         index = *io_index;
  248.         if (index < 0) {
  249.                 return -1;
  250.         }
  251.         sum = 0;
  252.         for (;;) {
  253.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  254.                         if (sum > 0 && value == 0) {
  255.                                 return -1;
  256.                         }
  257.                         sum += value;
  258.                         if (get_digit_base(p, &index, &base) == 0) {
  259.                                 if (sum == 0) {
  260.                                         return -1;
  261.                                 }
  262.                                 sum *= base;
  263.                                 if (skip_word(p, &index, "and") == 0) {
  264.                                         continue;
  265.                                 }
  266.                         }
  267.                         *o_value = sum;
  268.                         *io_index = index;
  269.                         return 0;
  270.                 }else if (sum == 0) {
  271.                         if (skip_word(p, &index, "a") == 0) {
  272.                                 if (get_digit_base(p, &index, &base) == 0) {
  273.                                         sum = base;
  274.                                         if (skip_word(p, &index, "and") == 0) {
  275.                                                 continue;
  276.                                         }
  277.                                         *o_value = sum;
  278.                                         *io_index = index;
  279.                                         return 0;
  280.                                 }
  281.                         }
  282.                 }
  283.                 return -1;
  284.         }
  285. }

  286. int get_operator1(const char *p, int *io_index, int *o_op)
  287. {
  288.         static const char *op_list[] = {
  289.                 "positive",
  290.                 "+",
  291.                 "negative",
  292.                 "-",
  293.         };
  294.         int index;
  295.         int start, len;
  296.         int retn;
  297.        
  298.         if (p == NULL || io_index == NULL || o_op == NULL) {
  299.                 return -1;
  300.         }
  301.         index = *io_index;
  302.         if (index < 0) {
  303.                 return -1;
  304.         }
  305.         skip_space(p, &index);
  306.         if (get_word(p, &index, &start, &len) == 0) {
  307.                 retn = get_token(p + start, len, op_list, 8);
  308.                 if (retn != -1) {
  309.                         *o_op = retn / 2;
  310.                         *io_index = index;
  311.                         return 0;
  312.                 }
  313.         }
  314.         return -1;
  315. }

  316. int get_operator2(const char *p, int *io_index, int *o_op)
  317. {
  318.         static const char *op_list[] = {
  319.                 "plus",
  320.                 "+",
  321.                 "minus",
  322.                 "-",
  323.                 "multiply",
  324.                 "*",
  325.                 "divide",
  326.                 "/",
  327.         };
  328.         int index;
  329.         int start, len;
  330.         int retn;

  331.         if (p == NULL || io_index == NULL || o_op == NULL) {
  332.                 return -1;
  333.         }
  334.         index = *io_index;
  335.         if (index < 0) {
  336.                 return -1;
  337.         }
  338.         skip_space(p, &index);
  339.         if (get_word(p, &index, &start, &len) == 0) {
  340.                 retn = get_token(p + start, len, op_list, 8);
  341.                 if (retn != -1) {
  342.                         if ((retn & 1) == 0) {
  343.                                 skip_word(p, &index, "with");
  344.                         }
  345.                         *o_op = retn / 2;
  346.                         *io_index = index;
  347.                         return 0;
  348.                 }
  349.         }
  350.         return -1;
  351. }

  352. int get_number(const char *p, int *io_index, int *o_value)
  353. {
  354.         int index;
  355.         int value;

  356.         if (p == NULL || io_index == NULL || o_value == NULL) {
  357.                 return -1;
  358.         }
  359.         index = *io_index;
  360.         if (index < 0) {
  361.                 return -1;
  362.         }
  363.         skip_space(p, &index);
  364.         if (isdigit(p[index])) {
  365.                 value = 0;
  366.                 do {
  367.                         value = value * 10 + p[index] - '0';
  368.                         index++;
  369.                 }while (isdigit(p[index]));
  370.                 *o_value = value;
  371.                 *io_index = index;
  372.                 return 0;
  373.         }
  374.         return -1;
  375. }

  376. int get_digit(const char *p, int *io_index, int *o_value)
  377. {
  378.         int index;
  379.         int value;

  380.         if (p == NULL || io_index == NULL || o_value == NULL) {
  381.                 return -1;
  382.         }
  383.         index = *io_index;
  384.         if (index < 0) {
  385.                 return -1;
  386.         }
  387.         if (get_english_digit(p, &index, &value) == 0
  388.                 || get_number(p, &index, &value) == 0) {
  389.                 *o_value = value;
  390.                 *io_index = index;
  391.                 return 0;
  392.         }
  393.         return -1;
  394. }

  395. int get_oprand(const char *p, int *io_index, int *o_value)
  396. {
  397.         int index;
  398.         int op;
  399.         int d1;
  400.         int result;

  401.         if (p == NULL || io_index == NULL || o_value == NULL) {
  402.                 return -1;
  403.         }
  404.         index = *io_index;
  405.         if (index < 0) {
  406.                 return -1;
  407.         }
  408.         /* one oprand operation */
  409.         if (get_operator1(p, &index, &op) == 0) {
  410.                 if (get_digit(p, &index, &d1) != 0) {
  411.                         return -1;
  412.                 }
  413.                 switch (op) {
  414.                 case 0:
  415.                         result = d1;
  416.                         break;
  417.                 case 1:
  418.                         result = -d1;
  419.                         break;
  420.                 default:
  421.                         return -1;
  422.                 }
  423.         }else {
  424.                 if (get_digit(p, &index, &result) != 0) {
  425.                         return -1;
  426.                 }
  427.         }
  428.         *o_value = result;
  429.         *io_index = index;
  430.         return 0;
  431. }

  432. int strrtrim(char *p)
  433. {
  434.         int len;

  435.         if (p == NULL) {
  436.                 return -1;
  437.         }
  438.         len = strlen(p);
  439.         if (len > 0) {
  440.                 if (isspace(p[len - 1])) {
  441.                         do {
  442.                                 --len;
  443.                         }while(len >= 0 && isspace(p[len]));
  444.                         p[len + 1] = '\0';
  445.                 }
  446.         }
  447.         return 0;
  448. }

  449. int strtrim(char *p)
  450. {
  451.         int i;

  452.         if (p == NULL) {
  453.                 return -1;
  454.         }
  455.         for (i = 0; p[i] != '\0'; ++i) {
  456.                 if (!isspace(p[i])) {
  457.                         break;
  458.                 }
  459.         }
  460.         strcpy(p, p + i);
  461.         return 0;
  462. }

  463. int main(void)
  464. {
  465.         char cmd_line[1024];
  466.         int op; /* operator */
  467.         int d1, d2; /* oprand number */
  468.         int result; /* store the expression result */
  469.         int index;

  470.         puts("English Caculator\n");
  471.         puts("Enter an expression");
  472.         puts("CTRL-Z to exit\n");
  473.         for (;;) {
  474.                 printf(": ");
  475.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  476.                         return 0;
  477.                 }
  478.                 strrtrim(cmd_line);
  479.                 strtrim(cmd_line);
  480.                 index = 0;
  481.                 if (get_oprand(cmd_line, &index, &result) == -1) {
  482.                         printf("'%s' = E, Invalid Expression\n", cmd_line);
  483.                         continue;
  484.                 }
  485.                 /* conjunction operation */
  486.                 for (;;) {
  487.                         /* two oprands operation */
  488.                         d1 = result;
  489.                         if (get_operator2(cmd_line, &index, &op) != 0) {
  490.                                 printf("'%s' = %d\n", cmd_line, result);
  491.                                 break; /* end of conjunction */
  492.                         }
  493.                         if (get_oprand(cmd_line, &index, &d2) == -1) {
  494.                                 printf("'%s' = E, Invalid Expression\n", cmd_line);
  495.                                 break;
  496.                         }
  497.                         switch (op) {
  498.                         case 0:
  499.                                 result = d1 + d2;
  500.                                 break;
  501.                         case 1:
  502.                                 result = d1 - d2;
  503.                                 break;
  504.                         case 2:
  505.                                 result = d1 * d2;
  506.                                 break;
  507.                         case 3:
  508.                                 result = d1 / d2;
  509.                                 break;
  510.                         default:
  511.                                 printf("'%s' = E, Unknown Operator \n", cmd_line);
  512.                                 continue;
  513.                         }
  514.                 }
  515.         }
  516. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
15 [报告]
发表于 2011-08-09 15:57 |只看该作者
小改动

  1. /* eng_cac.c */

  2. /* english caculator */

  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>

  6. int skip_space(const char *p, int *io_index)
  7. {
  8.         int index;

  9.         if (p == NULL || io_index == NULL) {
  10.                 return -1;
  11.         }
  12.         index = *io_index;
  13.         if (index < 0) {
  14.                 return -1;
  15.         }
  16.         if (!isspace(p[index])) {
  17.                 return -1;
  18.         }
  19.         do {
  20.                 ++index;
  21.         }while (isspace(p[index]));
  22.         *io_index = index;
  23.         return 0;
  24. }

  25. int get_word(const char *p, int *io_index, int *o_start, int *o_len)
  26. {
  27.         int index;

  28.         if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
  29.                 return -1;
  30.         }
  31.         index = *io_index;
  32.         if (index < 0) {
  33.                 return -1;
  34.         }
  35.         if (isalpha(p[index])) {
  36.                 do {
  37.                         ++index;
  38.                 }while (isalpha(p[index]));
  39.                 *o_start = *io_index;
  40.                 *o_len = index - *io_index;
  41.                 *io_index = index;
  42.                 return 0;
  43.         }else if (ispunct(p[index])) {
  44.                 ++index;
  45.                 *o_start = *io_index;
  46.                 *o_len = 1;
  47.                 *io_index = index;
  48.                 return 0;
  49.         }else {
  50.                 return -1;
  51.         }
  52. }

  53. int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
  54. {
  55.         int i;

  56.         if (tok == NULL || tok_tab == NULL) {
  57.                 return -1;
  58.         }
  59.         if (len <= 0 || tab_len <= 0) {
  60.                 return -1;
  61.         }
  62.         for (i = 0; i < tab_len; ++i) {
  63.                 if (strncmp(tok, tok_tab[i], len) == 0) {
  64.                         return i;
  65.                 }
  66.         }
  67.         return -1;
  68. }

  69. int skip_word(const char *p, int *io_index, const char *s)
  70. {
  71.         int index;
  72.         int start, len;

  73.         if (p == NULL || io_index == NULL || s == NULL) {
  74.                 return -1;
  75.         }
  76.         index = *io_index;
  77.         if (index < 0) {
  78.                 return -1;
  79.         }
  80.         skip_space(p, &index);
  81.         if (get_word(p, &index, &start, &len) == 0) {
  82.                 if (strncmp(p + start, s, len) == 0) {
  83.                         *io_index = index;
  84.                         return 0;
  85.                 }
  86.         }
  87.         return -1;
  88. }

  89. int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
  90. {
  91.         static const char *digit20[20] = {
  92.                 "zero",
  93.                 "one",
  94.                 "two",
  95.                 "three",
  96.                 "four",
  97.                 "five",
  98.                 "six",
  99.                 "seven",
  100.                 "eight",
  101.                 "nine",
  102.                 "ten",
  103.                 "eleven",
  104.                 "twelve",
  105.                 "thirteen",
  106.                 "fourteen",
  107.                 "fifteen",
  108.                 "sixteen",
  109.                 "seventeen",
  110.                 "eighteen",
  111.                 "nineteen",
  112.         };
  113.         int index;
  114.         int start;
  115.         int len;
  116.         int tok;

  117.         if (p == NULL || io_index == NULL || o_value == NULL) {
  118.                 return -1;
  119.         }
  120.         index = *io_index;
  121.         if (index < 0) {
  122.                 return -1;
  123.         }
  124.         skip_space(p, &index);
  125.         if (get_word(p, &index, &start, &len) == 0) {
  126.                 tok = get_token(p + start, len, digit20, 20);
  127.                 if (tok != -1) {
  128.                         *o_value = tok;
  129.                         *io_index = index;
  130.                         return 0;
  131.                 }
  132.         }
  133.         return -1;
  134. }

  135. int get_english_digit_decade(const char *p, int *io_index, int *o_value)
  136. {
  137.         static const char *decades[8] = {
  138.                 "twenty",
  139.                 "thirty",
  140.                 "forty",
  141.                 "fifty",
  142.                 "sixty",
  143.                 "seventy",
  144.                 "eighty",
  145.                 "ninety",
  146.         };
  147.         int index;
  148.         int start, len;
  149.         int value;
  150.         int retn;

  151.         if (p == NULL || io_index == NULL || o_value == NULL) {
  152.                 return -1;
  153.         }
  154.         index = *io_index;
  155.         if (index < 0) {
  156.                 return -1;
  157.         }
  158.         skip_space(p, &index);
  159.         if (get_word(p, &index, &start, &len) == 0) {
  160.                 retn = get_token(p + start, len, decades, 8);
  161.                 if (retn != -1) {
  162.                         value = retn * 10 + 20;
  163.                         *o_value = value;
  164.                         *io_index = index;
  165.                         return 0;
  166.                 }
  167.         }
  168.         return -1;
  169. }

  170. int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
  171. {
  172.         int index;
  173.         int value;
  174.         int digit;
  175.         int decade_yes;

  176.         if (p == NULL || io_index == NULL || o_value == NULL) {
  177.                 return -1;
  178.         }
  179.         index = *io_index;
  180.         if (index < 0) {
  181.                 return -1;
  182.         }
  183.         decade_yes = 0;
  184.         if (get_english_digit_decade(p, &index, &value) == -1) {
  185.                 value = 0;
  186.         }else {
  187.                 decade_yes = 1;
  188.         }
  189.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  190.                 if (decade_yes && digit == 0) {
  191.                         return -1;
  192.                 }
  193.                 value += digit;
  194.         }else {
  195.                 if (!decade_yes) {
  196.                         return -1;
  197.                 }
  198.         }
  199.         *o_value = value;
  200.         *io_index = index;
  201.         return 0;
  202. }

  203. int get_digit_base(const char *p, int *io_index, int *o_base)
  204. {
  205.         static const char *more[] = {
  206.                 "hundred",
  207.                 "thousand",
  208.                 "million",
  209.                 "billion",
  210.         };
  211.         static const int base[] = {
  212.                 100,
  213.                 1000,
  214.                 1000000,
  215.                 1000000000,
  216.         };
  217.         int index;
  218.         int start,len;
  219.         int retn;

  220.         if (p == NULL || io_index == NULL || o_base == NULL) {
  221.                 return -1;
  222.         }
  223.         index = *io_index;
  224.         if (index < 0) {
  225.                 return -1;
  226.         }
  227.         skip_space(p, &index);
  228.         if (get_word(p, &index, &start, &len) == 0) {
  229.                 retn = get_token(p + start, len, more, 4);
  230.                 if (retn != -1) {
  231.                         *o_base = base[retn];
  232.                         *io_index = index;
  233.                         return 0;
  234.                 }
  235.         }
  236.         return -1;
  237. }

  238. int get_english_digit(const char *p, int *io_index, int *o_value)
  239. {
  240.         int index;
  241.         int value;
  242.         int sum;
  243.         int base;

  244.         if (p == NULL || io_index == NULL || o_value == NULL) {
  245.                 return -1;
  246.         }
  247.         index = *io_index;
  248.         if (index < 0) {
  249.                 return -1;
  250.         }
  251.         sum = 0;
  252.         for (;;) {
  253.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  254.                         if (sum > 0 && value == 0) {
  255.                                 return -1;
  256.                         }
  257.                         sum += value;
  258.                         if (get_digit_base(p, &index, &base) == 0) {
  259.                                 if (sum == 0) {
  260.                                         return -1;
  261.                                 }
  262.                                 sum *= base;
  263.                                 if (skip_word(p, &index, "and") == 0) {
  264.                                         continue;
  265.                                 }
  266.                         }
  267.                         *o_value = sum;
  268.                         *io_index = index;
  269.                         return 0;
  270.                 }else if (sum == 0) {
  271.                         if (skip_word(p, &index, "a") == 0) {
  272.                                 if (get_digit_base(p, &index, &base) == 0) {
  273.                                         sum = base;
  274.                                         if (skip_word(p, &index, "and") == 0) {
  275.                                                 continue;
  276.                                         }
  277.                                         *o_value = sum;
  278.                                         *io_index = index;
  279.                                         return 0;
  280.                                 }
  281.                         }
  282.                 }
  283.                 return -1;
  284.         }
  285. }

  286. int get_operator1(const char *p, int *io_index, int *o_op)
  287. {
  288.         static const char *op_list[] = {
  289.                 "positive",
  290.                 "+",
  291.                 "negative",
  292.                 "-",
  293.         };
  294.         int index;
  295.         int start, len;
  296.         int retn;
  297.        
  298.         if (p == NULL || io_index == NULL || o_op == NULL) {
  299.                 return -1;
  300.         }
  301.         index = *io_index;
  302.         if (index < 0) {
  303.                 return -1;
  304.         }
  305.         skip_space(p, &index);
  306.         if (get_word(p, &index, &start, &len) == 0) {
  307.                 retn = get_token(p + start, len, op_list, 8);
  308.                 if (retn != -1) {
  309.                         *o_op = retn / 2;
  310.                         *io_index = index;
  311.                         return 0;
  312.                 }
  313.         }
  314.         return -1;
  315. }

  316. int get_operator2(const char *p, int *io_index, int *o_op)
  317. {
  318.         static const char *op_list[] = {
  319.                 "plus",
  320.                 "+",
  321.                 "minus",
  322.                 "-",
  323.                 "multiply",
  324.                 "*",
  325.                 "divide",
  326.                 "/",
  327.         };
  328.         int index;
  329.         int start, len;
  330.         int retn;

  331.         if (p == NULL || io_index == NULL || o_op == NULL) {
  332.                 return -1;
  333.         }
  334.         index = *io_index;
  335.         if (index < 0) {
  336.                 return -1;
  337.         }
  338.         skip_space(p, &index);
  339.         if (get_word(p, &index, &start, &len) == 0) {
  340.                 retn = get_token(p + start, len, op_list, 8);
  341.                 if (retn != -1) {
  342.                         if ((retn & 1) == 0) {
  343.                                 skip_word(p, &index, "with");
  344.                         }
  345.                         *o_op = retn / 2;
  346.                         *io_index = index;
  347.                         return 0;
  348.                 }
  349.         }
  350.         return -1;
  351. }

  352. int get_number(const char *p, int *io_index, int *o_value)
  353. {
  354.         int index;
  355.         int value;

  356.         if (p == NULL || io_index == NULL || o_value == NULL) {
  357.                 return -1;
  358.         }
  359.         index = *io_index;
  360.         if (index < 0) {
  361.                 return -1;
  362.         }
  363.         skip_space(p, &index);
  364.         if (isdigit(p[index])) {
  365.                 value = 0;
  366.                 do {
  367.                         value = value * 10 + p[index] - '0';
  368.                         index++;
  369.                 }while (isdigit(p[index]));
  370.                 *o_value = value;
  371.                 *io_index = index;
  372.                 return 0;
  373.         }
  374.         return -1;
  375. }

  376. int get_digit(const char *p, int *io_index, int *o_value)
  377. {
  378.         int index;
  379.         int value;

  380.         if (p == NULL || io_index == NULL || o_value == NULL) {
  381.                 return -1;
  382.         }
  383.         index = *io_index;
  384.         if (index < 0) {
  385.                 return -1;
  386.         }
  387.         if (get_english_digit(p, &index, &value) == 0
  388.                 || get_number(p, &index, &value) == 0) {
  389.                 *o_value = value;
  390.                 *io_index = index;
  391.                 return 0;
  392.         }
  393.         return -1;
  394. }

  395. int get_oprand(const char *p, int *io_index, int *o_value)
  396. {
  397.         int index;
  398.         int op;
  399.         int d1;
  400.         int result;

  401.         if (p == NULL || io_index == NULL || o_value == NULL) {
  402.                 return -1;
  403.         }
  404.         index = *io_index;
  405.         if (index < 0) {
  406.                 return -1;
  407.         }
  408.         /* one oprand operation */
  409.         if (get_operator1(p, &index, &op) == 0) {
  410.                 if (get_digit(p, &index, &d1) != 0) {
  411.                         return -1;
  412.                 }
  413.                 switch (op) {
  414.                 case 0:
  415.                         result = d1;
  416.                         break;
  417.                 case 1:
  418.                         result = -d1;
  419.                         break;
  420.                 default:
  421.                         return -1;
  422.                 }
  423.         }else {
  424.                 if (get_digit(p, &index, &result) != 0) {
  425.                         return -1;
  426.                 }
  427.         }
  428.         *o_value = result;
  429.         *io_index = index;
  430.         return 0;
  431. }

  432. int strrtrim(char *p)
  433. {
  434.         int len;

  435.         if (p == NULL) {
  436.                 return -1;
  437.         }
  438.         len = strlen(p);
  439.         if (len > 0) {
  440.                 if (isspace(p[len - 1])) {
  441.                         do {
  442.                                 --len;
  443.                         }while(len >= 0 && isspace(p[len]));
  444.                         p[len + 1] = '\0';
  445.                 }
  446.         }
  447.         return 0;
  448. }

  449. int strtrim(char *p)
  450. {
  451.         int i;

  452.         if (p == NULL) {
  453.                 return -1;
  454.         }
  455.         for (i = 0; p[i] != '\0'; ++i) {
  456.                 if (!isspace(p[i])) {
  457.                         break;
  458.                 }
  459.         }
  460.         strcpy(p, p + i);
  461.         return 0;
  462. }

  463. int caculate(const char *line, int *o_value)
  464. {
  465.         int op; /* operator */
  466.         int d1, d2; /* oprand number */
  467.         int result; /* store the expression result */
  468.         int index;

  469.         if (line == NULL || o_value == NULL) {
  470.                 return -1;
  471.         }
  472.         index = 0;
  473.         if (get_oprand(line, &index, &result) == -1) {
  474.                 return -1;
  475.         }
  476.         /* conjunction operation */
  477.         for (;;) {
  478.                 /* two oprands operation */
  479.                 d1 = result;
  480.                 if (get_operator2(line, &index, &op) != 0) {
  481.                         *o_value = result;
  482.                         return 0; /* end of conjunction */
  483.                 }
  484.                 if (get_oprand(line, &index, &d2) == -1) {
  485.                         return -1;
  486.                 }
  487.                 switch (op) {
  488.                 case 0:
  489.                         result = d1 + d2;
  490.                         break;
  491.                 case 1:
  492.                         result = d1 - d2;
  493.                         break;
  494.                 case 2:
  495.                         result = d1 * d2;
  496.                         break;
  497.                 case 3:
  498.                         result = d1 / d2;
  499.                         break;
  500.                 default:
  501.                         return -1;
  502.                 }
  503.         }
  504. }

  505. int main(void)
  506. {
  507.         char cmd_line[1024];
  508.         int result;

  509.         puts("English Caculator\n");
  510.         puts("Enter an expression");
  511.         puts("CTRL-Z to exit\n");
  512.         for (;;) {
  513.                 printf(": ");
  514.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  515.                         return 0;
  516.                 }
  517.                 strrtrim(cmd_line);
  518.                 strtrim(cmd_line);
  519.                 if (caculate(cmd_line, &result) == 0) {
  520.                         printf("'%s' = %d\n", cmd_line, result);
  521.                 }else {
  522.                         printf("'%s' = E, Invalid Expression\n", cmd_line);
  523.                 }
  524.         }
  525. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
16 [报告]
发表于 2011-08-09 16:08 |只看该作者
增加零除错误判断。

  1. /* eng_cac.c */

  2. /* english caculator */

  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>

  6. int skip_space(const char *p, int *io_index)
  7. {
  8.         int index;

  9.         if (p == NULL || io_index == NULL) {
  10.                 return -1;
  11.         }
  12.         index = *io_index;
  13.         if (index < 0) {
  14.                 return -1;
  15.         }
  16.         if (!isspace(p[index])) {
  17.                 return -1;
  18.         }
  19.         do {
  20.                 ++index;
  21.         }while (isspace(p[index]));
  22.         *io_index = index;
  23.         return 0;
  24. }

  25. int get_word(const char *p, int *io_index, int *o_start, int *o_len)
  26. {
  27.         int index;

  28.         if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
  29.                 return -1;
  30.         }
  31.         index = *io_index;
  32.         if (index < 0) {
  33.                 return -1;
  34.         }
  35.         if (isalpha(p[index])) {
  36.                 do {
  37.                         ++index;
  38.                 }while (isalpha(p[index]));
  39.                 *o_start = *io_index;
  40.                 *o_len = index - *io_index;
  41.                 *io_index = index;
  42.                 return 0;
  43.         }else if (ispunct(p[index])) {
  44.                 ++index;
  45.                 *o_start = *io_index;
  46.                 *o_len = 1;
  47.                 *io_index = index;
  48.                 return 0;
  49.         }else {
  50.                 return -1;
  51.         }
  52. }

  53. int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
  54. {
  55.         int i;

  56.         if (tok == NULL || tok_tab == NULL) {
  57.                 return -1;
  58.         }
  59.         if (len <= 0 || tab_len <= 0) {
  60.                 return -1;
  61.         }
  62.         for (i = 0; i < tab_len; ++i) {
  63.                 if (strncmp(tok, tok_tab[i], len) == 0) {
  64.                         return i;
  65.                 }
  66.         }
  67.         return -1;
  68. }

  69. int skip_word(const char *p, int *io_index, const char *s)
  70. {
  71.         int index;
  72.         int start, len;

  73.         if (p == NULL || io_index == NULL || s == NULL) {
  74.                 return -1;
  75.         }
  76.         index = *io_index;
  77.         if (index < 0) {
  78.                 return -1;
  79.         }
  80.         skip_space(p, &index);
  81.         if (get_word(p, &index, &start, &len) == 0) {
  82.                 if (strncmp(p + start, s, len) == 0) {
  83.                         *io_index = index;
  84.                         return 0;
  85.                 }
  86.         }
  87.         return -1;
  88. }

  89. int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
  90. {
  91.         static const char *digit20[20] = {
  92.                 "zero",
  93.                 "one",
  94.                 "two",
  95.                 "three",
  96.                 "four",
  97.                 "five",
  98.                 "six",
  99.                 "seven",
  100.                 "eight",
  101.                 "nine",
  102.                 "ten",
  103.                 "eleven",
  104.                 "twelve",
  105.                 "thirteen",
  106.                 "fourteen",
  107.                 "fifteen",
  108.                 "sixteen",
  109.                 "seventeen",
  110.                 "eighteen",
  111.                 "nineteen",
  112.         };
  113.         int index;
  114.         int start;
  115.         int len;
  116.         int tok;

  117.         if (p == NULL || io_index == NULL || o_value == NULL) {
  118.                 return -1;
  119.         }
  120.         index = *io_index;
  121.         if (index < 0) {
  122.                 return -1;
  123.         }
  124.         skip_space(p, &index);
  125.         if (get_word(p, &index, &start, &len) == 0) {
  126.                 tok = get_token(p + start, len, digit20, 20);
  127.                 if (tok != -1) {
  128.                         *o_value = tok;
  129.                         *io_index = index;
  130.                         return 0;
  131.                 }
  132.         }
  133.         return -1;
  134. }

  135. int get_english_digit_decade(const char *p, int *io_index, int *o_value)
  136. {
  137.         static const char *decades[8] = {
  138.                 "twenty",
  139.                 "thirty",
  140.                 "forty",
  141.                 "fifty",
  142.                 "sixty",
  143.                 "seventy",
  144.                 "eighty",
  145.                 "ninety",
  146.         };
  147.         int index;
  148.         int start, len;
  149.         int value;
  150.         int retn;

  151.         if (p == NULL || io_index == NULL || o_value == NULL) {
  152.                 return -1;
  153.         }
  154.         index = *io_index;
  155.         if (index < 0) {
  156.                 return -1;
  157.         }
  158.         skip_space(p, &index);
  159.         if (get_word(p, &index, &start, &len) == 0) {
  160.                 retn = get_token(p + start, len, decades, 8);
  161.                 if (retn != -1) {
  162.                         value = retn * 10 + 20;
  163.                         *o_value = value;
  164.                         *io_index = index;
  165.                         return 0;
  166.                 }
  167.         }
  168.         return -1;
  169. }

  170. int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
  171. {
  172.         int index;
  173.         int value;
  174.         int digit;
  175.         int decade_yes;

  176.         if (p == NULL || io_index == NULL || o_value == NULL) {
  177.                 return -1;
  178.         }
  179.         index = *io_index;
  180.         if (index < 0) {
  181.                 return -1;
  182.         }
  183.         decade_yes = 0;
  184.         if (get_english_digit_decade(p, &index, &value) == -1) {
  185.                 value = 0;
  186.         }else {
  187.                 decade_yes = 1;
  188.         }
  189.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  190.                 if (decade_yes && digit == 0) {
  191.                         return -1;
  192.                 }
  193.                 value += digit;
  194.         }else {
  195.                 if (!decade_yes) {
  196.                         return -1;
  197.                 }
  198.         }
  199.         *o_value = value;
  200.         *io_index = index;
  201.         return 0;
  202. }

  203. int get_digit_base(const char *p, int *io_index, int *o_base)
  204. {
  205.         static const char *more[] = {
  206.                 "hundred",
  207.                 "thousand",
  208.                 "million",
  209.                 "billion",
  210.         };
  211.         static const int base[] = {
  212.                 100,
  213.                 1000,
  214.                 1000000,
  215.                 1000000000,
  216.         };
  217.         int index;
  218.         int start,len;
  219.         int retn;

  220.         if (p == NULL || io_index == NULL || o_base == NULL) {
  221.                 return -1;
  222.         }
  223.         index = *io_index;
  224.         if (index < 0) {
  225.                 return -1;
  226.         }
  227.         skip_space(p, &index);
  228.         if (get_word(p, &index, &start, &len) == 0) {
  229.                 retn = get_token(p + start, len, more, 4);
  230.                 if (retn != -1) {
  231.                         *o_base = base[retn];
  232.                         *io_index = index;
  233.                         return 0;
  234.                 }
  235.         }
  236.         return -1;
  237. }

  238. int get_english_digit(const char *p, int *io_index, int *o_value)
  239. {
  240.         int index;
  241.         int value;
  242.         int sum;
  243.         int base;

  244.         if (p == NULL || io_index == NULL || o_value == NULL) {
  245.                 return -1;
  246.         }
  247.         index = *io_index;
  248.         if (index < 0) {
  249.                 return -1;
  250.         }
  251.         sum = 0;
  252.         for (;;) {
  253.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  254.                         if (sum > 0 && value == 0) {
  255.                                 return -1;
  256.                         }
  257.                         sum += value;
  258.                         if (get_digit_base(p, &index, &base) == 0) {
  259.                                 if (sum == 0) {
  260.                                         return -1;
  261.                                 }
  262.                                 sum *= base;
  263.                                 if (skip_word(p, &index, "and") == 0) {
  264.                                         continue;
  265.                                 }
  266.                         }
  267.                         *o_value = sum;
  268.                         *io_index = index;
  269.                         return 0;
  270.                 }else if (sum == 0) {
  271.                         if (skip_word(p, &index, "a") == 0) {
  272.                                 if (get_digit_base(p, &index, &base) == 0) {
  273.                                         sum = base;
  274.                                         if (skip_word(p, &index, "and") == 0) {
  275.                                                 continue;
  276.                                         }
  277.                                         *o_value = sum;
  278.                                         *io_index = index;
  279.                                         return 0;
  280.                                 }
  281.                         }
  282.                 }
  283.                 return -1;
  284.         }
  285. }

  286. int get_operator1(const char *p, int *io_index, int *o_op)
  287. {
  288.         static const char *op_list[] = {
  289.                 "positive",
  290.                 "+",
  291.                 "negative",
  292.                 "-",
  293.         };
  294.         int index;
  295.         int start, len;
  296.         int retn;
  297.        
  298.         if (p == NULL || io_index == NULL || o_op == NULL) {
  299.                 return -1;
  300.         }
  301.         index = *io_index;
  302.         if (index < 0) {
  303.                 return -1;
  304.         }
  305.         skip_space(p, &index);
  306.         if (get_word(p, &index, &start, &len) == 0) {
  307.                 retn = get_token(p + start, len, op_list, 8);
  308.                 if (retn != -1) {
  309.                         *o_op = retn / 2;
  310.                         *io_index = index;
  311.                         return 0;
  312.                 }
  313.         }
  314.         return -1;
  315. }

  316. int get_operator2(const char *p, int *io_index, int *o_op)
  317. {
  318.         static const char *op_list[] = {
  319.                 "plus",
  320.                 "+",
  321.                 "minus",
  322.                 "-",
  323.                 "multiply",
  324.                 "*",
  325.                 "divide",
  326.                 "/",
  327.         };
  328.         int index;
  329.         int start, len;
  330.         int retn;

  331.         if (p == NULL || io_index == NULL || o_op == NULL) {
  332.                 return -1;
  333.         }
  334.         index = *io_index;
  335.         if (index < 0) {
  336.                 return -1;
  337.         }
  338.         skip_space(p, &index);
  339.         if (get_word(p, &index, &start, &len) == 0) {
  340.                 retn = get_token(p + start, len, op_list, 8);
  341.                 if (retn != -1) {
  342.                         if ((retn & 1) == 0) {
  343.                                 skip_word(p, &index, "with");
  344.                         }
  345.                         *o_op = retn / 2;
  346.                         *io_index = index;
  347.                         return 0;
  348.                 }
  349.         }
  350.         return -1;
  351. }

  352. int get_number(const char *p, int *io_index, int *o_value)
  353. {
  354.         int index;
  355.         int value;

  356.         if (p == NULL || io_index == NULL || o_value == NULL) {
  357.                 return -1;
  358.         }
  359.         index = *io_index;
  360.         if (index < 0) {
  361.                 return -1;
  362.         }
  363.         skip_space(p, &index);
  364.         if (isdigit(p[index])) {
  365.                 value = 0;
  366.                 do {
  367.                         value = value * 10 + p[index] - '0';
  368.                         index++;
  369.                 }while (isdigit(p[index]));
  370.                 *o_value = value;
  371.                 *io_index = index;
  372.                 return 0;
  373.         }
  374.         return -1;
  375. }

  376. int get_digit(const char *p, int *io_index, int *o_value)
  377. {
  378.         int index;
  379.         int value;

  380.         if (p == NULL || io_index == NULL || o_value == NULL) {
  381.                 return -1;
  382.         }
  383.         index = *io_index;
  384.         if (index < 0) {
  385.                 return -1;
  386.         }
  387.         if (get_english_digit(p, &index, &value) == 0
  388.                 || get_number(p, &index, &value) == 0) {
  389.                 *o_value = value;
  390.                 *io_index = index;
  391.                 return 0;
  392.         }
  393.         return -1;
  394. }

  395. int get_oprand(const char *p, int *io_index, int *o_value)
  396. {
  397.         int index;
  398.         int op;
  399.         int d1;
  400.         int result;

  401.         if (p == NULL || io_index == NULL || o_value == NULL) {
  402.                 return -1;
  403.         }
  404.         index = *io_index;
  405.         if (index < 0) {
  406.                 return -1;
  407.         }
  408.         /* one oprand operation */
  409.         if (get_operator1(p, &index, &op) == 0) {
  410.                 if (get_digit(p, &index, &d1) != 0) {
  411.                         return -1;
  412.                 }
  413.                 switch (op) {
  414.                 case 0:
  415.                         result = d1;
  416.                         break;
  417.                 case 1:
  418.                         result = -d1;
  419.                         break;
  420.                 default:
  421.                         return -1;
  422.                 }
  423.         }else {
  424.                 if (get_digit(p, &index, &result) != 0) {
  425.                         return -1;
  426.                 }
  427.         }
  428.         *o_value = result;
  429.         *io_index = index;
  430.         return 0;
  431. }

  432. int strrtrim(char *p)
  433. {
  434.         int len;

  435.         if (p == NULL) {
  436.                 return -1;
  437.         }
  438.         len = strlen(p);
  439.         if (len > 0) {
  440.                 if (isspace(p[len - 1])) {
  441.                         do {
  442.                                 --len;
  443.                         }while(len >= 0 && isspace(p[len]));
  444.                         p[len + 1] = '\0';
  445.                 }
  446.         }
  447.         return 0;
  448. }

  449. int strtrim(char *p)
  450. {
  451.         int i;

  452.         if (p == NULL) {
  453.                 return -1;
  454.         }
  455.         for (i = 0; p[i] != '\0'; ++i) {
  456.                 if (!isspace(p[i])) {
  457.                         break;
  458.                 }
  459.         }
  460.         strcpy(p, p + i);
  461.         return 0;
  462. }

  463. int caculate(const char *line, int *o_value)
  464. {
  465.         int op; /* operator */
  466.         int d1, d2; /* oprand number */
  467.         int result; /* store the expression result */
  468.         int index;

  469.         if (line == NULL || o_value == NULL) {
  470.                 return -1;
  471.         }
  472.         index = 0;
  473.         if (get_oprand(line, &index, &result) == -1) {
  474.                 return -1;
  475.         }
  476.         /* conjunction operation */
  477.         for (;;) {
  478.                 /* two oprands operation */
  479.                 d1 = result;
  480.                 if (get_operator2(line, &index, &op) != 0) {
  481.                         *o_value = result;
  482.                         return 0; /* end of conjunction */
  483.                 }
  484.                 if (get_oprand(line, &index, &d2) == -1) {
  485.                         return -1;
  486.                 }
  487.                 switch (op) {
  488.                 case 0:
  489.                         result = d1 + d2;
  490.                         break;
  491.                 case 1:
  492.                         result = d1 - d2;
  493.                         break;
  494.                 case 2:
  495.                         result = d1 * d2;
  496.                         break;
  497.                 case 3:
  498.                         if (d2 == 0) {
  499.                                 return -1;
  500.                         }
  501.                         result = d1 / d2;
  502.                         break;
  503.                 default:
  504.                         return -1;
  505.                 }
  506.         }
  507. }

  508. int main(void)
  509. {
  510.         char cmd_line[1024];
  511.         int result;

  512.         puts("English Caculator\n");
  513.         puts("Enter an expression");
  514.         puts("CTRL-Z to exit\n");
  515.         for (;;) {
  516.                 printf(": ");
  517.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  518.                         return 0;
  519.                 }
  520.                 strrtrim(cmd_line);
  521.                 strtrim(cmd_line);
  522.                 if (caculate(cmd_line, &result) == 0) {
  523.                         printf("'%s' = %d\n", cmd_line, result);
  524.                 }else {
  525.                         printf("'%s' = E, Invalid Expression\n", cmd_line);
  526.                 }
  527.         }
  528. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
17 [报告]
发表于 2011-08-09 17:35 |只看该作者
增加支持“a hundred thousand”类型的解析。

  1. /* eng_cac.c */

  2. /* english caculator */

  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>

  6. int skip_space(const char *p, int *io_index)
  7. {
  8.         int index;

  9.         if (p == NULL || io_index == NULL) {
  10.                 return -1;
  11.         }
  12.         index = *io_index;
  13.         if (index < 0) {
  14.                 return -1;
  15.         }
  16.         if (!isspace(p[index])) {
  17.                 return -1;
  18.         }
  19.         do {
  20.                 ++index;
  21.         }while (isspace(p[index]));
  22.         *io_index = index;
  23.         return 0;
  24. }

  25. int get_word(const char *p, int *io_index, int *o_start, int *o_len)
  26. {
  27.         int index;

  28.         if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
  29.                 return -1;
  30.         }
  31.         index = *io_index;
  32.         if (index < 0) {
  33.                 return -1;
  34.         }
  35.         if (isalpha(p[index])) {
  36.                 do {
  37.                         ++index;
  38.                 }while (isalpha(p[index]));
  39.                 *o_start = *io_index;
  40.                 *o_len = index - *io_index;
  41.                 *io_index = index;
  42.                 return 0;
  43.         }else if (ispunct(p[index])) {
  44.                 ++index;
  45.                 *o_start = *io_index;
  46.                 *o_len = 1;
  47.                 *io_index = index;
  48.                 return 0;
  49.         }else {
  50.                 return -1;
  51.         }
  52. }

  53. int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
  54. {
  55.         int i;

  56.         if (tok == NULL || tok_tab == NULL) {
  57.                 return -1;
  58.         }
  59.         if (len <= 0 || tab_len <= 0) {
  60.                 return -1;
  61.         }
  62.         for (i = 0; i < tab_len; ++i) {
  63.                 if (strncmp(tok, tok_tab[i], len) == 0) {
  64.                         return i;
  65.                 }
  66.         }
  67.         return -1;
  68. }

  69. int skip_word(const char *p, int *io_index, const char *s)
  70. {
  71.         int index;
  72.         int start, len;

  73.         if (p == NULL || io_index == NULL || s == NULL) {
  74.                 return -1;
  75.         }
  76.         index = *io_index;
  77.         if (index < 0) {
  78.                 return -1;
  79.         }
  80.         skip_space(p, &index);
  81.         if (get_word(p, &index, &start, &len) == 0) {
  82.                 if (strncmp(p + start, s, len) == 0) {
  83.                         *io_index = index;
  84.                         return 0;
  85.                 }
  86.         }
  87.         return -1;
  88. }

  89. int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
  90. {
  91.         static const char *digit20[20] = {
  92.                 "zero",
  93.                 "one",
  94.                 "two",
  95.                 "three",
  96.                 "four",
  97.                 "five",
  98.                 "six",
  99.                 "seven",
  100.                 "eight",
  101.                 "nine",
  102.                 "ten",
  103.                 "eleven",
  104.                 "twelve",
  105.                 "thirteen",
  106.                 "fourteen",
  107.                 "fifteen",
  108.                 "sixteen",
  109.                 "seventeen",
  110.                 "eighteen",
  111.                 "nineteen",
  112.         };
  113.         int index;
  114.         int start;
  115.         int len;
  116.         int tok;

  117.         if (p == NULL || io_index == NULL || o_value == NULL) {
  118.                 return -1;
  119.         }
  120.         index = *io_index;
  121.         if (index < 0) {
  122.                 return -1;
  123.         }
  124.         skip_space(p, &index);
  125.         if (get_word(p, &index, &start, &len) == 0) {
  126.                 tok = get_token(p + start, len, digit20, 20);
  127.                 if (tok != -1) {
  128.                         *o_value = tok;
  129.                         *io_index = index;
  130.                         return 0;
  131.                 }
  132.         }
  133.         return -1;
  134. }

  135. int get_english_digit_decade(const char *p, int *io_index, int *o_value)
  136. {
  137.         static const char *decades[8] = {
  138.                 "twenty",
  139.                 "thirty",
  140.                 "forty",
  141.                 "fifty",
  142.                 "sixty",
  143.                 "seventy",
  144.                 "eighty",
  145.                 "ninety",
  146.         };
  147.         int index;
  148.         int start, len;
  149.         int value;
  150.         int retn;

  151.         if (p == NULL || io_index == NULL || o_value == NULL) {
  152.                 return -1;
  153.         }
  154.         index = *io_index;
  155.         if (index < 0) {
  156.                 return -1;
  157.         }
  158.         skip_space(p, &index);
  159.         if (get_word(p, &index, &start, &len) == 0) {
  160.                 retn = get_token(p + start, len, decades, 8);
  161.                 if (retn != -1) {
  162.                         value = retn * 10 + 20;
  163.                         *o_value = value;
  164.                         *io_index = index;
  165.                         return 0;
  166.                 }
  167.         }
  168.         return -1;
  169. }

  170. int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
  171. {
  172.         int index;
  173.         int value;
  174.         int digit;
  175.         int decade_yes;

  176.         if (p == NULL || io_index == NULL || o_value == NULL) {
  177.                 return -1;
  178.         }
  179.         index = *io_index;
  180.         if (index < 0) {
  181.                 return -1;
  182.         }
  183.         decade_yes = 0;
  184.         if (get_english_digit_decade(p, &index, &value) == -1) {
  185.                 value = 0;
  186.         }else {
  187.                 decade_yes = 1;
  188.         }
  189.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  190.                 if (decade_yes && digit == 0) {
  191.                         return -1;
  192.                 }
  193.                 value += digit;
  194.         }else {
  195.                 if (!decade_yes) {
  196.                         return -1;
  197.                 }
  198.         }
  199.         *o_value = value;
  200.         *io_index = index;
  201.         return 0;
  202. }

  203. int get_english_digit_base(const char *p, int *io_index, int *o_base)
  204. {
  205.         static const char *more[] = {
  206.                 "hundred",
  207.                 "thousand",
  208.                 "million",
  209.                 "billion",
  210.         };
  211.         static const int base[] = {
  212.                 100,
  213.                 1000,
  214.                 1000000,
  215.                 1000000000,
  216.         };
  217.         int index;
  218.         int start,len;
  219.         int retn;

  220.         if (p == NULL || io_index == NULL || o_base == NULL) {
  221.                 return -1;
  222.         }
  223.         index = *io_index;
  224.         if (index < 0) {
  225.                 return -1;
  226.         }
  227.         skip_space(p, &index);
  228.         if (get_word(p, &index, &start, &len) == 0) {
  229.                 retn = get_token(p + start, len, more, 4);
  230.                 if (retn != -1) {
  231.                         *o_base = base[retn];
  232.                         *io_index = index;
  233.                         return 0;
  234.                 }
  235.         }
  236.         return -1;
  237. }

  238. int get_english_digit(const char *p, int *io_index, int *o_value)
  239. {
  240.         int index;
  241.         int value;
  242.         int sum;
  243.         int base;

  244.         if (p == NULL || io_index == NULL || o_value == NULL) {
  245.                 return -1;
  246.         }
  247.         index = *io_index;
  248.         if (index < 0) {
  249.                 return -1;
  250.         }
  251.         sum = 0;
  252.         for (;;) {
  253.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  254.                         if (sum > 0 && value == 0) {
  255.                                 return -1;
  256.                         }
  257.                         sum += value;
  258.                         while (get_english_digit_base(p, &index, &base) == 0) {
  259.                                 if (sum == 0) {
  260.                                         return -1;
  261.                                 }
  262.                                 sum *= base;
  263.                         }
  264.                         if (skip_word(p, &index, "and") == 0) {
  265.                                 continue;
  266.                         }
  267.                         break;
  268.                 }else if (sum == 0) {
  269.                         if (skip_word(p, &index, "a") == 0) {
  270.                                 sum = 1;
  271.                                 while (get_english_digit_base(p, &index, &base) == 0) {
  272.                                         sum *= base;
  273.                                 }
  274.                                 if (skip_word(p, &index, "and") == 0) {
  275.                                         continue;
  276.                                 }
  277.                                 break;
  278.                         }
  279.                 }
  280.                 return -1;
  281.         }
  282.         *o_value = sum;
  283.         *io_index = index;
  284.         return 0;
  285. }

  286. int get_operator1(const char *p, int *io_index, int *o_op)
  287. {
  288.         static const char *op_list[] = {
  289.                 "positive",
  290.                 "+",
  291.                 "negative",
  292.                 "-",
  293.         };
  294.         int index;
  295.         int start, len;
  296.         int retn;
  297.        
  298.         if (p == NULL || io_index == NULL || o_op == NULL) {
  299.                 return -1;
  300.         }
  301.         index = *io_index;
  302.         if (index < 0) {
  303.                 return -1;
  304.         }
  305.         skip_space(p, &index);
  306.         if (get_word(p, &index, &start, &len) == 0) {
  307.                 retn = get_token(p + start, len, op_list, 8);
  308.                 if (retn != -1) {
  309.                         *o_op = retn / 2;
  310.                         *io_index = index;
  311.                         return 0;
  312.                 }
  313.         }
  314.         return -1;
  315. }

  316. int get_operator2(const char *p, int *io_index, int *o_op)
  317. {
  318.         static const char *op_list[] = {
  319.                 "plus",
  320.                 "+",
  321.                 "minus",
  322.                 "-",
  323.                 "multiply",
  324.                 "*",
  325.                 "divide",
  326.                 "/",
  327.         };
  328.         int index;
  329.         int start, len;
  330.         int retn;

  331.         if (p == NULL || io_index == NULL || o_op == NULL) {
  332.                 return -1;
  333.         }
  334.         index = *io_index;
  335.         if (index < 0) {
  336.                 return -1;
  337.         }
  338.         skip_space(p, &index);
  339.         if (get_word(p, &index, &start, &len) == 0) {
  340.                 retn = get_token(p + start, len, op_list, 8);
  341.                 if (retn != -1) {
  342.                         if ((retn & 1) == 0) {
  343.                                 skip_word(p, &index, "with");
  344.                         }
  345.                         *o_op = retn / 2;
  346.                         *io_index = index;
  347.                         return 0;
  348.                 }
  349.         }
  350.         return -1;
  351. }

  352. int get_number(const char *p, int *io_index, int *o_value)
  353. {
  354.         int index;
  355.         int value;

  356.         if (p == NULL || io_index == NULL || o_value == NULL) {
  357.                 return -1;
  358.         }
  359.         index = *io_index;
  360.         if (index < 0) {
  361.                 return -1;
  362.         }
  363.         skip_space(p, &index);
  364.         if (isdigit(p[index])) {
  365.                 value = 0;
  366.                 do {
  367.                         value = value * 10 + p[index] - '0';
  368.                         index++;
  369.                 }while (isdigit(p[index]));
  370.                 *o_value = value;
  371.                 *io_index = index;
  372.                 return 0;
  373.         }
  374.         return -1;
  375. }

  376. int get_digit(const char *p, int *io_index, int *o_value)
  377. {
  378.         int index;
  379.         int value;

  380.         if (p == NULL || io_index == NULL || o_value == NULL) {
  381.                 return -1;
  382.         }
  383.         index = *io_index;
  384.         if (index < 0) {
  385.                 return -1;
  386.         }
  387.         if (get_english_digit(p, &index, &value) == 0
  388.                 || get_number(p, &index, &value) == 0) {
  389.                 *o_value = value;
  390.                 *io_index = index;
  391.                 return 0;
  392.         }
  393.         return -1;
  394. }

  395. int get_oprand(const char *p, int *io_index, int *o_value)
  396. {
  397.         int index;
  398.         int op;
  399.         int d1;
  400.         int result;

  401.         if (p == NULL || io_index == NULL || o_value == NULL) {
  402.                 return -1;
  403.         }
  404.         index = *io_index;
  405.         if (index < 0) {
  406.                 return -1;
  407.         }
  408.         /* one oprand operation */
  409.         if (get_operator1(p, &index, &op) == 0) {
  410.                 if (get_digit(p, &index, &d1) != 0) {
  411.                         return -1;
  412.                 }
  413.                 switch (op) {
  414.                 case 0:
  415.                         result = d1;
  416.                         break;
  417.                 case 1:
  418.                         result = -d1;
  419.                         break;
  420.                 default:
  421.                         return -1;
  422.                 }
  423.         }else {
  424.                 if (get_digit(p, &index, &result) != 0) {
  425.                         return -1;
  426.                 }
  427.         }
  428.         *o_value = result;
  429.         *io_index = index;
  430.         return 0;
  431. }

  432. int strrtrim(char *p)
  433. {
  434.         int len;

  435.         if (p == NULL) {
  436.                 return -1;
  437.         }
  438.         len = strlen(p);
  439.         if (len > 0) {
  440.                 if (isspace(p[len - 1])) {
  441.                         do {
  442.                                 --len;
  443.                         }while(len >= 0 && isspace(p[len]));
  444.                         p[len + 1] = '\0';
  445.                 }
  446.         }
  447.         return 0;
  448. }

  449. int strtrim(char *p)
  450. {
  451.         int i;

  452.         if (p == NULL) {
  453.                 return -1;
  454.         }
  455.         for (i = 0; p[i] != '\0'; ++i) {
  456.                 if (!isspace(p[i])) {
  457.                         break;
  458.                 }
  459.         }
  460.         strcpy(p, p + i);
  461.         return 0;
  462. }

  463. int get_end(const char *p, int *io_index)
  464. {
  465.         int index;

  466.         if (p == NULL || io_index == NULL) {
  467.                 return -1;
  468.         }
  469.         index = *io_index;
  470.         if (index < 0) {
  471.                 return -1;
  472.         }
  473.         skip_space(p, &index);
  474.         if (p[index] == '\0') {
  475.                 *io_index = index;
  476.                 return 0;
  477.         }
  478.         return -1;
  479. }

  480. int caculate(const char *exp, int *o_value)
  481. {
  482.         int op; /* operator */
  483.         int d1, d2; /* oprand number */
  484.         int result; /* store the expression result */
  485.         int index;

  486.         if (exp == NULL || o_value == NULL) {
  487.                 return -1;
  488.         }
  489.         index = 0;
  490.         if (get_oprand(exp, &index, &result) == -1) {
  491.                 return -1;
  492.         }
  493.         /* conjunction operation */
  494.         while (get_end(exp, &index) == -1) {
  495.                 /* two oprands operation */
  496.                 d1 = result;
  497.                 if (get_operator2(exp, &index, &op) == -1) {
  498.                         return -1;
  499.                 }
  500.                 if (get_oprand(exp, &index, &d2) == -1) {
  501.                         return -1;
  502.                 }
  503.                 switch (op) {
  504.                 case 0:
  505.                         result = d1 + d2;
  506.                         break;
  507.                 case 1:
  508.                         result = d1 - d2;
  509.                         break;
  510.                 case 2:
  511.                         result = d1 * d2;
  512.                         break;
  513.                 case 3:
  514.                         if (d2 == 0) {
  515.                                 return -1;
  516.                         }
  517.                         result = d1 / d2;
  518.                         break;
  519.                 default:
  520.                         return -1;
  521.                 }
  522.         }
  523.         *o_value = result;
  524.         return 0; /* end of conjunction */
  525. }

  526. int main(void)
  527. {
  528.         char cmd_line[1024];
  529.         int result;

  530.         puts("English Caculator");
  531.         puts("Enter an expression");
  532.         puts("Ctrl-Z to exit");
  533.         for (;;) {
  534.                 printf(": ");
  535.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  536.                         puts("");
  537.                         return 0;
  538.                 }
  539.                 strrtrim(cmd_line);
  540.                 strtrim(cmd_line);
  541.                 if (caculate(cmd_line, &result) == 0) {
  542.                         printf("\"%s\" = %d\n", cmd_line, result);
  543.                 }else {
  544.                         printf("\"%s\" = E, Invalid Expression\n", cmd_line);
  545.                 }
  546.         }
  547. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
18 [报告]
发表于 2011-08-10 09:53 |只看该作者
增加检测“zero and a hundred”一类的错误语法。

  1. /* eng_cac.c */

  2. /* english caculator */

  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>

  6. int skip_space(const char *p, int *io_index)
  7. {
  8.         int index;

  9.         if (p == NULL || io_index == NULL) {
  10.                 return -1;
  11.         }
  12.         index = *io_index;
  13.         if (index < 0) {
  14.                 return -1;
  15.         }
  16.         if (!isspace(p[index])) {
  17.                 return -1;
  18.         }
  19.         do {
  20.                 ++index;
  21.         }while (isspace(p[index]));
  22.         *io_index = index;
  23.         return 0;
  24. }

  25. int get_word(const char *p, int *io_index, int *o_start, int *o_len)
  26. {
  27.         int index;

  28.         if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
  29.                 return -1;
  30.         }
  31.         index = *io_index;
  32.         if (index < 0) {
  33.                 return -1;
  34.         }
  35.         if (isalpha(p[index])) {
  36.                 do {
  37.                         ++index;
  38.                 }while (isalpha(p[index]));
  39.                 *o_start = *io_index;
  40.                 *o_len = index - *io_index;
  41.                 *io_index = index;
  42.                 return 0;
  43.         }else if (ispunct(p[index])) {
  44.                 ++index;
  45.                 *o_start = *io_index;
  46.                 *o_len = 1;
  47.                 *io_index = index;
  48.                 return 0;
  49.         }else {
  50.                 return -1;
  51.         }
  52. }

  53. int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
  54. {
  55.         int i;

  56.         if (tok == NULL || tok_tab == NULL) {
  57.                 return -1;
  58.         }
  59.         if (len <= 0 || tab_len <= 0) {
  60.                 return -1;
  61.         }
  62.         for (i = 0; i < tab_len; ++i) {
  63.                 if (strncmp(tok, tok_tab[i], len) == 0) {
  64.                         return i;
  65.                 }
  66.         }
  67.         return -1;
  68. }

  69. int skip_word(const char *p, int *io_index, const char *s)
  70. {
  71.         int index;
  72.         int start, len;

  73.         if (p == NULL || io_index == NULL || s == NULL) {
  74.                 return -1;
  75.         }
  76.         index = *io_index;
  77.         if (index < 0) {
  78.                 return -1;
  79.         }
  80.         skip_space(p, &index);
  81.         if (get_word(p, &index, &start, &len) == 0) {
  82.                 if (strncmp(p + start, s, len) == 0) {
  83.                         *io_index = index;
  84.                         return 0;
  85.                 }
  86.         }
  87.         return -1;
  88. }

  89. int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
  90. {
  91.         static const char *digit20[20] = {
  92.                 "zero",
  93.                 "one",
  94.                 "two",
  95.                 "three",
  96.                 "four",
  97.                 "five",
  98.                 "six",
  99.                 "seven",
  100.                 "eight",
  101.                 "nine",
  102.                 "ten",
  103.                 "eleven",
  104.                 "twelve",
  105.                 "thirteen",
  106.                 "fourteen",
  107.                 "fifteen",
  108.                 "sixteen",
  109.                 "seventeen",
  110.                 "eighteen",
  111.                 "nineteen",
  112.         };
  113.         int index;
  114.         int start;
  115.         int len;
  116.         int tok;

  117.         if (p == NULL || io_index == NULL || o_value == NULL) {
  118.                 return -1;
  119.         }
  120.         index = *io_index;
  121.         if (index < 0) {
  122.                 return -1;
  123.         }
  124.         skip_space(p, &index);
  125.         if (get_word(p, &index, &start, &len) == 0) {
  126.                 tok = get_token(p + start, len, digit20, 20);
  127.                 if (tok != -1) {
  128.                         *o_value = tok;
  129.                         *io_index = index;
  130.                         return 0;
  131.                 }
  132.         }
  133.         return -1;
  134. }

  135. int get_english_digit_decade(const char *p, int *io_index, int *o_value)
  136. {
  137.         static const char *decades[8] = {
  138.                 "twenty",
  139.                 "thirty",
  140.                 "forty",
  141.                 "fifty",
  142.                 "sixty",
  143.                 "seventy",
  144.                 "eighty",
  145.                 "ninety",
  146.         };
  147.         int index;
  148.         int start, len;
  149.         int value;
  150.         int retn;

  151.         if (p == NULL || io_index == NULL || o_value == NULL) {
  152.                 return -1;
  153.         }
  154.         index = *io_index;
  155.         if (index < 0) {
  156.                 return -1;
  157.         }
  158.         skip_space(p, &index);
  159.         if (get_word(p, &index, &start, &len) == 0) {
  160.                 retn = get_token(p + start, len, decades, 8);
  161.                 if (retn != -1) {
  162.                         value = retn * 10 + 20;
  163.                         *o_value = value;
  164.                         *io_index = index;
  165.                         return 0;
  166.                 }
  167.         }
  168.         return -1;
  169. }

  170. int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
  171. {
  172.         int index;
  173.         int value;
  174.         int digit;
  175.         int decade_yes;

  176.         if (p == NULL || io_index == NULL || o_value == NULL) {
  177.                 return -1;
  178.         }
  179.         index = *io_index;
  180.         if (index < 0) {
  181.                 return -1;
  182.         }
  183.         decade_yes = 0;
  184.         if (get_english_digit_decade(p, &index, &value) == -1) {
  185.                 value = 0;
  186.         }else {
  187.                 decade_yes = 1;
  188.         }
  189.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  190.                 if (decade_yes && digit == 0) {
  191.                         return -1;
  192.                 }
  193.                 value += digit;
  194.         }else {
  195.                 if (!decade_yes) {
  196.                         return -1;
  197.                 }
  198.         }
  199.         *o_value = value;
  200.         *io_index = index;
  201.         return 0;
  202. }

  203. int get_english_digit_base(const char *p, int *io_index, int *o_base)
  204. {
  205.         static const char *more[] = {
  206.                 "hundred",
  207.                 "thousand",
  208.                 "million",
  209.                 "billion",
  210.         };
  211.         static const int base[] = {
  212.                 100,
  213.                 1000,
  214.                 1000000,
  215.                 1000000000,
  216.         };
  217.         int index;
  218.         int start,len;
  219.         int retn;

  220.         if (p == NULL || io_index == NULL || o_base == NULL) {
  221.                 return -1;
  222.         }
  223.         index = *io_index;
  224.         if (index < 0) {
  225.                 return -1;
  226.         }
  227.         skip_space(p, &index);
  228.         if (get_word(p, &index, &start, &len) == 0) {
  229.                 retn = get_token(p + start, len, more, 4);
  230.                 if (retn != -1) {
  231.                         *o_base = base[retn];
  232.                         *io_index = index;
  233.                         return 0;
  234.                 }
  235.         }
  236.         return -1;
  237. }

  238. int get_english_digit(const char *p, int *io_index, int *o_value)
  239. {
  240.         int index;
  241.         int value;
  242.         int sum;
  243.         int base;

  244.         if (p == NULL || io_index == NULL || o_value == NULL) {
  245.                 return -1;
  246.         }
  247.         index = *io_index;
  248.         if (index < 0) {
  249.                 return -1;
  250.         }
  251.         sum = 0;
  252.         for (;;) {
  253.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  254.                         if (value == 0) {
  255.                                 if (sum > 0) {
  256.                                         return -1;
  257.                                 }
  258.                                 sum = 0;
  259.                                 break;
  260.                         }
  261.                         sum += value;
  262.                         while (get_english_digit_base(p, &index, &base) == 0) {
  263.                                 sum *= base;
  264.                         }
  265.                         if (skip_word(p, &index, "and") == 0) {
  266.                                 continue;
  267.                         }
  268.                         break;
  269.                 }else if (sum == 0) {
  270.                         if (skip_word(p, &index, "a") == 0) {
  271.                                 sum = 1;
  272.                                 while (get_english_digit_base(p, &index, &base) == 0) {
  273.                                         sum *= base;
  274.                                 }
  275.                                 if (skip_word(p, &index, "and") == 0) {
  276.                                         continue;
  277.                                 }
  278.                                 break;
  279.                         }
  280.                 }
  281.                 return -1;
  282.         }
  283.         *o_value = sum;
  284.         *io_index = index;
  285.         return 0;
  286. }

  287. int get_operator1(const char *p, int *io_index, int *o_op)
  288. {
  289.         static const char *op_list[] = {
  290.                 "positive",
  291.                 "+",
  292.                 "negative",
  293.                 "-",
  294.         };
  295.         int index;
  296.         int start, len;
  297.         int retn;
  298.        
  299.         if (p == NULL || io_index == NULL || o_op == NULL) {
  300.                 return -1;
  301.         }
  302.         index = *io_index;
  303.         if (index < 0) {
  304.                 return -1;
  305.         }
  306.         skip_space(p, &index);
  307.         if (get_word(p, &index, &start, &len) == 0) {
  308.                 retn = get_token(p + start, len, op_list, 8);
  309.                 if (retn != -1) {
  310.                         *o_op = retn / 2;
  311.                         *io_index = index;
  312.                         return 0;
  313.                 }
  314.         }
  315.         return -1;
  316. }

  317. int get_operator2(const char *p, int *io_index, int *o_op)
  318. {
  319.         static const char *op_list[] = {
  320.                 "plus",
  321.                 "+",
  322.                 "minus",
  323.                 "-",
  324.                 "multiply",
  325.                 "*",
  326.                 "divide",
  327.                 "/",
  328.         };
  329.         int index;
  330.         int start, len;
  331.         int retn;

  332.         if (p == NULL || io_index == NULL || o_op == NULL) {
  333.                 return -1;
  334.         }
  335.         index = *io_index;
  336.         if (index < 0) {
  337.                 return -1;
  338.         }
  339.         skip_space(p, &index);
  340.         if (get_word(p, &index, &start, &len) == 0) {
  341.                 retn = get_token(p + start, len, op_list, 8);
  342.                 if (retn != -1) {
  343.                         if ((retn & 1) == 0) {
  344.                                 skip_word(p, &index, "with");
  345.                         }
  346.                         *o_op = retn / 2;
  347.                         *io_index = index;
  348.                         return 0;
  349.                 }
  350.         }
  351.         return -1;
  352. }

  353. int get_number(const char *p, int *io_index, int *o_value)
  354. {
  355.         int index;
  356.         int value;

  357.         if (p == NULL || io_index == NULL || o_value == NULL) {
  358.                 return -1;
  359.         }
  360.         index = *io_index;
  361.         if (index < 0) {
  362.                 return -1;
  363.         }
  364.         skip_space(p, &index);
  365.         if (isdigit(p[index])) {
  366.                 value = 0;
  367.                 do {
  368.                         value = value * 10 + p[index] - '0';
  369.                         index++;
  370.                 }while (isdigit(p[index]));
  371.                 *o_value = value;
  372.                 *io_index = index;
  373.                 return 0;
  374.         }
  375.         return -1;
  376. }

  377. int get_digit(const char *p, int *io_index, int *o_value)
  378. {
  379.         int index;
  380.         int value;

  381.         if (p == NULL || io_index == NULL || o_value == NULL) {
  382.                 return -1;
  383.         }
  384.         index = *io_index;
  385.         if (index < 0) {
  386.                 return -1;
  387.         }
  388.         if (get_english_digit(p, &index, &value) == 0
  389.                 || get_number(p, &index, &value) == 0) {
  390.                 *o_value = value;
  391.                 *io_index = index;
  392.                 return 0;
  393.         }
  394.         return -1;
  395. }

  396. int get_oprand(const char *p, int *io_index, int *o_value)
  397. {
  398.         int index;
  399.         int op;
  400.         int d1;
  401.         int result;

  402.         if (p == NULL || io_index == NULL || o_value == NULL) {
  403.                 return -1;
  404.         }
  405.         index = *io_index;
  406.         if (index < 0) {
  407.                 return -1;
  408.         }
  409.         /* one oprand operation */
  410.         if (get_operator1(p, &index, &op) == 0) {
  411.                 if (get_digit(p, &index, &d1) != 0) {
  412.                         return -1;
  413.                 }
  414.                 switch (op) {
  415.                 case 0:
  416.                         result = d1;
  417.                         break;
  418.                 case 1:
  419.                         result = -d1;
  420.                         break;
  421.                 default:
  422.                         return -1;
  423.                 }
  424.         }else {
  425.                 if (get_digit(p, &index, &result) != 0) {
  426.                         return -1;
  427.                 }
  428.         }
  429.         *o_value = result;
  430.         *io_index = index;
  431.         return 0;
  432. }

  433. int strrtrim(char *p)
  434. {
  435.         int len;

  436.         if (p == NULL) {
  437.                 return -1;
  438.         }
  439.         len = strlen(p);
  440.         if (len > 0) {
  441.                 if (isspace(p[len - 1])) {
  442.                         do {
  443.                                 --len;
  444.                         }while(len >= 0 && isspace(p[len]));
  445.                         p[len + 1] = '\0';
  446.                 }
  447.         }
  448.         return 0;
  449. }

  450. int strtrim(char *p)
  451. {
  452.         int i;

  453.         if (p == NULL) {
  454.                 return -1;
  455.         }
  456.         for (i = 0; p[i] != '\0'; ++i) {
  457.                 if (!isspace(p[i])) {
  458.                         break;
  459.                 }
  460.         }
  461.         strcpy(p, p + i);
  462.         return 0;
  463. }

  464. int get_end(const char *p, int *io_index)
  465. {
  466.         int index;

  467.         if (p == NULL || io_index == NULL) {
  468.                 return -1;
  469.         }
  470.         index = *io_index;
  471.         if (index < 0) {
  472.                 return -1;
  473.         }
  474.         skip_space(p, &index);
  475.         if (p[index] == '\0') {
  476.                 *io_index = index;
  477.                 return 0;
  478.         }
  479.         return -1;
  480. }

  481. int caculate(const char *exp, int *o_value)
  482. {
  483.         int op; /* operator */
  484.         int d1, d2; /* oprand number */
  485.         int result; /* store the expression result */
  486.         int index;

  487.         if (exp == NULL || o_value == NULL) {
  488.                 return -1;
  489.         }
  490.         index = 0;
  491.         if (get_oprand(exp, &index, &result) == -1) {
  492.                 return -1;
  493.         }
  494.         /* conjunction operation */
  495.         while (get_end(exp, &index) == -1) {
  496.                 /* two oprands operation */
  497.                 d1 = result;
  498.                 if (get_operator2(exp, &index, &op) == -1) {
  499.                         return -1;
  500.                 }
  501.                 if (get_oprand(exp, &index, &d2) == -1) {
  502.                         return -1;
  503.                 }
  504.                 switch (op) {
  505.                 case 0:
  506.                         result = d1 + d2;
  507.                         break;
  508.                 case 1:
  509.                         result = d1 - d2;
  510.                         break;
  511.                 case 2:
  512.                         result = d1 * d2;
  513.                         break;
  514.                 case 3:
  515.                         if (d2 == 0) {
  516.                                 return -1;
  517.                         }
  518.                         result = d1 / d2;
  519.                         break;
  520.                 default:
  521.                         return -1;
  522.                 }
  523.         }
  524.         *o_value = result;
  525.         return 0; /* end of conjunction */
  526. }

  527. int main(void)
  528. {
  529.         char cmd_line[1024];
  530.         int result;

  531.         puts("English Caculator");
  532.         puts("Enter an expression");
  533.         puts("Ctrl-Z to exit");
  534.         for (;;) {
  535.                 printf(": ");
  536.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  537.                         puts("");
  538.                         return 0;
  539.                 }
  540.                 strrtrim(cmd_line);
  541.                 strtrim(cmd_line);
  542.                 if (caculate(cmd_line, &result) == 0) {
  543.                         printf("\"%s\" = %d\n", cmd_line, result);
  544.                 }else {
  545.                         printf("\"%s\" = E, Invalid Expression\n", cmd_line);
  546.                 }
  547.         }
  548. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
19 [报告]
发表于 2011-08-10 10:10 |只看该作者
更正“nine”和“ninety”相等的错误!!!

  1. /* eng_cac.c */

  2. /* english caculator */

  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>

  6. int skip_space(const char *p, int *io_index)
  7. {
  8.         int index;

  9.         if (p == NULL || io_index == NULL) {
  10.                 return -1;
  11.         }
  12.         index = *io_index;
  13.         if (index < 0) {
  14.                 return -1;
  15.         }
  16.         if (!isspace(p[index])) {
  17.                 return -1;
  18.         }
  19.         do {
  20.                 ++index;
  21.         }while (isspace(p[index]));
  22.         *io_index = index;
  23.         return 0;
  24. }

  25. int get_word(const char *p, int *io_index, int *o_start, int *o_len)
  26. {
  27.         int index;

  28.         if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
  29.                 return -1;
  30.         }
  31.         index = *io_index;
  32.         if (index < 0) {
  33.                 return -1;
  34.         }
  35.         if (isalpha(p[index])) {
  36.                 do {
  37.                         ++index;
  38.                 }while (isalpha(p[index]));
  39.                 *o_start = *io_index;
  40.                 *o_len = index - *io_index;
  41.                 *io_index = index;
  42.                 return 0;
  43.         }else if (ispunct(p[index])) {
  44.                 ++index;
  45.                 *o_start = *io_index;
  46.                 *o_len = 1;
  47.                 *io_index = index;
  48.                 return 0;
  49.         }else {
  50.                 return -1;
  51.         }
  52. }

  53. int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
  54. {
  55.         int tok_len;
  56.         int i;

  57.         if (tok == NULL || tok_tab == NULL) {
  58.                 return -1;
  59.         }
  60.         if (len <= 0 || tab_len <= 0) {
  61.                 return -1;
  62.         }
  63.         for (i = 0; i < tab_len; ++i) {
  64.                 tok_len = strlen(tok_tab[i]);
  65.                 if (len == tok_len && strncmp(tok, tok_tab[i], len) == 0) {
  66.                         return i;
  67.                 }
  68.         }
  69.         return -1;
  70. }

  71. int skip_word(const char *p, int *io_index, const char *s)
  72. {
  73.         int index;
  74.         int start, len;

  75.         if (p == NULL || io_index == NULL || s == NULL) {
  76.                 return -1;
  77.         }
  78.         index = *io_index;
  79.         if (index < 0) {
  80.                 return -1;
  81.         }
  82.         skip_space(p, &index);
  83.         if (get_word(p, &index, &start, &len) == 0) {
  84.                 if (strncmp(p + start, s, len) == 0) {
  85.                         *io_index = index;
  86.                         return 0;
  87.                 }
  88.         }
  89.         return -1;
  90. }

  91. int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
  92. {
  93.         static const char *digit20[20] = {
  94.                 "zero",
  95.                 "one",
  96.                 "two",
  97.                 "three",
  98.                 "four",
  99.                 "five",
  100.                 "six",
  101.                 "seven",
  102.                 "eight",
  103.                 "nine",
  104.                 "ten",
  105.                 "eleven",
  106.                 "twelve",
  107.                 "thirteen",
  108.                 "fourteen",
  109.                 "fifteen",
  110.                 "sixteen",
  111.                 "seventeen",
  112.                 "eighteen",
  113.                 "nineteen",
  114.         };
  115.         int index;
  116.         int start;
  117.         int len;
  118.         int tok;

  119.         if (p == NULL || io_index == NULL || o_value == NULL) {
  120.                 return -1;
  121.         }
  122.         index = *io_index;
  123.         if (index < 0) {
  124.                 return -1;
  125.         }
  126.         skip_space(p, &index);
  127.         if (get_word(p, &index, &start, &len) == 0) {
  128.                 tok = get_token(p + start, len, digit20, 20);
  129.                 if (tok != -1) {
  130.                         *o_value = tok;
  131.                         *io_index = index;
  132.                         return 0;
  133.                 }
  134.         }
  135.         return -1;
  136. }

  137. int get_english_digit_decade(const char *p, int *io_index, int *o_value)
  138. {
  139.         static const char *decades[8] = {
  140.                 "twenty",
  141.                 "thirty",
  142.                 "forty",
  143.                 "fifty",
  144.                 "sixty",
  145.                 "seventy",
  146.                 "eighty",
  147.                 "ninety",
  148.         };
  149.         int index;
  150.         int start, len;
  151.         int value;
  152.         int retn;

  153.         if (p == NULL || io_index == NULL || o_value == NULL) {
  154.                 return -1;
  155.         }
  156.         index = *io_index;
  157.         if (index < 0) {
  158.                 return -1;
  159.         }
  160.         skip_space(p, &index);
  161.         if (get_word(p, &index, &start, &len) == 0) {
  162.                 retn = get_token(p + start, len, decades, 8);
  163.                 if (retn != -1) {
  164.                         value = retn * 10 + 20;
  165.                         *o_value = value;
  166.                         *io_index = index;
  167.                         return 0;
  168.                 }
  169.         }
  170.         return -1;
  171. }

  172. int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
  173. {
  174.         int index;
  175.         int value;
  176.         int digit;
  177.         int decade_yes;

  178.         if (p == NULL || io_index == NULL || o_value == NULL) {
  179.                 return -1;
  180.         }
  181.         index = *io_index;
  182.         if (index < 0) {
  183.                 return -1;
  184.         }
  185.         decade_yes = 0;
  186.         if (get_english_digit_decade(p, &index, &value) == -1) {
  187.                 value = 0;
  188.         }else {
  189.                 decade_yes = 1;
  190.         }
  191.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  192.                 if (decade_yes && digit == 0) {
  193.                         return -1;
  194.                 }
  195.                 value += digit;
  196.         }else {
  197.                 if (!decade_yes) {
  198.                         return -1;
  199.                 }
  200.         }
  201.         *o_value = value;
  202.         *io_index = index;
  203.         return 0;
  204. }

  205. int get_english_digit_base(const char *p, int *io_index, int *o_base)
  206. {
  207.         static const char *more[] = {
  208.                 "hundred",
  209.                 "thousand",
  210.                 "million",
  211.                 "billion",
  212.         };
  213.         static const int base[] = {
  214.                 100,
  215.                 1000,
  216.                 1000000,
  217.                 1000000000,
  218.         };
  219.         int index;
  220.         int start,len;
  221.         int retn;

  222.         if (p == NULL || io_index == NULL || o_base == NULL) {
  223.                 return -1;
  224.         }
  225.         index = *io_index;
  226.         if (index < 0) {
  227.                 return -1;
  228.         }
  229.         skip_space(p, &index);
  230.         if (get_word(p, &index, &start, &len) == 0) {
  231.                 retn = get_token(p + start, len, more, 4);
  232.                 if (retn != -1) {
  233.                         *o_base = base[retn];
  234.                         *io_index = index;
  235.                         return 0;
  236.                 }
  237.         }
  238.         return -1;
  239. }

  240. int get_english_digit(const char *p, int *io_index, int *o_value)
  241. {
  242.         int index;
  243.         int value;
  244.         int sum;
  245.         int base;

  246.         if (p == NULL || io_index == NULL || o_value == NULL) {
  247.                 return -1;
  248.         }
  249.         index = *io_index;
  250.         if (index < 0) {
  251.                 return -1;
  252.         }
  253.         sum = 0;
  254.         for (;;) {
  255.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  256.                         if (value == 0) {
  257.                                 if (sum > 0) {
  258.                                         return -1;
  259.                                 }
  260.                                 sum = 0;
  261.                                 break;
  262.                         }
  263.                         sum += value;
  264.                         while (get_english_digit_base(p, &index, &base) == 0) {
  265.                                 sum *= base;
  266.                         }
  267.                         if (skip_word(p, &index, "and") == 0) {
  268.                                 continue;
  269.                         }
  270.                         break;
  271.                 }else if (sum == 0) {
  272.                         if (skip_word(p, &index, "a") == 0) {
  273.                                 sum = 1;
  274.                                 while (get_english_digit_base(p, &index, &base) == 0) {
  275.                                         sum *= base;
  276.                                 }
  277.                                 if (skip_word(p, &index, "and") == 0) {
  278.                                         continue;
  279.                                 }
  280.                                 break;
  281.                         }
  282.                 }
  283.                 return -1;
  284.         }
  285.         *o_value = sum;
  286.         *io_index = index;
  287.         return 0;
  288. }

  289. int get_operator1(const char *p, int *io_index, int *o_op)
  290. {
  291.         static const char *op_list[] = {
  292.                 "positive",
  293.                 "+",
  294.                 "negative",
  295.                 "-",
  296.         };
  297.         int index;
  298.         int start, len;
  299.         int retn;
  300.        
  301.         if (p == NULL || io_index == NULL || o_op == NULL) {
  302.                 return -1;
  303.         }
  304.         index = *io_index;
  305.         if (index < 0) {
  306.                 return -1;
  307.         }
  308.         skip_space(p, &index);
  309.         if (get_word(p, &index, &start, &len) == 0) {
  310.                 retn = get_token(p + start, len, op_list, 8);
  311.                 if (retn != -1) {
  312.                         *o_op = retn / 2;
  313.                         *io_index = index;
  314.                         return 0;
  315.                 }
  316.         }
  317.         return -1;
  318. }

  319. int get_operator2(const char *p, int *io_index, int *o_op)
  320. {
  321.         static const char *op_list[] = {
  322.                 "plus",
  323.                 "+",
  324.                 "minus",
  325.                 "-",
  326.                 "multiply",
  327.                 "*",
  328.                 "divide",
  329.                 "/",
  330.         };
  331.         int index;
  332.         int start, len;
  333.         int retn;

  334.         if (p == NULL || io_index == NULL || o_op == NULL) {
  335.                 return -1;
  336.         }
  337.         index = *io_index;
  338.         if (index < 0) {
  339.                 return -1;
  340.         }
  341.         skip_space(p, &index);
  342.         if (get_word(p, &index, &start, &len) == 0) {
  343.                 retn = get_token(p + start, len, op_list, 8);
  344.                 if (retn != -1) {
  345.                         if ((retn & 1) == 0) {
  346.                                 skip_word(p, &index, "with");
  347.                         }
  348.                         *o_op = retn / 2;
  349.                         *io_index = index;
  350.                         return 0;
  351.                 }
  352.         }
  353.         return -1;
  354. }

  355. int get_number(const char *p, int *io_index, int *o_value)
  356. {
  357.         int index;
  358.         int value;

  359.         if (p == NULL || io_index == NULL || o_value == NULL) {
  360.                 return -1;
  361.         }
  362.         index = *io_index;
  363.         if (index < 0) {
  364.                 return -1;
  365.         }
  366.         skip_space(p, &index);
  367.         if (isdigit(p[index])) {
  368.                 value = 0;
  369.                 do {
  370.                         value = value * 10 + p[index] - '0';
  371.                         index++;
  372.                 }while (isdigit(p[index]));
  373.                 *o_value = value;
  374.                 *io_index = index;
  375.                 return 0;
  376.         }
  377.         return -1;
  378. }

  379. int get_digit(const char *p, int *io_index, int *o_value)
  380. {
  381.         int index;
  382.         int value;

  383.         if (p == NULL || io_index == NULL || o_value == NULL) {
  384.                 return -1;
  385.         }
  386.         index = *io_index;
  387.         if (index < 0) {
  388.                 return -1;
  389.         }
  390.         if (get_english_digit(p, &index, &value) == 0
  391.                 || get_number(p, &index, &value) == 0) {
  392.                 *o_value = value;
  393.                 *io_index = index;
  394.                 return 0;
  395.         }
  396.         return -1;
  397. }

  398. int get_oprand(const char *p, int *io_index, int *o_value)
  399. {
  400.         int index;
  401.         int op;
  402.         int d1;
  403.         int result;

  404.         if (p == NULL || io_index == NULL || o_value == NULL) {
  405.                 return -1;
  406.         }
  407.         index = *io_index;
  408.         if (index < 0) {
  409.                 return -1;
  410.         }
  411.         /* one oprand operation */
  412.         if (get_operator1(p, &index, &op) == 0) {
  413.                 if (get_digit(p, &index, &d1) != 0) {
  414.                         return -1;
  415.                 }
  416.                 switch (op) {
  417.                 case 0:
  418.                         result = d1;
  419.                         break;
  420.                 case 1:
  421.                         result = -d1;
  422.                         break;
  423.                 default:
  424.                         return -1;
  425.                 }
  426.         }else {
  427.                 if (get_digit(p, &index, &result) != 0) {
  428.                         return -1;
  429.                 }
  430.         }
  431.         *o_value = result;
  432.         *io_index = index;
  433.         return 0;
  434. }

  435. int strrtrim(char *p)
  436. {
  437.         int len;

  438.         if (p == NULL) {
  439.                 return -1;
  440.         }
  441.         len = strlen(p);
  442.         if (len > 0) {
  443.                 if (isspace(p[len - 1])) {
  444.                         do {
  445.                                 --len;
  446.                         }while(len >= 0 && isspace(p[len]));
  447.                         p[len + 1] = '\0';
  448.                 }
  449.         }
  450.         return 0;
  451. }

  452. int strtrim(char *p)
  453. {
  454.         int i;

  455.         if (p == NULL) {
  456.                 return -1;
  457.         }
  458.         for (i = 0; p[i] != '\0'; ++i) {
  459.                 if (!isspace(p[i])) {
  460.                         break;
  461.                 }
  462.         }
  463.         strcpy(p, p + i);
  464.         return 0;
  465. }

  466. int get_end(const char *p, int *io_index)
  467. {
  468.         int index;

  469.         if (p == NULL || io_index == NULL) {
  470.                 return -1;
  471.         }
  472.         index = *io_index;
  473.         if (index < 0) {
  474.                 return -1;
  475.         }
  476.         skip_space(p, &index);
  477.         if (p[index] == '\0') {
  478.                 *io_index = index;
  479.                 return 0;
  480.         }
  481.         return -1;
  482. }

  483. int caculate(const char *exp, int *o_value)
  484. {
  485.         int op; /* operator */
  486.         int d1, d2; /* oprand number */
  487.         int result; /* store the expression result */
  488.         int index;

  489.         if (exp == NULL || o_value == NULL) {
  490.                 return -1;
  491.         }
  492.         index = 0;
  493.         if (get_oprand(exp, &index, &result) == -1) {
  494.                 return -1;
  495.         }
  496.         /* conjunction operation */
  497.         while (get_end(exp, &index) == -1) {
  498.                 /* two oprands operation */
  499.                 d1 = result;
  500.                 if (get_operator2(exp, &index, &op) == -1) {
  501.                         return -1;
  502.                 }
  503.                 if (get_oprand(exp, &index, &d2) == -1) {
  504.                         return -1;
  505.                 }
  506.                 switch (op) {
  507.                 case 0:
  508.                         result = d1 + d2;
  509.                         break;
  510.                 case 1:
  511.                         result = d1 - d2;
  512.                         break;
  513.                 case 2:
  514.                         result = d1 * d2;
  515.                         break;
  516.                 case 3:
  517.                         if (d2 == 0) {
  518.                                 return -1;
  519.                         }
  520.                         result = d1 / d2;
  521.                         break;
  522.                 default:
  523.                         return -1;
  524.                 }
  525.         }
  526.         *o_value = result;
  527.         return 0; /* end of conjunction */
  528. }

  529. int main(void)
  530. {
  531.         char cmd_line[1024];
  532.         int result;

  533.         puts("English Caculator");
  534.         puts("Enter an expression");
  535.         puts("Ctrl-Z to exit");
  536.         for (;;) {
  537.                 printf(": ");
  538.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  539.                         puts("");
  540.                         return 0;
  541.                 }
  542.                 strrtrim(cmd_line);
  543.                 strtrim(cmd_line);
  544.                 if (caculate(cmd_line, &result) == 0) {
  545.                         printf("\"%s\" = %d\n", cmd_line, result);
  546.                 }else {
  547.                         printf("\"%s\" = E, Invalid Expression\n", cmd_line);
  548.                 }
  549.         }
  550. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
20 [报告]
发表于 2011-08-10 10:20 |只看该作者
改进token匹配算法。

  1. /* eng_cac.c */

  2. /* english caculator */

  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <string.h>

  6. int skip_space(const char *p, int *io_index)
  7. {
  8.         int index;

  9.         if (p == NULL || io_index == NULL) {
  10.                 return -1;
  11.         }
  12.         index = *io_index;
  13.         if (index < 0) {
  14.                 return -1;
  15.         }
  16.         if (!isspace(p[index])) {
  17.                 return -1;
  18.         }
  19.         do {
  20.                 ++index;
  21.         }while (isspace(p[index]));
  22.         *io_index = index;
  23.         return 0;
  24. }

  25. int get_word(const char *p, int *io_index, int *o_start, int *o_len)
  26. {
  27.         int index;

  28.         if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
  29.                 return -1;
  30.         }
  31.         index = *io_index;
  32.         if (index < 0) {
  33.                 return -1;
  34.         }
  35.         if (isalpha(p[index])) {
  36.                 do {
  37.                         ++index;
  38.                 }while (isalpha(p[index]));
  39.                 *o_start = *io_index;
  40.                 *o_len = index - *io_index;
  41.                 *io_index = index;
  42.                 return 0;
  43.         }else if (ispunct(p[index])) {
  44.                 ++index;
  45.                 *o_start = *io_index;
  46.                 *o_len = 1;
  47.                 *io_index = index;
  48.                 return 0;
  49.         }else {
  50.                 return -1;
  51.         }
  52. }

  53. int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
  54. {
  55.         int i;

  56.         if (tok == NULL || tok_tab == NULL) {
  57.                 return -1;
  58.         }
  59.         if (len <= 0 || tab_len <= 0) {
  60.                 return -1;
  61.         }
  62.         for (i = 0; i < tab_len; ++i) {
  63.                 if (strncmp(tok, tok_tab[i], len) == 0) {
  64.                         if (tok_tab[i][len] == '\0') {
  65.                                 return i;
  66.                         }
  67.                 }
  68.         }
  69.         return -1;
  70. }

  71. int skip_word(const char *p, int *io_index, const char *s)
  72. {
  73.         int index;
  74.         int start, len;

  75.         if (p == NULL || io_index == NULL || s == NULL) {
  76.                 return -1;
  77.         }
  78.         index = *io_index;
  79.         if (index < 0) {
  80.                 return -1;
  81.         }
  82.         skip_space(p, &index);
  83.         if (get_word(p, &index, &start, &len) == 0) {
  84.                 if (strncmp(p + start, s, len) == 0) {
  85.                         *io_index = index;
  86.                         return 0;
  87.                 }
  88.         }
  89.         return -1;
  90. }

  91. int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
  92. {
  93.         static const char *digit20[20] = {
  94.                 "zero",
  95.                 "one",
  96.                 "two",
  97.                 "three",
  98.                 "four",
  99.                 "five",
  100.                 "six",
  101.                 "seven",
  102.                 "eight",
  103.                 "nine",
  104.                 "ten",
  105.                 "eleven",
  106.                 "twelve",
  107.                 "thirteen",
  108.                 "fourteen",
  109.                 "fifteen",
  110.                 "sixteen",
  111.                 "seventeen",
  112.                 "eighteen",
  113.                 "nineteen",
  114.         };
  115.         int index;
  116.         int start;
  117.         int len;
  118.         int tok;

  119.         if (p == NULL || io_index == NULL || o_value == NULL) {
  120.                 return -1;
  121.         }
  122.         index = *io_index;
  123.         if (index < 0) {
  124.                 return -1;
  125.         }
  126.         skip_space(p, &index);
  127.         if (get_word(p, &index, &start, &len) == 0) {
  128.                 tok = get_token(p + start, len, digit20, 20);
  129.                 if (tok != -1) {
  130.                         *o_value = tok;
  131.                         *io_index = index;
  132.                         return 0;
  133.                 }
  134.         }
  135.         return -1;
  136. }

  137. int get_english_digit_decade(const char *p, int *io_index, int *o_value)
  138. {
  139.         static const char *decades[8] = {
  140.                 "twenty",
  141.                 "thirty",
  142.                 "forty",
  143.                 "fifty",
  144.                 "sixty",
  145.                 "seventy",
  146.                 "eighty",
  147.                 "ninety",
  148.         };
  149.         int index;
  150.         int start, len;
  151.         int value;
  152.         int retn;

  153.         if (p == NULL || io_index == NULL || o_value == NULL) {
  154.                 return -1;
  155.         }
  156.         index = *io_index;
  157.         if (index < 0) {
  158.                 return -1;
  159.         }
  160.         skip_space(p, &index);
  161.         if (get_word(p, &index, &start, &len) == 0) {
  162.                 retn = get_token(p + start, len, decades, 8);
  163.                 if (retn != -1) {
  164.                         value = retn * 10 + 20;
  165.                         *o_value = value;
  166.                         *io_index = index;
  167.                         return 0;
  168.                 }
  169.         }
  170.         return -1;
  171. }

  172. int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
  173. {
  174.         int index;
  175.         int value;
  176.         int digit;
  177.         int decade_yes;

  178.         if (p == NULL || io_index == NULL || o_value == NULL) {
  179.                 return -1;
  180.         }
  181.         index = *io_index;
  182.         if (index < 0) {
  183.                 return -1;
  184.         }
  185.         decade_yes = 0;
  186.         if (get_english_digit_decade(p, &index, &value) == -1) {
  187.                 value = 0;
  188.         }else {
  189.                 decade_yes = 1;
  190.         }
  191.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  192.                 if (decade_yes && digit == 0) {
  193.                         return -1;
  194.                 }
  195.                 value += digit;
  196.         }else {
  197.                 if (!decade_yes) {
  198.                         return -1;
  199.                 }
  200.         }
  201.         *o_value = value;
  202.         *io_index = index;
  203.         return 0;
  204. }

  205. int get_english_digit_base(const char *p, int *io_index, int *o_base)
  206. {
  207.         static const char *more[] = {
  208.                 "hundred",
  209.                 "thousand",
  210.                 "million",
  211.                 "billion",
  212.         };
  213.         static const int base[] = {
  214.                 100,
  215.                 1000,
  216.                 1000000,
  217.                 1000000000,
  218.         };
  219.         int index;
  220.         int start,len;
  221.         int retn;

  222.         if (p == NULL || io_index == NULL || o_base == NULL) {
  223.                 return -1;
  224.         }
  225.         index = *io_index;
  226.         if (index < 0) {
  227.                 return -1;
  228.         }
  229.         skip_space(p, &index);
  230.         if (get_word(p, &index, &start, &len) == 0) {
  231.                 retn = get_token(p + start, len, more, 4);
  232.                 if (retn != -1) {
  233.                         *o_base = base[retn];
  234.                         *io_index = index;
  235.                         return 0;
  236.                 }
  237.         }
  238.         return -1;
  239. }

  240. int get_english_digit(const char *p, int *io_index, int *o_value)
  241. {
  242.         int index;
  243.         int value;
  244.         int sum;
  245.         int base;

  246.         if (p == NULL || io_index == NULL || o_value == NULL) {
  247.                 return -1;
  248.         }
  249.         index = *io_index;
  250.         if (index < 0) {
  251.                 return -1;
  252.         }
  253.         sum = 0;
  254.         for (;;) {
  255.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  256.                         if (value == 0) {
  257.                                 if (sum > 0) {
  258.                                         return -1;
  259.                                 }
  260.                                 sum = 0;
  261.                                 break;
  262.                         }
  263.                         sum += value;
  264.                         while (get_english_digit_base(p, &index, &base) == 0) {
  265.                                 sum *= base;
  266.                         }
  267.                         if (skip_word(p, &index, "and") == 0) {
  268.                                 continue;
  269.                         }
  270.                         break;
  271.                 }else if (sum == 0) {
  272.                         if (skip_word(p, &index, "a") == 0) {
  273.                                 sum = 1;
  274.                                 while (get_english_digit_base(p, &index, &base) == 0) {
  275.                                         sum *= base;
  276.                                 }
  277.                                 if (skip_word(p, &index, "and") == 0) {
  278.                                         continue;
  279.                                 }
  280.                                 break;
  281.                         }
  282.                 }
  283.                 return -1;
  284.         }
  285.         *o_value = sum;
  286.         *io_index = index;
  287.         return 0;
  288. }

  289. int get_operator1(const char *p, int *io_index, int *o_op)
  290. {
  291.         static const char *op_list[] = {
  292.                 "positive",
  293.                 "+",
  294.                 "negative",
  295.                 "-",
  296.         };
  297.         int index;
  298.         int start, len;
  299.         int retn;
  300.        
  301.         if (p == NULL || io_index == NULL || o_op == NULL) {
  302.                 return -1;
  303.         }
  304.         index = *io_index;
  305.         if (index < 0) {
  306.                 return -1;
  307.         }
  308.         skip_space(p, &index);
  309.         if (get_word(p, &index, &start, &len) == 0) {
  310.                 retn = get_token(p + start, len, op_list, 8);
  311.                 if (retn != -1) {
  312.                         *o_op = retn / 2;
  313.                         *io_index = index;
  314.                         return 0;
  315.                 }
  316.         }
  317.         return -1;
  318. }

  319. int get_operator2(const char *p, int *io_index, int *o_op)
  320. {
  321.         static const char *op_list[] = {
  322.                 "plus",
  323.                 "+",
  324.                 "minus",
  325.                 "-",
  326.                 "multiply",
  327.                 "*",
  328.                 "divide",
  329.                 "/",
  330.         };
  331.         int index;
  332.         int start, len;
  333.         int retn;

  334.         if (p == NULL || io_index == NULL || o_op == NULL) {
  335.                 return -1;
  336.         }
  337.         index = *io_index;
  338.         if (index < 0) {
  339.                 return -1;
  340.         }
  341.         skip_space(p, &index);
  342.         if (get_word(p, &index, &start, &len) == 0) {
  343.                 retn = get_token(p + start, len, op_list, 8);
  344.                 if (retn != -1) {
  345.                         if ((retn & 1) == 0) {
  346.                                 skip_word(p, &index, "with");
  347.                         }
  348.                         *o_op = retn / 2;
  349.                         *io_index = index;
  350.                         return 0;
  351.                 }
  352.         }
  353.         return -1;
  354. }

  355. int get_number(const char *p, int *io_index, int *o_value)
  356. {
  357.         int index;
  358.         int value;

  359.         if (p == NULL || io_index == NULL || o_value == NULL) {
  360.                 return -1;
  361.         }
  362.         index = *io_index;
  363.         if (index < 0) {
  364.                 return -1;
  365.         }
  366.         skip_space(p, &index);
  367.         if (isdigit(p[index])) {
  368.                 value = 0;
  369.                 do {
  370.                         value = value * 10 + p[index] - '0';
  371.                         index++;
  372.                 }while (isdigit(p[index]));
  373.                 *o_value = value;
  374.                 *io_index = index;
  375.                 return 0;
  376.         }
  377.         return -1;
  378. }

  379. int get_digit(const char *p, int *io_index, int *o_value)
  380. {
  381.         int index;
  382.         int value;

  383.         if (p == NULL || io_index == NULL || o_value == NULL) {
  384.                 return -1;
  385.         }
  386.         index = *io_index;
  387.         if (index < 0) {
  388.                 return -1;
  389.         }
  390.         if (get_english_digit(p, &index, &value) == 0
  391.                 || get_number(p, &index, &value) == 0) {
  392.                 *o_value = value;
  393.                 *io_index = index;
  394.                 return 0;
  395.         }
  396.         return -1;
  397. }

  398. int get_oprand(const char *p, int *io_index, int *o_value)
  399. {
  400.         int index;
  401.         int op;
  402.         int d1;
  403.         int result;

  404.         if (p == NULL || io_index == NULL || o_value == NULL) {
  405.                 return -1;
  406.         }
  407.         index = *io_index;
  408.         if (index < 0) {
  409.                 return -1;
  410.         }
  411.         /* one oprand operation */
  412.         if (get_operator1(p, &index, &op) == 0) {
  413.                 if (get_digit(p, &index, &d1) != 0) {
  414.                         return -1;
  415.                 }
  416.                 switch (op) {
  417.                 case 0:
  418.                         result = d1;
  419.                         break;
  420.                 case 1:
  421.                         result = -d1;
  422.                         break;
  423.                 default:
  424.                         return -1;
  425.                 }
  426.         }else {
  427.                 if (get_digit(p, &index, &result) != 0) {
  428.                         return -1;
  429.                 }
  430.         }
  431.         *o_value = result;
  432.         *io_index = index;
  433.         return 0;
  434. }

  435. int strrtrim(char *p)
  436. {
  437.         int len;

  438.         if (p == NULL) {
  439.                 return -1;
  440.         }
  441.         len = strlen(p);
  442.         if (len > 0) {
  443.                 if (isspace(p[len - 1])) {
  444.                         do {
  445.                                 --len;
  446.                         }while(len >= 0 && isspace(p[len]));
  447.                         p[len + 1] = '\0';
  448.                 }
  449.         }
  450.         return 0;
  451. }

  452. int strtrim(char *p)
  453. {
  454.         int i;

  455.         if (p == NULL) {
  456.                 return -1;
  457.         }
  458.         for (i = 0; p[i] != '\0'; ++i) {
  459.                 if (!isspace(p[i])) {
  460.                         break;
  461.                 }
  462.         }
  463.         strcpy(p, p + i);
  464.         return 0;
  465. }

  466. int get_end(const char *p, int *io_index)
  467. {
  468.         int index;

  469.         if (p == NULL || io_index == NULL) {
  470.                 return -1;
  471.         }
  472.         index = *io_index;
  473.         if (index < 0) {
  474.                 return -1;
  475.         }
  476.         skip_space(p, &index);
  477.         if (p[index] == '\0') {
  478.                 *io_index = index;
  479.                 return 0;
  480.         }
  481.         return -1;
  482. }

  483. int caculate(const char *exp, int *o_value)
  484. {
  485.         int op; /* operator */
  486.         int d1, d2; /* oprand number */
  487.         int result; /* store the expression result */
  488.         int index;

  489.         if (exp == NULL || o_value == NULL) {
  490.                 return -1;
  491.         }
  492.         index = 0;
  493.         if (get_oprand(exp, &index, &result) == -1) {
  494.                 return -1;
  495.         }
  496.         /* conjunction operation */
  497.         while (get_end(exp, &index) == -1) {
  498.                 /* two oprands operation */
  499.                 d1 = result;
  500.                 if (get_operator2(exp, &index, &op) == -1) {
  501.                         return -1;
  502.                 }
  503.                 if (get_oprand(exp, &index, &d2) == -1) {
  504.                         return -1;
  505.                 }
  506.                 switch (op) {
  507.                 case 0:
  508.                         result = d1 + d2;
  509.                         break;
  510.                 case 1:
  511.                         result = d1 - d2;
  512.                         break;
  513.                 case 2:
  514.                         result = d1 * d2;
  515.                         break;
  516.                 case 3:
  517.                         if (d2 == 0) {
  518.                                 return -1;
  519.                         }
  520.                         result = d1 / d2;
  521.                         break;
  522.                 default:
  523.                         return -1;
  524.                 }
  525.         }
  526.         *o_value = result;
  527.         return 0; /* end of conjunction */
  528. }

  529. int main(void)
  530. {
  531.         char cmd_line[1024];
  532.         int result;

  533.         puts("English Caculator");
  534.         puts("Enter an expression");
  535.         puts("Ctrl-Z to exit");
  536.         for (;;) {
  537.                 printf(": ");
  538.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  539.                         puts("");
  540.                         return 0;
  541.                 }
  542.                 strrtrim(cmd_line);
  543.                 strtrim(cmd_line);
  544.                 if (caculate(cmd_line, &result) == 0) {
  545.                         printf("\"%s\" = %d\n", cmd_line, result);
  546.                 }else {
  547.                         printf("\"%s\" = E, Invalid Expression\n", cmd_line);
  548.                 }
  549.         }
  550. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP