- 论坛徽章:
- 2
|
修正"twenty zero"之类的错误表示。
- /* eng_cac.c */
- /* english caculator */
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- int skip_space(const char *p, int *io_index)
- {
- int index;
- if (p == NULL || io_index == NULL) {
- return -1;
- }
- index = *io_index;
- if (index < 0) {
- return -1;
- }
- if (!isspace(p[index])) {
- return -1;
- }
- do {
- ++index;
- }while (isspace(p[index]));
- *io_index = index;
- return 0;
- }
- int get_word(const char *p, int *io_index, int *o_start, int *o_len)
- {
- int index;
- if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
- return -1;
- }
- index = *io_index;
- if (index < 0) {
- return -1;
- }
- if (isalpha(p[index])) {
- do {
- ++index;
- }while (isalpha(p[index]));
- *o_start = *io_index;
- *o_len = index - *io_index;
- *io_index = index;
- return 0;
- }else if (ispunct(p[index])) {
- ++index;
- *o_start = *io_index;
- *o_len = 1;
- *io_index = index;
- return 0;
- }else {
- return -1;
- }
- }
- int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
- {
- int i;
- if (tok == NULL || tok_tab == NULL) {
- return -1;
- }
- if (len <= 0 || tab_len <= 0) {
- return -1;
- }
- for (i = 0; i < tab_len; ++i) {
- if (strncmp(tok, tok_tab[i], len) == 0) {
- return i;
- }
- }
- return -1;
- }
- int skip_word(const char *p, int *io_index, const char *s)
- {
- int index;
- int start, len;
- if (p == NULL || io_index == NULL || s == NULL) {
- return -1;
- }
- index = *io_index;
- if (index < 0) {
- return -1;
- }
- skip_space(p, &index);
- if (get_word(p, &index, &start, &len) == 0) {
- if (strncmp(p + start, s, len) == 0) {
- *io_index = index;
- return 0;
- }
- }
- return -1;
- }
- int get_english_digit_bellow_twenty(const char *p, int *io_index, int *o_value)
- {
- static const char *digit20[20] = {
- "zero",
- "one",
- "two",
- "three",
- "four",
- "five",
- "six",
- "seven",
- "eight",
- "nine",
- "ten",
- "eleven",
- "twelve",
- "thirteen",
- "fourteen",
- "fifteen",
- "sixteen",
- "seventeen",
- "eighteen",
- "nineteen",
- };
- int index;
- int start;
- int len;
- int tok;
- if (p == NULL || io_index == NULL || o_value == NULL) {
- return -1;
- }
- index = *io_index;
- if (index < 0) {
- return -1;
- }
- skip_space(p, &index);
- if (get_word(p, &index, &start, &len) == 0) {
- tok = get_token(p + start, len, digit20, 20);
- if (tok != -1) {
- *o_value = tok;
- *io_index = index;
- return 0;
- }
- }
- return -1;
- }
- int get_english_digit_decade(const char *p, int *io_index, int *o_value)
- {
- static const char *decades[8] = {
- "twenty",
- "thirty",
- "forty",
- "fifty",
- "sixty",
- "seventy",
- "eighty",
- "ninety",
- };
- int index;
- int start, len;
- int value;
- int retn;
- if (p == NULL || io_index == NULL || o_value == NULL) {
- return -1;
- }
- index = *io_index;
- if (index < 0) {
- return -1;
- }
- skip_space(p, &index);
- if (get_word(p, &index, &start, &len) == 0) {
- retn = get_token(p + start, len, decades, 8);
- if (retn != -1) {
- value = retn * 10 + 20;
- *o_value = value;
- *io_index = index;
- return 0;
- }
- }
- return -1;
- }
- int get_english_digit_bellow_hundred(const char *p, int *io_index, int *o_value)
- {
- int index;
- int value;
- int digit;
- int decade_yes;
- if (p == NULL || io_index == NULL || o_value == NULL) {
- return -1;
- }
- index = *io_index;
- if (index < 0) {
- return -1;
- }
- decade_yes = 0;
- if (get_english_digit_decade(p, &index, &value) == -1) {
- value = 0;
- }else {
- decade_yes = 1;
- }
- if (get_english_digit_bellow_twenty(p, &index, &digit) == 0) {
- if (decade_yes && digit == 0) {
- return -1;
- }
- value += digit;
- }else {
- if (!decade_yes) {
- return -1;
- }
- }
- *o_value = value;
- *io_index = index;
- return 0;
- }
- int get_digit_base(const char *p, int *io_index, int *o_base)
- {
- static const char *more[] = {
- "hundred",
- "thousand",
- "million",
- "billion",
- };
- static const int base[] = {
- 100,
- 1000,
- 1000000,
- 1000000000,
- };
- int index;
- int start,len;
- int retn;
- if (p == NULL || io_index == NULL || o_base == NULL) {
- return -1;
- }
- index = *io_index;
- if (index < 0) {
- return -1;
- }
- skip_space(p, &index);
- if (get_word(p, &index, &start, &len) == 0) {
- retn = get_token(p + start, len, more, 4);
- if (retn != -1) {
- *o_base = base[retn];
- *io_index = index;
- return 0;
- }
- }
- return -1;
- }
- int get_english_digit(const char *p, int *io_index, int *o_value)
- {
- int index;
- int value;
- int sum;
- int base;
- if (p == NULL || io_index == NULL || o_value == NULL) {
- return -1;
- }
- index = *io_index;
- if (index < 0) {
- return -1;
- }
- sum = 0;
- for (;;) {
- if (get_english_digit_bellow_hundred(p, &index, &value) == 0) {
- sum += value;
- if (get_digit_base(p, &index, &base) == 0) {
- sum *= base;
- if (skip_word(p, &index, "and") == 0) {
- continue;
- }
- }
- *o_value = sum;
- *io_index = index;
- return 0;
- }else if (sum == 0) {
- if (skip_word(p, &index, "a") == 0) {
- if (get_digit_base(p, &index, &base) == 0) {
- sum = base;
- if (skip_word(p, &index, "and") == 0) {
- continue;
- }
- *o_value = sum;
- *io_index = index;
- return 0;
- }
- }
- }
- return -1;
- }
- }
- int get_operator1(const char *p, int *io_index, int *o_op)
- {
- static const char *op_list[] = {
- "positive",
- "+",
- "negative",
- "-",
- };
- int index;
- int start, len;
- int retn;
-
- if (p == NULL || io_index == NULL || o_op == NULL) {
- return -1;
- }
- index = *io_index;
- if (index < 0) {
- return -1;
- }
- skip_space(p, &index);
- if (get_word(p, &index, &start, &len) == 0) {
- retn = get_token(p + start, len, op_list, 8);
- if (retn != -1) {
- *o_op = retn / 2;
- *io_index = index;
- return 0;
- }
- }
- return -1;
- }
- int get_operator2(const char *p, int *io_index, int *o_op)
- {
- static const char *op_list[] = {
- "plus",
- "+",
- "minus",
- "-",
- "multiple",
- "*",
- "divide",
- "/",
- };
- int index;
- int start, len;
- int retn;
- if (p == NULL || io_index == NULL || o_op == NULL) {
- return -1;
- }
- index = *io_index;
- if (index < 0) {
- return -1;
- }
- skip_space(p, &index);
- if (get_word(p, &index, &start, &len) == 0) {
- retn = get_token(p + start, len, op_list, 8);
- if (retn != -1) {
- *o_op = retn / 2;
- *io_index = index;
- return 0;
- }
- }
- return -1;
- }
- int main(void)
- {
- char cmd_line[1024];
- int op; /* operator */
- int d1, d2; /* oprand number */
- int result; /* store the expression result */
- int index;
- puts("English Caculator\n");
- puts("Please enter an expression");
- puts("CTRL-Z to exit");
- for (;;) {
- printf("\n: ");
- if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
- return 0;
- }
- index = 0;
- if (get_english_digit(cmd_line, &index, &d1) == 0) {
- /* two oprands operation */
- if (get_operator2(cmd_line, &index, &op) != 0) {
- printf("Invalid Operator\n");
- continue;
- }
- if (get_english_digit(cmd_line, &index, &d2) != 0) {
- printf("Invalid English Number\n");
- continue;
- }
- switch (op) {
- case 0:
- result = d1 + d2;
- break;
- case 1:
- result = d1 - d2;
- break;
- case 2:
- result = d1 * d2;
- break;
- case 3:
- result = d1 / d2;
- break;
- default:
- printf("unknown operator\n");
- continue;
- }
- }else {
- /* one oprand operation */
- if (get_operator1(cmd_line, &index, &op) != 0) {
- printf("Invalid Operator\n");
- continue;
- }
- if (get_english_digit(cmd_line, &index, &d1) != 0) {
- printf("Invalid English Number\n");
- continue;
- }
- switch (op) {
- case 0:
- result = d1;
- break;
- case 1:
- result = -d1;
- break;
- default:
- printf("unknown operator\n");
- continue;
- }
- }
- printf("%d\n", result);
- }
- }
复制代码 |
|