免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 8729 | 回复: 26

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

论坛徽章:
0
发表于 2011-08-08 15:09 |显示全部楼层
大家好!!

我现在要在Linux下实现一个计算器程序, 它有如下的要求:
1.  能识别英文数字:比如 three hundred and ninety two, 要能转换为392.
2.  能识别英文的加减乘除: Add, minus, multiply, divide.
3.  能识别符号的加减乘除: +, -, *, /

例子如下:
输入:three hundred and ninety two multiply with 7
结果:2744

输入:12 minus 3
结果: 9


要怎么实现这个程序啊。。。跪求各位高手指点一下。。。尤其是是英文数字的识别。。这个还没头绪啊。。。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2011-08-08 15:14 |显示全部楼层
大家好!!

我现在要在Linux下实现一个计算器程序, 它有如下的要求:
1.  能识别英文数字:比如 three  ...
toddytao 发表于 2011-08-08 15:09



    YACC

论坛徽章:
0
发表于 2011-08-08 15:16 |显示全部楼层
回复 2# yulihua49


    求详解啊。。。大侠!!

论坛徽章:
0
发表于 2011-08-08 15:47 |显示全部楼层
flex & bison

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
发表于 2011-08-09 13:45 |显示全部楼层
注意:输入数字不能超过整数的范围,否则会溢出,将得不到正确结果。

  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.         if (p == NULL || io_index == NULL || o_value == NULL) {
  176.                 return -1;
  177.         }
  178.         index = *io_index;
  179.         if (index < 0) {
  180.                 return -1;
  181.         }
  182.         if (get_english_digit_decade(p, &index, &value) == -1) {
  183.                 value = 0;
  184.         }
  185.         if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
  186.                 value += digit;
  187.         }else {
  188.                 if (value == 0) {
  189.                         return -1;
  190.                 }
  191.         }
  192.         *o_value = value;
  193.         *io_index = index;
  194.         return 0;
  195. }

  196. int get_digit_base(const char *p, int *io_index, int *o_base)
  197. {
  198.         static const char *more[] = {
  199.                 "hundred",
  200.                 "thousand",
  201.                 "million",
  202.                 "billion",
  203.         };
  204.         static const int base[] = {
  205.                 100,
  206.                 1000,
  207.                 1000000,
  208.                 1000000000,
  209.         };
  210.         int index;
  211.         int start,len;
  212.         int retn;

  213.         if (p == NULL || io_index == NULL || o_base == NULL) {
  214.                 return -1;
  215.         }
  216.         index = *io_index;
  217.         if (index < 0) {
  218.                 return -1;
  219.         }
  220.         skip_space(p, &index);
  221.         if (get_word(p, &index, &start, &len) == 0) {
  222.                 retn = get_token(p + start, len, more, 4);
  223.                 if (retn != -1) {
  224.                         *o_base = base[retn];
  225.                         *io_index = index;
  226.                         return 0;
  227.                 }
  228.         }
  229.         return -1;
  230. }

  231. int get_english_digit(const char *p, int *io_index, int *o_value)
  232. {
  233.         int index;
  234.         int value;
  235.         int sum;
  236.         int base;

  237.         if (p == NULL || io_index == NULL || o_value == NULL) {
  238.                 return -1;
  239.         }
  240.         index = *io_index;
  241.         if (index < 0) {
  242.                 return -1;
  243.         }
  244.         sum = 0;
  245.         for (;;) {
  246.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  247.                         sum += value;
  248.                         if (get_digit_base(p, &index, &base) == 0) {
  249.                                 sum *= base;
  250.                                 if (skip_word(p, &index, "and") == 0) {
  251.                                         continue;
  252.                                 }
  253.                         }
  254.                         *o_value = sum;
  255.                         *io_index = index;
  256.                         return 0;
  257.                 }
  258.                 return -1;
  259.         }
  260. }

  261. int get_operator1(const char *p, int *io_index, int *o_op)
  262. {
  263.         static const char *op_list[] = {
  264.                 "positive",
  265.                 "+",
  266.                 "negative",
  267.                 "-",
  268.         };
  269.         int index;
  270.         int start, len;
  271.         int retn;
  272.        
  273.         if (p == NULL || io_index == NULL || o_op == NULL) {
  274.                 return -1;
  275.         }
  276.         index = *io_index;
  277.         if (index < 0) {
  278.                 return -1;
  279.         }
  280.         skip_space(p, &index);
  281.         if (get_word(p, &index, &start, &len) == 0) {
  282.                 retn = get_token(p + start, len, op_list, 8);
  283.                 if (retn != -1) {
  284.                         *o_op = retn / 2;
  285.                         *io_index = index;
  286.                         return 0;
  287.                 }
  288.         }
  289.         return -1;
  290. }

  291. int get_operator2(const char *p, int *io_index, int *o_op)
  292. {
  293.         static const char *op_list[] = {
  294.                 "plus",
  295.                 "+",
  296.                 "minus",
  297.                 "-",
  298.                 "multiple",
  299.                 "*",
  300.                 "divide",
  301.                 "/",
  302.         };
  303.         int index;
  304.         int start, len;
  305.         int retn;

  306.         if (p == NULL || io_index == NULL || o_op == NULL) {
  307.                 return -1;
  308.         }
  309.         index = *io_index;
  310.         if (index < 0) {
  311.                 return -1;
  312.         }
  313.         skip_space(p, &index);
  314.         if (get_word(p, &index, &start, &len) == 0) {
  315.                 retn = get_token(p + start, len, op_list, 8);
  316.                 if (retn != -1) {
  317.                         *o_op = retn / 2;
  318.                         *io_index = index;
  319.                         return 0;
  320.                 }
  321.         }
  322.         return -1;
  323. }

  324. int main(void)
  325. {
  326.         char cmd_line[1024];
  327.         int op; /* operator */
  328.         int d1, d2; /* oprand number */
  329.         int result; /* store the expression result */
  330.         int index;

  331.         puts("English Caculator\n");
  332.         puts("Please enter an expression");
  333.         puts("CTRL-Z to exit");
  334.         for (;;) {
  335.                 printf("\n: ");
  336.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  337.                         return 0;
  338.                 }
  339.                 index = 0;
  340.                 if (get_english_digit(cmd_line, &index, &d1) == 0) {
  341.                         /* two oprands operation */
  342.                         if (get_operator2(cmd_line, &index, &op) != 0) {
  343.                                 printf("Invalid Operator\n");
  344.                                 continue;
  345.                         }
  346.                         if (get_english_digit(cmd_line, &index, &d2) != 0) {
  347.                                 printf("Invalid English Number\n");
  348.                                 continue;
  349.                         }
  350.                         switch (op) {
  351.                         case 0:
  352.                                 result = d1 + d2;
  353.                                 break;
  354.                         case 1:
  355.                                 result = d1 - d2;
  356.                                 break;
  357.                         case 2:
  358.                                 result = d1 * d2;
  359.                                 break;
  360.                         case 3:
  361.                                 result = d1 / d2;
  362.                                 break;
  363.                         default:
  364.                                 printf("unknown operator\n");
  365.                                 continue;
  366.                         }
  367.                 }else {
  368.                         /* one oprands operation */
  369.                         if (get_operator1(cmd_line, &index, &op) != 0) {
  370.                                 printf("Invalid Operator\n");
  371.                                 continue;
  372.                         }
  373.                         if (get_english_digit(cmd_line, &index, &d1) != 0) {
  374.                                 printf("Invalid English Number\n");
  375.                                 continue;
  376.                         }
  377.                         switch (op) {
  378.                         case 0:
  379.                                 result = d1;
  380.                                 break;
  381.                         case 1:
  382.                                 result = -d1;
  383.                                 break;
  384.                         default:
  385.                                 printf("unknown operator\n");
  386.                                 continue;
  387.                         }
  388.                 }
  389.                 printf("%d\n", result);
  390.         }
  391. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
