mathemathecal expression | | |
hello, i thought it was wise to include my program. my main problem is
i wantto adapt the program to do only multiplication
,division,addition, and subtraction and what ever i do there is an
error.However, i also think my program is too long and so if someone
has written a shorter one i will be grateful.here is the program.
#include <string.h>
#include <iostream.h>
namespace
{
const int maxLength = 82; // including end character and the zero
character
const char finishLoopChar = '$';
// Input and error atlets
const char AnExpr[] = "Please give An Expression,and then press the
ENTER key:";
const char Answer[] = " The Answer is: ";
const char DivByZero[] = "WARNING!!!:No Division by Zero;Check
answer.";
const char FloatPtNo[] = "WARNING!!!:No decimal points
allowed,discarded,please Watch out for Answer.";
const char ExpNeg[] = " Negative exp is not allowed,Watch out for
answer";
const char wrongSyntax[] = "WARNING!!!:Wrong syntax,please review
input and Watch out for answer!";
//operations and Levels of operation
const operatorLevels = 4; // including exponents and mod(not asked,but
derived from discussion with friends)
const opsPerLevel = 2; // Two operations with same precidence on
same level
const char operatorTable[operatorLevels][opsPerLevel] = {{'e', '^'},
{'*','/'}, {'%','m'}, {'+','-'} };
//Function declarations
long polyno(long base, long exp);
bool searchOperator(char* line, char &curOp, int &curOpPos);
long doTask(long operand1, long operand2, char operation);
bool verArray(const char array[operatorLevels][opsPerLevel], char
testChar);
int goToOp1(char* line, int startPos, int &curExprBegin);
int goToOp2(char* line, int startPos, int &curExprEnd);
void shortArray(char* line, int curExprBegin, int curExprEnd, long
number);
void discardBadChar(char* line, bool &exit);
void errorOutput(const char* erroralert);
//Function definitions
int length(long number) //how long is the number
{
int i=0;
int answer=0;
if (number <= 0 ) {
answer=1;
number *= -1;
}
while (number >= polyno(10,i)) i++;
return answer + i;
}
void errorOutput(const char* errorAlert) //write error alerts
{
cerr << errorAlert << endl;
}
bool verArray(const char array[operatorLevels][opsPerLevel], char
testChar) //Check if char "test" is in array
{
int i=0;
int j=0;
while (i < operatorLevels) {
if (array[i][j]==testChar) return true;
j++;
if (j == opsPerLevel) {
j=0;
i++;
}
}
return false;
}
//Function definitions
long doTask(long operand1, long operand2, char operation) //evaluation
of operations
{
switch (operation) {
case '*': return operand1 * operand2;
case '/': if (operand2==0) {
errorOutput(DivByZero);
return 0;
}
else return operand1 / operand2;
case '%':
case 'm': if (operand2==0) {
cerr << DivByZero << endl;
return 0;
}
else return operand1 % operand2;
case '+': return operand1 + operand2;
case '-': return operand1 - operand2;
case '^': return polyno(operand1,operand2);
case 'e': return operand1*polyno(10,operand2);
default : return 0;
}
}
long polyno(long base, long exp) //Calculate powers
{
if (exp < 0) errorOutput(ExpNeg); //Prevent floating point answers
long answer = 1;
while (exp > 0) {
exp--;
answer = answer * base;
}
return answer;
}
//Function definitions: string processing
int goToOp1(char* line, int startPos, int &curExprBegin) //Detect left
operant
{
int pos=startPos-2;
int op1Size=0;
int answer;
answer = 0;
//Construct operand until another operator or begin of line reached
while ((pos>=0) && (verArray(operatorTable, line[pos])==false)) {
answer = answer + (line[pos] - '0') * polyno(10,op1Size);
op1Size++;
pos--;
}
if ((line[pos]=='-') && ((verArray(operatorTable, line[pos-1])) ||
(pos==0))) { //Detect negative sign
answer*=-1;
pos--;
}
curExprBegin = pos + 1;
return answer;
}
int goToOp2(char* line, int startPos, int &curExprEnd) //Detect right
operant
{
int pos=startPos;
int answer=0;
int factor=1;
if (line[startPos]=='-') { //Detect negative operand
factor=-1;
pos++;
}
//Construct operand until another operator or end of line reached
while ((line[pos]!='\0') && (verArray(operatorTable,
line[pos])==false)) {
answer = answer * 10 + line[pos] - '0';
pos++;
}
curExprEnd = pos - 1;
return answer*factor;
}
//Overwrite operand1, operator and operand2 by calculation result,
shorten line
void shortArray(char* line, int curExprBegin, int curExprEnd, long
number)
{
char newLine[maxLength];
int oldLinePos=0, newLinePos=0;
while (line[oldLinePos]!='\0') {
if (((oldLinePos < curExprBegin) || (oldLinePos > curExprEnd))) {
newLine[newLinePos]=line[oldLinePos]; //Simple copy from line to
newLine
newLinePos++;
}
else { //Inserting intermediate result number
if (number <0) {
newLine[newLinePos]='-';
newLinePos++;
number*=-1;
}
{ //Block for variable tmpAnswer being valid only in this area
int tmpAnswer;
for (int i=length(number)-1; i>=0 ; i--) {
tmpAnswer = number / polyno(10,i);
number -= polyno(10,i) * tmpAnswer;
newLine[newLinePos] = tmpAnswer + '0';
newLinePos++;
}
}
oldLinePos = curExprEnd;
}
oldLinePos++;
}
newLine[newLinePos]='\0'; //Append null character
strcpy(line,newLine);
}
void discardUnwantedChar(char* line, bool &exit) //Remove invalid
characters
{
int readPos=0;
int insertPos=0;
char lastChar=' ';
while (line[readPos]!='\0') {
if (readPos!=0 && verArray(operatorTable, lastChar) &&
verArray(operatorTable, line[readPos]) && line[readPos] != '-') {
//Check for double operator except *-, +-, --,...
errorOutput(wrongSyntax);
}
else if(((line[readPos]>='0') && (line[readPos]<='9')) ||
(verArray(operatorTable, line[readPos])==true)) {
line[insertPos]=line[readPos];
insertPos++;
}
else {
switch(line[readPos]) {
case ',' :
case '.' : errorOutput(FloatPtNo);
break;
case 'T' : //Transform to lowercase
case 'L' : line[insertPos] = line[readPos] - 'A' + 'a';
insertPos++;
break;
case finishLoopChar : exit = true;
break;
}
}
lastChar = line[readPos];
readPos++;
}
line[insertPos]='\0';
if (verArray(operatorTable, line[0]) && line[0] != '-')
errorOutput(wrongSyntax); //Check for leading operator
if (verArray(operatorTable, line[insertPos-1]))
errorOutput(wrongSyntax); //Check for operator at end of line
}
bool searchOperator(char* line, char &curOp, int &curOpPos)
{
bool answer=false;
int curOpLevel=0;
curOp = ' ';
while ((curOpLevel<operatorLevels) && (answer == false)) { //Check all
operator levels
curOpPos=0;
while ((line[curOpPos] != '\0' ) && (answer == false)) { //Search line
for current operator
if (line[curOpPos]==operatorTable[curOpLevel][0]) {
answer = true;
curOp=operatorTable[curOpLevel][0];
}
else if ((line[curOpPos]==operatorTable[curOpLevel][1]) &&
(curOpPos!=0)) {
answer = true;
curOp=operatorTable[curOpLevel][1];
}
curOpPos++;
}
curOpLevel++;
}
return answer;
}
} //closing unnamed namespace
int main()
{
char line[maxLength];
bool opFound = false;
int curOpPos=0;
char curOp=' ';
int curExprBegin=0, curExprEnd=0;
long operand1, operand2;
bool exit = false;
cout << finishLoopChar << endl; //User friendly opening
while (exit == false) {
cout << AnExpr << endl;
cin.getline(line, sizeof(line)); //Reads maximum maxlength-1
characters and adds \0
discardUnwantedChar(line, exit); //Discard invalid characters from
line
opFound=searchOperator(line, curOp, curOpPos); //Search line for
operator,and keep answer in variable opFound
while (opFound==true) {
operand1=goToOp1(line, curOpPos, curExprBegin); //go to operant 1
operand2=goToOp2(line, curOpPos, curExprEnd); //go to operant 2
shortArray(line, curExprBegin, curExprEnd, doTask(operand1, operand2,
curOp)); //shorten line
opFound=searchOperator(line, curOp, curOpPos); //Search for more
operators
}
cout << Answer << line << endl; //Output answer
}
return 0;
} | | | | re: mathemathecal expression
"stanlo" <mungwest@yahoo.com> wrote in message
news:1105151301.415501.85590@z14g2000cwz.googlegro ups.com...[color=blue]
> hello, i thought it was wise to include my program. my main problem is
> i wantto adapt the program to do only multiplication
> ,division,addition, and subtraction[/color]
As I said in my other reply, start with *one* thing at a time.
Don't try to do it all at once.
[color=blue]
> and what ever i do there is an
> error.[/color]
So what is the error, and where does the compiler say it is?
[color=blue]
>However, i also think my program is too long[/color]
It might or might not be. What *is* a problem is that
it's hardly readable. Use indentation and whitespace
to organize your code. Remember that source code is
primarily for *humans* to read.
[color=blue]
>and so if someone
> has written a shorter one i will be grateful.here is the program.
>
>
> #include <string.h>[/color]
Why don't you use the std::string type instead of struggling
with the error-prone, difficult-for-beginners 'C-style'
strings (arrays of characters)?
[color=blue]
>
> #include <iostream.h>[/color]
This is not, nor has it ever been, a standard C++ header.
The correct header for declaring the standard stream
objects (std::cin, std::cout, etc.) is <iostream>.
No '.h'.
I won't even try to decipher the 'spaghetti' you've posted,
but repeat again: Start Small. One Thing At A Time.
BTW which C++ book(s) are you reading? There are far more
bad ones than good ones available (and unfortunately often
the 'bad' ones are used in shcools). Perhaps that's at least
part of your troubles.
-Mike | | | | re: mathemathecal expression
stanlo wrote:
<snip>
Whoa there Tex!
Examine this rewrite of 'doTask':
<code>
long evaluate(long op1, long op2, char op)
{
long result = 0;
switch (op)
{
case '*':
{
result = op1 * op2;
break;
}
case '/':
{
if (op2==0)
{
errorOutput(DivByZero);
result = 0;
}
else
{
result = op1 / op2;
}
break;
}
case '%':
{
// Whatever '%' was going to do. Modulus?
// You had this falling thru to 'm'. Intended?
// 'm' and '%' synonomous?
break;
}
case 'm':
{
if (op2==0)
{
cerr << DivByZero << endl;
result = 0;
}
else
{
result = op1 % op2;
}
break;
}
case '+':
{
result = op1 + op2;
break;
}
case '-':
{
result = op1 - op2;
break;
}
case '^':
{
result = polyno(op1,op2);
break;
}
case 'e':
{
result = op1*polyno(10,op2);
break;
}
default :
{
result = 0;
break;
}
}
return result;
}
<end code>
( Please no style wars, folks - exaggerated for clarity )
Notes:
- function name more reflective of purpose, self documenting.
- whitespace/indent is your friend.
- well named identifier for return value, self documenting.
- single point of 'return' at end.
- generous use of 'break'.
- easier to pick up missed brackets and semicolons.
- flow control now much more obvious.
This is now a much more debuggable, maintainable, comprehendible,
extensible, tolerable ... it might even work! :-)
You seem to have the basic idea of the project's requirements, and
reading your code I can sense ( and only sense, because of the spaghetti
) that you intuitively know what you're doing.
Good!
Now you have to express that, so
- someone else.
- yourself.
- your future self.
- the compiler
can all be aligned.
Also write, test and evaluate code in small bytes ( pun intended ).
Brick by brick.
There's a heap of other stuff I could probably discuss( eg. why
don't you store your error messages as standard library string types not
char arrays? Heck, you even nearly included the right header! ), but
'nuf for now. I do hope this helps. :-)
--
Cheers
--
Hewson::Mike
"This letter is longer than usual because I lack the time to make it
shorter" - Blaise Pascal | | | | re: mathemathecal expression
hello, i tried use the std and it did not work, so i saw .h in a
book and i tried and it worked. | | | | re: mathemathecal expression
thank u mike i will make a more readible text and post. | | | | re: mathemathecal expression
Mike Hewson wrote:i am reay very grateul or your reply, in fact your
proposition made me nderstood more what i was doing.i think u are right
too about the storing o my error messges.but i don t understand the
altenative u gave me,that is not to use char array, but use standard
libary types. well i make my program better in a moment and post it.[color=blue]
> stanlo wrote:
>
> <snip>
>
> Whoa there Tex!
> Examine this rewrite of 'doTask':
>
> <code>
>
> long evaluate(long op1, long op2, char op)
> {
> long result = 0;
> switch (op)
> {
> case '*':
> {
> result = op1 * op2;
> break;
> }
> case '/':
> {
> if (op2==0)
> {
> errorOutput(DivByZero);
> result = 0;
> }
> else
> {
> result = op1 / op2;
> }
> break;
> }
> case '%':
> {
> // Whatever '%' was going to do. Modulus?
> // You had this falling thru to 'm'. Intended?
> // 'm' and '%' synonomous?
> break;
> }
> case 'm':
> {
> if (op2==0)
> {
> cerr << DivByZero << endl;
> result = 0;
> }
> else
> {
> result = op1 % op2;
> }
> break;
> }
> case '+':
> {
> result = op1 + op2;
> break;
> }
> case '-':
> {
> result = op1 - op2;
> break;
> }
> case '^':
> {
> result = polyno(op1,op2);
> break;
> }
> case 'e':
> {
> result = op1*polyno(10,op2);
> break;
> }
> default :
> {
> result = 0;
> break;
> }
> }
> return result;
> }
>
> <end code>
>
> ( Please no style wars, folks - exaggerated for clarity )
>
> Notes:
>
> - function name more reflective of purpose, self documenting.
> - whitespace/indent is your friend.
> - well named identifier for return value, self documenting.
> - single point of 'return' at end.
> - generous use of 'break'.
> - easier to pick up missed brackets and semicolons.
> - flow control now much more obvious.
>
> This is now a much more debuggable, maintainable, comprehendible,[/color]
[color=blue]
> extensible, tolerable ... it might even work! :-)
>
> You seem to have the basic idea of the project's requirements,[/color]
and[color=blue]
> reading your code I can sense ( and only sense, because of the[/color]
spaghetti[color=blue]
> ) that you intuitively know what you're doing.
> Good!
> Now you have to express that, so
>
> - someone else.
> - yourself.
> - your future self.
> - the compiler
>
> can all be aligned.
>
> Also write, test and evaluate code in small bytes ( pun intended[/color]
).[color=blue]
> Brick by brick.
>
> There's a heap of other stuff I could probably discuss( eg. why
> don't you store your error messages as standard library string types[/color]
not[color=blue]
> char arrays? Heck, you even nearly included the right header! ), but
> 'nuf for now. I do hope this helps. :-)
>
> --
>
> Cheers
> --
> Hewson::Mike
> "This letter is longer than usual because I lack the time to make it
> shorter" - Blaise Pascal[/color] |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,471 network members.
|