一、简介
Linux下实现的简单的计算器程序。
二、详解
1、代码一
(1)caculator.c:
/*Linux下实现一个计算器程序, 它有如下的要求:
*1. 能识别英文数字:比如 three hundred and ninety two, 要能转换为392.
*2. 能识别英文的加减乘除: Add, minus, multiply, divide.
*3. 能识别符号的加减乘除: +, -, *, /
*
*例子如下:
*输入:three hundred and ninety two multiply 7
*结果:2744
*
*输入:12 minus 3
*结果: 9
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#define bool int
#define true 1
#define false 0
void ltrim(char *str, const char ch);
void rtrim(char *str, const char ch);
int caculate(const char *input, int *result);
char get_operant(char *data, int* op1, int* op2);
int skip_work(char *data);
jmp_buf jmp;
int main()
{
int result;
char input[1024] = {0};
puts("***********self made english caculator*****************");
puts("input exit to go out!");
while(1)
{
setjmp(jmp);
puts("please input an expression:");
if(gets(input) == NULL)
{
puts("get input data failed!");
return -1;
}
ltrim(input, ' ');
rtrim(input, ' ');
if(strcmp(input, "exit") == 0)
break;
if(skip_work(input) < 0)
puts("skip failed!");
if(caculate(input, &result) == 0)
{
printf("The result is:%s = %d\n", input, result);
}
else
{
printf("cannot caculate!\n");
}
}
puts("out of the caculator!");
return 0;
}
void ltrim(char *str, const char ch)
{
char *ptr;
for (ptr = str; *ptr; ptr ++)
{
if(*ptr != ch)
break;
}
strcpy(str, ptr);
}
void rtrim(char *str, const char ch)
{
int i;
int len = strlen(str);
for (i = len - 1; i >= 0; i--)
{
if(str[i] != ch)
break;
}
str[i + 1] = '\0';
}
int caculate(const char *str, int *result)
{
char *input = (char*)malloc(strlen(str) + 1);
strcpy(input, str);
int op1, op2;
char op;
float div;
op = get_operant(input, &op1, &op2);
free(input);
input = NULL;
switch(op)
{
case '+':
*result = op1 + op2;
break;
case '-':
*result = op1 - op2;
break;
case '*':
*result = op1 * op2;
break;
case '/':
if(op2 == 0)
{
puts("divisor illegal!");
return -1;
}
else
div = (float)op1 / op2;
printf("The result is:%s = %0.3f\n", str, div);
longjmp(jmp, 1);
break;
default:
return -1;
}
return 0;
}
char get_operant(char *data, int* op1, int* op2)
{
static const char *op_list[]={"+", "-", "*", "/"};
int i;
char *temp = data;
char *change;
char *tok = NULL;
char *steptok = NULL;
while(*temp != '\0')
{
if(*temp == ' ')
{
change = temp;
while(*change != '\0')
{
*change = *(change + 1);
change ++;
}
}
temp++;
}
char data_mp[100] = {0};
//char data_mp[100] = {0};
int sum = 0;
strcpy(data_mp, data);
char tok_one[50] = {0};
char tok_two[50] = {0};
char tok_one_temp[50] = {0};
char tok_two_temp[50] = {0};
for (i = 0; i < 4; i++)
{
tok = strtok(data, op_list[i]);
if (strcmp(data, data_mp) != 0)
break;
}
strcpy(tok_one, tok);
strcpy(tok_one_temp, tok);
tok = strtok(NULL, op_list[i]);
strcpy(tok_two, tok);
strcpy(tok_two_temp, tok);
//printf("tok_one:%s\n", tok_one);
steptok = strtok(tok_one, "and");
if(strcmp(tok_one_temp, steptok) != 0)
{
sum = atoi(steptok);
steptok = strtok(NULL, "and");
sum += atoi(steptok);
*op1 = sum;
}
else
*op1 = atoi(tok_one);
steptok = strtok(tok_two, "and");
if(strcmp(tok_two_temp, steptok) != 0)
{
sum = atoi(steptok);
steptok = strtok(NULL, "and");
sum += atoi(steptok);
*op2 = sum;
}
else
*op2 = atoi(tok_two);
//printf("%d,%d,%c\n",*op1,*op2,*op_list[i]);
return *op_list[i];
}
int skip_work(char *data)
{
static const char *symbol[8]={
"plus", "minus", "multiply", "divide", "+", "-", "*", "/"};
static const char *link[8]={
"hundred", "thousand", "million", "billion", "00", "000", "000000, 000000000"};
static const char *decade[16] ={
"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety",
"20", "30", "40", "50", "60", "70", "80", "90"};
static const char *digit[20]={
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
"ten", "eleven", "twelve", "thirteen", "fourteen","fifteen", "sixteen",
"seventeen", "eighteen", "nineteen"};
bool flag = false;
char *toks = " ";
char *tok = strtok(data, toks);
int i, j, m ,n;
char temp_tok[20] = {0};
char data_temp[50]= {0};
while(tok)
{
for(i = 0; i < 20; i++)
if(!strcmp(tok, digit[i]))
{
if(flag == true)
{
i += atoi(decade[m + 8]);
}
sprintf(temp_tok, "%d", i);
break;
}
for(j = 0; j < 4; j++)
{
if(!strcmp(tok, link[j]))
{
strcat(data_temp, link[j + 4]);
//sprintf(temp_tok, i*atoi(j+4));
break;
}
}
if(j != 4)
{
tok = strtok(NULL, toks);
continue;
}
for(m = 0; m < 8; m++)
{
if(!strcmp(tok, decade[m]))
{
flag = true;
//strcat(data_temp, decade[m + 8]);
break;
}
}
if (m != 8)
{
tok = strtok(NULL, toks);
continue;
}
for(n = 0; n < 4;n++)
if(!strcmp(tok, symbol[n]))
{
strcpy(temp_tok, symbol[n+4]);
break;
}
if(i == 20 && j == 4 && m == 8 && n == 4)
strcpy(temp_tok, tok);
//if (!strcmp(temp_tok, data))
// strcpy(data, temp_tok);
//else
// printf("dddd11:%s\n", temp_tok);
strcat(data_temp, temp_tok);
tok = strtok(NULL, toks);
flag = false;
}
strcpy(data, data_temp);
return 0;
}
(2)编译运行
2、代码二
(1)caculator.c://Linux 下实现计算器程序
/* 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) {
if (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_number_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_number_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_number_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_number_decade(p, &index, &value) == -1) {
value = 0;
}else {
decade_yes = 1;
}
if (get_english_number_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_english_number_base(const char *p, int *io_index, int *o_base)
{
static const char *more[] = {
"thousand",
"million",
"billion",
};
static const int base[] = {
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_number_bellow_thousand(const char *p, int *io_index, int *o_value)
{
int index;
int value;
int sum;
if (p == NULL || io_index == NULL || o_value == NULL) {
return -1;
}
index = *io_index;
if (index < 0) {
return -1;
}
if (get_english_number_bellow_hundred(p, &index, &sum) == 0) {
if (sum > 0 && sum < 10) {
if (skip_word(p, &index, "hundred") == 0) {
sum *= 100;
if (skip_word(p, &index, "and") == 0) {
if (get_english_number_bellow_hundred(p, &index, &value) == -1) {
return -1;
}
if (value == 0) {
return -1;
}
sum += value;
}
}
}
*o_value = sum;
*io_index = index;
return 0;
}else if (skip_word(p, &index, "a") == 0) {
sum = 1;
if (skip_word(p, &index, "hundred") == 0) {
sum *= 100;
if (skip_word(p, &index, "and") == 0) {
if (get_english_number_bellow_hundred(p, &index, &value) == -1) {
return -1;
}
if (value == 0) {
return -1;
}
sum += + value;
}
}
*o_value = sum;
*io_index = index;
return 0;
}
return -1;
}
int get_english_number(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_number_bellow_thousand(p, &index, &value) == 0) {
if (value == 0) {
break;
}
if (get_english_number_base(p, &index, &base) == 0) {
value *= base;
if (sum > 0 && value >= sum) {
return -1;
}
sum += value;
continue;
}
sum += value;
}
if (sum == 0) {
return -1;
}
break;
}
*o_value = sum;
*io_index = index;
return 0;
}
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",
"-",
"multiply",
"*",
"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) {
if ((retn & 1) == 0) {
skip_word(p, &index, "with");
}
*o_op = retn / 2;
*io_index = index;
return 0;
}
}
return -1;
}
int get_arab_number(const char *p, int *io_index, int *o_value)
{
int index;
int value;
if (p == NULL || io_index == NULL || o_value == NULL) {
return -1;
}
index = *io_index;
if (index < 0) {
return -1;
}
skip_space(p, &index);
if (isdigit(p[index])) {
value = 0;
do {
value = value * 10 + p[index] - '0';
index++;
}while (isdigit(p[index]));
*o_value = value;
*io_index = index;
return 0;
}
return -1;
}
int get_number(const char *p, int *io_index, int *o_value)
{
int index;
int value;
if (p == NULL || io_index == NULL || o_value == NULL) {
return -1;
}
index = *io_index;
if (index < 0) {
return -1;
}
if (get_english_number(p, &index, &value) == 0
|| get_arab_number(p, &index, &value) == 0) {
*o_value = value;
*io_index = index;
return 0;
}
return -1;
}
int get_oprand(const char *p, int *io_index, int *o_value)
{
int index;
int op;
int d1;
int result;
if (p == NULL || io_index == NULL || o_value == NULL) {
return -1;
}
index = *io_index;
if (index < 0) {
return -1;
}
/* one oprand operation */
if (get_operator1(p, &index, &op) == 0) {
if (get_number(p, &index, &d1) != 0) {
return -1;
}
switch (op) {
case 0:
result = d1;
break;
case 1:
result = -d1;
break;
default:
return -1;
}
}else {
if (get_number(p, &index, &result) != 0) {
return -1;
}
}
*o_value = result;
*io_index = index;
return 0;
}
int get_end(const char *p, int *io_index)
{
int index;
if (p == NULL || io_index == NULL) {
return -1;
}
index = *io_index;
if (index < 0) {
return -1;
}
skip_space(p, &index);
if (p[index] == '\0') {
*io_index = index;
return 0;
}
return -1;
}
int caculate(const char *exp, int *o_value)
{
int op; /* operator */
int d1, d2; /* oprand number */
int result; /* store the expression result */
int index;
if (exp == NULL || o_value == NULL) {
return -1;
}
index = 0;
if (get_oprand(exp, &index, &result) == -1) {
return -1;
}
/* conjunction operation */
while (get_end(exp, &index) == -1) {
/* two oprands operation */
d1 = result;
if (get_operator2(exp, &index, &op) == -1) {
return -1;
}
if (get_oprand(exp, &index, &d2) == -1) {
return -1;
}
switch (op) {
case 0:
result = d1 + d2;
break;
case 1:
result = d1 - d2;
break;
case 2:
result = d1 * d2;
break;
case 3:
if (d2 == 0) {
return -1;
}
result = d1 / d2;
break;
default:
return -1;
}
}
*o_value = result;
return 0; /* end of conjunction */
}
int read_line(char *buff, int buf_len)
{
int len;
if (buff == NULL || buf_len <= 0) {
return -1;
}
for (;;) {
if (fgets(buff, buf_len, stdin) == NULL) {
return -1;
}
len = strlen(buff) - 1;
if (buff[len] == '\n') {
buff[len] = '\0';
return 0;
}
/* check for last not terminated line in file */
if (fgets(buff, buf_len, stdin) == NULL) {
return 0;
}
/* line length is greater than buffer */
/* skip rest line content */
for (;;) {
len = strlen(buff) - 1;
if (buff[len] == '\n') {
return -2; /* buffer overflow, skip the whole line */
}
if (fgets(buff, buf_len, stdin) == NULL) {
return -1;
}
}
}
}
int main(void)
{
char cmd_line[1024];
int result;
puts("English Caculator");
puts("Enter an expression");
puts("Ctrl-Z to exit\n");
for (;;) {
printf(": ");
switch (read_line(cmd_line, sizeof(cmd_line))) {
case 0:
break;
default:
case -1:
puts("");
return 0;
case -2:
puts("Buffer Overflow");
continue;
}
if (caculate(cmd_line, &result) == 0) {
printf("'%s' = %d\n", cmd_line, result);
}else {
printf("'%s' = E, Invalid Expression\n", cmd_line);
}
}
}
(2)编译运行
三、总结
(1)上述代码仅供参考,其中还有很多的问题需要修复。(2)若有建议,请留言,在此先感谢!