发表于 2011-08-09 13:59 |显示全部楼层
本帖最后由 cobras 于 2011-08-09 14:01 编辑

上面的修正版。
修正zero输入问题。

  1. Files in Workspace
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
发表于 2011-08-09 14: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.                 value += digit;
  191.         }else {
  192.                 if (!decade_yes) {
  193.                         return -1;
  194.                 }
  195.         }
  196.         *o_value = value;
  197.         *io_index = index;
  198.         return 0;
  199. }

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

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

  235. int get_english_digit(const char *p, int *io_index, int *o_value)
  236. {
  237.         int index;
  238.         int value;
  239.         int sum;
  240.         int base;

  241.         if (p == NULL || io_index == NULL || o_value == NULL) {
  242.                 return -1;
  243.         }
  244.         index = *io_index;
  245.         if (index < 0) {
  246.                 return -1;
  247.         }
  248.         sum = 0;
  249.         for (;;) {
  250.                 if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
  251.                         sum += value;
  252.                         if (get_digit_base(p, &index, &base) == 0) {
  253.                                 sum *= base;
  254.                                 if (skip_word(p, &index, "and") == 0) {
  255.                                         continue;
  256.                                 }
  257.                         }
  258.                         *o_value = sum;
  259.                         *io_index = index;
  260.                         return 0;
  261.                 }
  262.                 return -1;
  263.         }
  264. }

  265. int get_operator1(const char *p, int *io_index, int *o_op)
  266. {
  267.         static const char *op_list[] = {
  268.                 "positive",
  269.                 "+",
  270.                 "negative",
  271.                 "-",
  272.         };
  273.         int index;
  274.         int start, len;
  275.         int retn;
  276.        
  277.         if (p == NULL || io_index == NULL || o_op == NULL) {
  278.                 return -1;
  279.         }
  280.         index = *io_index;
  281.         if (index < 0) {
  282.                 return -1;
  283.         }
  284.         skip_space(p, &index);
  285.         if (get_word(p, &index, &start, &len) == 0) {
  286.                 retn = get_token(p + start, len, op_list, 8);
  287.                 if (retn != -1) {
  288.                         *o_op = retn / 2;
  289.                         *io_index = index;
  290.                         return 0;
  291.                 }
  292.         }
  293.         return -1;
  294. }

  295. int get_operator2(const char *p, int *io_index, int *o_op)
  296. {
  297.         static const char *op_list[] = {
  298.                 "plus",
  299.                 "+",
  300.                 "minus",
  301.                 "-",
  302.                 "multiple",
  303.                 "*",
  304.                 "divide",
  305.                 "/",
  306.         };
  307.         int index;
  308.         int start, len;
  309.         int retn;

  310.         if (p == NULL || io_index == NULL || o_op == NULL) {
  311.                 return -1;
  312.         }
  313.         index = *io_index;
  314.         if (index < 0) {
  315.                 return -1;
  316.         }
  317.         skip_space(p, &index);
  318.         if (get_word(p, &index, &start, &len) == 0) {
  319.                 retn = get_token(p + start, len, op_list, 8);
  320.                 if (retn != -1) {
  321.                         *o_op = retn / 2;
  322.                         *io_index = index;
  323.                         return 0;
  324.                 }
  325.         }
  326.         return -1;
  327. }

  328. int main(void)
  329. {
  330.         char cmd_line[1024];
  331.         int op; /* operator */
  332.         int d1, d2; /* oprand number */
  333.         int result; /* store the expression result */
  334.         int index;

  335.         puts("English Caculator\n");
  336.         puts("Please enter an expression");
  337.         puts("CTRL-Z to exit");
  338.         for (;;) {
  339.                 printf("\n: ");
  340.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  341.                         return 0;
  342.                 }
  343.                 index = 0;
  344.                 if (get_english_digit(cmd_line, &index, &d1) == 0) {
  345.                         /* two oprands operation */
  346.                         if (get_operator2(cmd_line, &index, &op) != 0) {
  347.                                 printf("Invalid Operator\n");
  348.                                 continue;
  349.                         }
  350.                         if (get_english_digit(cmd_line, &index, &d2) != 0) {
  351.                                 printf("Invalid English Number\n");
  352.                                 continue;
  353.                         }
  354.                         switch (op) {
  355.                         case 0:
  356.                                 result = d1 + d2;
  357.                                 break;
  358.                         case 1:
  359.                                 result = d1 - d2;
  360.                                 break;
  361.                         case 2:
  362.                                 result = d1 * d2;
  363.                                 break;
  364.                         case 3:
  365.                                 result = d1 / d2;
  366.                                 break;
  367.                         default:
  368.                                 printf("unknown operator\n");
  369.                                 continue;
  370.                         }
  371.                 }else {
  372.                         /* one oprand operation */
  373.                         if (get_operator1(cmd_line, &index, &op) != 0) {
  374.                                 printf("Invalid Operator\n");
  375.                                 continue;
  376.                         }
  377.                         if (get_english_digit(cmd_line, &index, &d1) != 0) {
  378.                                 printf("Invalid English Number\n");
  379.                                 continue;
  380.                         }
  381.                         switch (op) {
  382.                         case 0:
  383.                                 result = d1;
  384.                                 break;
  385.                         case 1:
  386.                                 result = -d1;
  387.                                 break;
  388.                         default:
  389.                                 printf("unknown operator\n");
  390.                                 continue;
  391.                         }
  392.                 }
  393.                 printf("%d\n", result);
  394.         }
  395. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
