#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/*
int replace(source_string, search_string, replace_string, start_position, replace_limit, ignore_case, output_buff)
return value : count of replace
*/
int replace(const char *s, const char *find, const char *rep, size_t pos, int count, int ignore, char *buff){
size_t i, len_f, len_r;
int rep_count=0;
int (*cmp)(const char*, const char*, size_t);
cmp = (ignore) ? strnicmp : strncmp;
len_f = strlen(find);
len_r = strlen(rep);
for(i=0;i<pos;i++)//output until start position
*buff++ = *s++;
while(rep_count != count){
if(cmp(s, find, len_f)){ //not match
*buff++ = *s++;
} else { //match
// strncpy(buff, rep, len_r);
// buff += len_r;
for(i=0;i<len_r;i++)
*buff++ = rep[i];
s += len_f;
rep_count++;
}
if(*s=='\0')//end of string
break;
}
while(*s){ //rest string output
*buff++ = *s++;
}
*buff = '\0';
return rep_count;
}
#define MAXLEN 80
#define STACKSIZE 3
int calc(char *str){
/* "(3+5)*7-2" => 54 */
char cstack[STACKSIZE]; /* op stack */
int vstack[STACKSIZE]; /* value stack */
int vsp,csp;
int level;
int sign=0;
int wk=0;
char buff[MAXLEN];
char *p,*pwk,cwk;
/* trim */
for(pwk=p=str;*p;p++)
if(*p=='\t' || *p==' ')
continue;
else
*pwk++=*p;
*pwk=*p;
vsp=csp=STACKSIZE;
cstack[--csp]='@';/* empty mark */
p=str;
while(*p){
if(isdigit(*p)){
if(sign==0)sign=1;
wk=wk*10+ *p++ - '0';
} else { /* Characters except the number of occurrences -> determined the number */
if(sign!=0)vstack[--vsp]=sign*wk; /* push num */
wk=0; /* wk initialize for next step */
sign=0;
switch(*p){
case '*':
case '/':
cwk=cstack[csp];
if(cwk=='@' || cwk=='+' || cwk=='-')
cstack[--csp]=*p;
else{
if(cwk=='*')
vstack[vsp+1]*=vstack[vsp];
else if(cwk=='/')
vstack[vsp+1]/=vstack[vsp];
vsp++;
cstack[csp]=*p;
}
p++;
break;
case '-':
if(str==p){
sign=-1;
p++;
break;
} else if(NULL!=strchr("*/+-",*(p-1))){
sign=-1;
p++;
break;
}
case '+':
cwk=cstack[csp];
if(cwk=='@')
cstack[--csp]=*p;
else {
switch(cwk){
case '+':
vstack[vsp+1]+=vstack[vsp];break;
case '-':
vstack[vsp+1]-=vstack[vsp];break;
case '*':
vstack[vsp+1]*=vstack[vsp];break;
case '/':
vstack[vsp+1]/=vstack[vsp];break;
}
vsp++;
cstack[csp]=*p;
}
p++;
break;
case '(': /* (expression) -> call calc(expression) */
p++;
level=1;
sign=1;
for(pwk=buff;*p;p++){
if(*p==')'){
if(--level==0){
*pwk='\0';
wk=calc(buff);
break;
}
} else if(*p=='('){
level++;
}
*pwk++=*p;
}
if(level){/* paren unmatch */
*pwk='\0';
wk=calc(buff);
} else
p++;
break;
case ')':/* never */
p++;
fprintf(stderr,"too many ')'\n");
break;
default:
fprintf(stderr, "'%c'is not allowed\n",*p++);
}
}
}
vstack[--vsp]=sign*wk;
while('@'!=(cwk=cstack[csp++])){
switch(cwk){
case '+':
vstack[vsp+1]+=vstack[vsp];break;
case '-':
vstack[vsp+1]-=vstack[vsp];break;
case '*':
vstack[vsp+1]*=vstack[vsp];break;
case '/':
vstack[vsp+1]/=vstack[vsp];break;
}
vsp++;
}
return (vstack[vsp]);
}
int main(void){
int x = 3, y;
char str[128];
char buff[128];
char strX[16];
sprintf(strX, "%d", x);
gets(str);
replace(str, "x", strX, 0, -1, 1, buff);
y = calc(buff);
printf("%d\n", y);
return 0;
}
DEMO
>calc
x + 3
6
>calc
x * x + 2 * x + 1
16
>calc
(3+5)*7-2
54
gets(). It can't be used safely and it will no longer be part ot the C language once the upcoming Standard is published and adopted by compilers.