发表于 2011-08-09 14:15 |显示全部楼层
增加解释"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.                 value += digit;
  191.         }else {
  192.                 if (!decade_yes) {
  193.                         return -1;
  194.                 }
  195.         }
  196.         *o_value = value;
  197.         *io_index = index;
  198.         return 0;
  199. }

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

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

  235. int get_english_digit(const char *p, int *io_index, int *o_value)
  236. {
  237.         int index;
  238.         int value;
  239.         int sum;
  240.         int base;

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

  277. int get_operator1(const char *p, int *io_index, int *o_op)
  278. {
  279.         static const char *op_list[] = {
  280.                 "positive",
  281.                 "+",
  282.                 "negative",
  283.                 "-",
  284.         };
  285.         int index;
  286.         int start, len;
  287.         int retn;
  288.        
  289.         if (p == NULL || io_index == NULL || o_op == NULL) {
  290.                 return -1;
  291.         }
  292.         index = *io_index;
  293.         if (index < 0) {
  294.                 return -1;
  295.         }
  296.         skip_space(p, &index);
  297.         if (get_word(p, &index, &start, &len) == 0) {
  298.                 retn = get_token(p + start, len, op_list, 8);
  299.                 if (retn != -1) {
  300.                         *o_op = retn / 2;
  301.                         *io_index = index;
  302.                         return 0;
  303.                 }
  304.         }
  305.         return -1;
  306. }

  307. int get_operator2(const char *p, int *io_index, int *o_op)
  308. {
  309.         static const char *op_list[] = {
  310.                 "plus",
  311.                 "+",
  312.                 "minus",
  313.                 "-",
  314.                 "multiple",
  315.                 "*",
  316.                 "divide",
  317.                 "/",
  318.         };
  319.         int index;
  320.         int start, len;
  321.         int retn;

  322.         if (p == NULL || io_index == NULL || o_op == NULL) {
  323.                 return -1;
  324.         }
  325.         index = *io_index;
  326.         if (index < 0) {
  327.                 return -1;
  328.         }
  329.         skip_space(p, &index);
  330.         if (get_word(p, &index, &start, &len) == 0) {
  331.                 retn = get_token(p + start, len, op_list, 8);
  332.                 if (retn != -1) {
  333.                         *o_op = retn / 2;
  334.                         *io_index = index;
  335.                         return 0;
  336.                 }
  337.         }
  338.         return -1;
  339. }

  340. int main(void)
  341. {
  342.         char cmd_line[1024];
  343.         int op; /* operator */
  344.         int d1, d2; /* oprand number */
  345.         int result; /* store the expression result */
  346.         int index;

  347.         puts("English Caculator\n");
  348.         puts("Please enter an expression");
  349.         puts("CTRL-Z to exit");
  350.         for (;;) {
  351.                 printf("\n: ");
  352.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  353.                         return 0;
  354.                 }
  355.                 index = 0;
  356.                 if (get_english_digit(cmd_line, &index, &d1) == 0) {
  357.                         /* two oprands operation */
  358.                         if (get_operator2(cmd_line, &index, &op) != 0) {
  359.                                 printf("Invalid Operator\n");
  360.                                 continue;
  361.                         }
  362.                         if (get_english_digit(cmd_line, &index, &d2) != 0) {
  363.                                 printf("Invalid English Number\n");
  364.                                 continue;
  365.                         }
  366.                         switch (op) {
  367.                         case 0:
  368.                                 result = d1 + d2;
  369.                                 break;
  370.                         case 1:
  371.                                 result = d1 - d2;
  372.                                 break;
  373.                         case 2:
  374.                                 result = d1 * d2;
  375.                                 break;
  376.                         case 3:
  377.                                 result = d1 / d2;
  378.                                 break;
  379.                         default:
  380.                                 printf("unknown operator\n");
  381.                                 continue;
  382.                         }
  383.                 }else {
  384.                         /* one oprand operation */
  385.                         if (get_operator1(cmd_line, &index, &op) != 0) {
  386.                                 printf("Invalid Operator\n");
  387.                                 continue;
  388.                         }
  389.                         if (get_english_digit(cmd_line, &index, &d1) != 0) {
  390.                                 printf("Invalid English Number\n");
  391.                                 continue;
  392.                         }
  393.                         switch (op) {
  394.                         case 0:
  395.                                 result = d1;
  396.                                 break;
  397.                         case 1:
  398.                                 result = -d1;
  399.                                 break;
  400.                         default:
  401.                                 printf("unknown operator\n");
  402.                                 continue;
  403.                         }
  404.                 }
  405.                 printf("%d\n", result);
  406.         }
  407. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
发表于 2011-08-09 14:17 |显示全部楼层
修正"twenty zero"之类的错误表示。

  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.                         sum += value;
  255.                         if (get_digit_base(p, &index, &base) == 0) {
  256.                                 sum *= base;
  257.                                 if (skip_word(p, &index, "and") == 0) {
  258.                                         continue;
  259.                                 }
  260.                         }
  261.                         *o_value = sum;
  262.                         *io_index = index;
  263.                         return 0;
  264.                 }else if (sum == 0) {
  265.                         if (skip_word(p, &index, "a") == 0) {
  266.                                 if (get_digit_base(p, &index, &base) == 0) {
  267.                                         sum = base;
  268.                                         if (skip_word(p, &index, "and") == 0) {
  269.                                                 continue;
  270.                                         }
  271.                                         *o_value = sum;
  272.                                         *io_index = index;
  273.                                         return 0;
  274.                                 }
  275.                         }
  276.                 }
  277.                 return -1;
  278.         }
  279. }

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

  310. int get_operator2(const char *p, int *io_index, int *o_op)
  311. {
  312.         static const char *op_list[] = {
  313.                 "plus",
  314.                 "+",
  315.                 "minus",
  316.                 "-",
  317.                 "multiple",
  318.                 "*",
  319.                 "divide",
  320.                 "/",
  321.         };
  322.         int index;
  323.         int start, len;
  324.         int retn;

  325.         if (p == NULL || io_index == NULL || o_op == NULL) {
  326.                 return -1;
  327.         }
  328.         index = *io_index;
  329.         if (index < 0) {
  330.                 return -1;
  331.         }
  332.         skip_space(p, &index);
  333.         if (get_word(p, &index, &start, &len) == 0) {
  334.                 retn = get_token(p + start, len, op_list, 8);
  335.                 if (retn != -1) {
  336.                         *o_op = retn / 2;
  337.                         *io_index = index;
  338.                         return 0;
  339.                 }
  340.         }
  341.         return -1;
  342. }

  343. int main(void)
  344. {
  345.         char cmd_line[1024];
  346.         int op; /* operator */
  347.         int d1, d2; /* oprand number */
  348.         int result; /* store the expression result */
  349.         int index;

  350.         puts("English Caculator\n");
  351.         puts("Please enter an expression");
  352.         puts("CTRL-Z to exit");
  353.         for (;;) {
  354.                 printf("\n: ");
  355.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  356.                         return 0;
  357.                 }
  358.                 index = 0;
  359.                 if (get_english_digit(cmd_line, &index, &d1) == 0) {
  360.                         /* two oprands operation */
  361.                         if (get_operator2(cmd_line, &index, &op) != 0) {
  362.                                 printf("Invalid Operator\n");
  363.                                 continue;
  364.                         }
  365.                         if (get_english_digit(cmd_line, &index, &d2) != 0) {
  366.                                 printf("Invalid English Number\n");
  367.                                 continue;
  368.                         }
  369.                         switch (op) {
  370.                         case 0:
  371.                                 result = d1 + d2;
  372.                                 break;
  373.                         case 1:
  374.                                 result = d1 - d2;
  375.                                 break;
  376.                         case 2:
  377.                                 result = d1 * d2;
  378.                                 break;
  379.                         case 3:
  380.                                 result = d1 / d2;
  381.                                 break;
  382.                         default:
  383.                                 printf("unknown operator\n");
  384.                                 continue;
  385.                         }
  386.                 }else {
  387.                         /* one oprand operation */
  388.                         if (get_operator1(cmd_line, &index, &op) != 0) {
  389.                                 printf("Invalid Operator\n");
  390.                                 continue;
  391.                         }
  392.                         if (get_english_digit(cmd_line, &index, &d1) != 0) {
  393.                                 printf("Invalid English Number\n");
  394.                                 continue;
  395.                         }
  396.                         switch (op) {
  397.                         case 0:
  398.                                 result = d1;
  399.                                 break;
  400.                         case 1:
  401.                                 result = -d1;
  402.                                 break;
  403.                         default:
  404.                                 printf("unknown operator\n");
  405.                                 continue;
  406.                         }
  407.                 }
  408.                 printf("%d\n", result);
  409.         }
  410. }
复制代码

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
发表于 2011-08-09 14:22 |显示全部楼层
修正:"a hundred and zero"和"zero 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_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.                 "multiple",
  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.                         *o_op = retn / 2;
  343.                         *io_index = index;
  344.                         return 0;
  345.                 }
  346.         }
  347.         return -1;
  348. }

  349. int main(void)
  350. {
  351.         char cmd_line[1024];
  352.         int op; /* operator */
  353.         int d1, d2; /* oprand number */
  354.         int result; /* store the expression result */
  355.         int index;

  356.         puts("English Caculator\n");
  357.         puts("Please enter an expression");
  358.         puts("CTRL-Z to exit");
  359.         for (;;) {
  360.                 printf("\n: ");
  361.                 if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
  362.                         return 0;
  363.                 }
  364.                 index = 0;
  365.                 if (get_english_digit(cmd_line, &index, &d1) == 0) {
  366.                         /* two oprands operation */
  367.                         if (get_operator2(cmd_line, &index, &op) != 0) {
  368.                                 printf("Invalid Operator\n");
  369.                                 continue;
  370.                         }
  371.                         if (get_english_digit(cmd_line, &index, &d2) != 0) {
  372.                                 printf("Invalid English Number\n");
  373.                                 continue;
  374.                         }
  375.                         switch (op) {
  376.                         case 0:
  377.                                 result = d1 + d2;
  378.                                 break;
  379.                         case 1:
  380.                                 result = d1 - d2;
  381.                                 break;
  382.                         case 2:
  383.                                 result = d1 * d2;
  384.                                 break;
  385.                         case 3:
  386.                                 result = d1 / d2;
  387.                                 break;
  388.                         default:
  389.                                 printf("unknown operator\n");
  390.                                 continue;
  391.                         }
  392.                 }else {
  393.                         /* one oprand operation */
  394.                         if (get_operator1(cmd_line, &index, &op) != 0) {
  395.                                 printf("Invalid Operator\n");
  396.                                 continue;
  397.                         }
  398.                         if (get_english_digit(cmd_line, &index, &d1) != 0) {
  399.                                 printf("Invalid English Number\n");
  400.                                 continue;
  401.                         }
  402.                         switch (op) {
  403.                         case 0:
  404.                                 result = d1;
  405.                                 break;
  406.                         case 1:
  407.                                 result = -d1;
  408.                                 break;
  409.                         default:
  410.                                 printf("unknown operator\n");
  411.                                 continue;
  412.                         }
  413.                 }
  414.                 printf("%d\n", result);
  415.         }
  416. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP