views:

565

answers:

5

Hello all, I'm doing a polynomial calculator and i'll need some help as i'll progress with the code.

For now I made only the polinom class which i represented it as a linked list with terms and some functions(only read and print the polynomial functions for now).

Here's the main program which for now only read a polynomial and prints it:

#include "polinom.h"

int main()

{

polinom P1;
bool varStatus = false;
char var = '\0', readStatus = '\0';

cout << "P1 = ";
P1.read(readStatus, var, varStatus); // i don't need readStatus yet as i haven't implemented the reset and quit functions 

cout << "\n\nP = ";
P1.print(var);

getch();
return 0;
}

And the header file polinom.h:

#ifndef _polinom_h
#define _polinom_h

#include <iostream>
#include <list>
#include <cstdlib>
#include <cctype>
#include <cstdio>
#include <conio.h>


using namespace std;

class polinom 
{
class term
{
    public:
        int coef;
        int pow;

        term() 
        {
            coef = 1;
            pow = 0;
        }    
};

list<term> poly;
list<term>::iterator i;

public:

    bool printable(char c) 
    {

        return (
                  ((int(c) > 42 && int(c) < 123) || isspace(c)) && int(c) != 44 && int(c) != 46 && int(c) != 47 && 
                  int(c) != 58 && int(c) != 59 && 
                  int(c) != 60 && int(c) != 61 && int(c) != 62 && int(c) != 63 && int(c) != 64 && int(c) != 65 && 
                  int(c) != 91 && int(c) != 92 && int(c) != 93 && int(c) != 95 && int(c) != 96
                ); 
    }


    void read(char &readStatus, char &var, bool &varStatus)
    {

        term t; // term variable to push it into the list of terms
        char c, lc, sign; // c = current char, lc = lastchar and sign the '+' or '-' sign before a coefficient
        int coef, pow; //variables to pass the coef and power to term t
        bool coefRead = false, powRead = false; //reading status of coef and power 

        while (c != '\r') { //we read characters until carriage return
            c = getch(); // get the new imputed char

            if (tolower(c) == 'r' || tolower(c) == 'q') { //if the user inputed r or q we reset the input or quit the program
                    readStatus = c; //pass current char value to readStatus so the program will know what to do next
                    return; //aborting the reading process
            }

            else 
            {
                if (printable(c)) cout << c; //print on screen only the correct characters

                if (!coefRead && !powRead) //we set term coef to the inputed value
                {                    
                    if (isdigit(c)) { 
                        if (isdigit(lc)) coef = coef * 10 + int(c); //if the last char was also a digit we multiply the last value of coef by 10 and add current char
                        else {                                    
                            if (sign == '-')  coef = -(int(c));//if the current coef has '-' before we set coef to it's negative value 
                            else              coef = int(c);   //this means a new term's coef is read
                    }
                    if (!isdigit(c) && isdigit(lc)) coefRead = true; //if the last char was a digit and we reached the var name we stop reading the coefficient
                }

                else if (coefRead && !powRead) //after coefficient is read we get the term's varname and power 
                {
                    if (isdigit(c)) { // just like in the case with coefficient we read the power until the current char is not a digit
                        if (isdigit(lc)) pow = pow * 10 + int(c);
                        else pow = int(c);
                    }

                    else if (isalpha(c) && isdigit(lc) && !varStatus) { //if the last char was a digit and the current not we reached the var name
                    var = c;                                            //also even though the variable is inputed more than once we save it only once
                    varStatus = true; //we mark the var name as read
                    }
                    else {
                        if (isdigit(lc)) powRead = true;
                    }   
                }

            else {
                if (c == '+' || c == '-') { // if a sign was inputed it means a new term is coming and we push the current term to the list and reset 
                    t.coef = coef;          // coefRead and powRead so we can read another term 
                    t.pow = pow;
                    poly.push_back(t);
                    sign = c;
                    coefRead = false;
                    powRead = false;
                }
            }

           lc = c; // we save the last character

            }
        } 
    }

    void print(char var)
    {
        for ( i=poly.begin() ; i != poly.end(); i++ ) { //going through the entire list to retrieve the terms and print them 

            if (i == poly.end() - 1) { // if we reached the last term 
                if (*(i->pow == 0) //if the last term's power is 0 we print only it's coefficient
                    cout << *(i->coef);
                else 
                    cout << *(i->coef) << var << "^" << *(i->pow); //otherwise we print both
            }

            else {
                if (*(i->coef > 0) //if the coef value is positive 
                    cout << *(i->coef) << var << "^" << *(i->pow) << " + "; //we also add the '+' sign
                else 
                    cout << *(i->coef) << var << "^" << *(i->pow) << " - "; // otherwise we add '-' sign
            }
        }
    }

};


#endif                    

EDIT

All compile errors fixed now thanks to JonH, but the read function is not working as the input characters aren't correctly inserted into the list. I know it may be trivial for you guys, but it would be great if you help me out.

Thanks!

+1  A: 

Those compile errors surely has a line number associated to them in the error message. Have you tried looking at the line indicated to see what is missing? If that does not help, please post the complete error output from the compiler so that we can se what the error is.

Anders Abel
Ok i edit and posted the complete error messages
Vlad
@Vlad - see my answer below you were missing 2-3 braces, when code starts looking like this it is ok to comment after an end curly brace`if (blah) { //lots and lots of code }//end if ... this is ok to do`
JonH
@JonH see my comment to your answer please
Vlad
+2  A: 

Your fundamental problem is that you wrote a bunch of code down without testing it piece by piece, without thinking about it. When you write as a beginner, you should try adding one little bit at a time and making sure it compiles. Even as an advanced programmer, modularization is an extremely important part of the design and code-writing process.

That said, here are a few tips about your posted code in particular:

  1. Your function printable is ugly as sin, and therefore impossible to debug or understand.
  2. The number of nested if statements is indicative of design flaws.
  3. You're missing an end brace on your if (isdigit(c)) statement.
  4. Declaring (and especially initializing) multiple variables on the same line is bad form.
Seth Johnson
Re: 1. That function is clearly just checking ASCII codes to determine if a character is printable or not. It basically says that `c` is between `*` and `(` (exclusive) or is a space and is not among a finite list of characters to exclude. It is ugly, and poorly written, and coud be improved significantly but it is neither impossible to understand nor debug. I agree with the rest of your points.
Jason
I'm impressed that you have the entire ASCII table memorized. Impossible was a strong word, perhaps, but when your code is obfuscated by translating `char`s into their `int` values, and when you chain a hundred logical tests together, something very wrong could easily go unnoticed. That is what I meant.
Seth Johnson
@Seth - memorizing the ASCII values isn't hard at all.
JonH
@JonH: Perhaps not, but there are far more useful things to memorize when you can just do `if (c >= 'a' || c <= 'z')`.
Seth Johnson
@Seth true but it still isnt difficult considering 'A' = 65 and the difference between 'A' and 'a'=97 is 32 so one could easily write a loop to accomplish an entire table.
JonH
+1  A: 

You are missing a few curly braces in your read function.

I redid it here:

 void read(char &readStatus, char &var, bool &varStatus) 
{ 

    term t; // term variable to push it into the list of terms 
    char c, lc, sign; // c = current char, lc = lastchar and sign the '+' or '-' sign before a coefficient 
    int coef, pow; //variables to pass the coef and power to term t 
    bool coefRead = false, powRead = false; //reading status of coef and power  

    while (c != '\r') { //we read characters until carriage return 
        c = getch(); // get the new imputed char 

        if (tolower(c) == 'r' || tolower(c) == 'q') 
        { //if the user inputed r or q we reset the input or quit the program 
                readStatus = c; //pass current char value to readStatus so the program will know what to do next 
                return; //aborting the reading process 
        } 

        else  
        { 
            if (printable(c)) 
               cout << c; //print on screen only the correct characters 

            if (!coefRead && !powRead) //we set term coef to the inputed value 
            {                     
                if (isdigit(c)) 
                   {  
                    if (isdigit(lc)) 
                       coef = coef * 10 + int(c); //if the last char was also a digit we multiply the last value of coef by 10 and add current char 
                    else 
                      {                                     
                        if (sign == '-')  
                           coef = -(int(c));//if the current coef has '-' before we set coef to it's negative value  
                        else              
                           coef = int(c);   //this means a new term's coef is read 
                      } //end else 
                    }//end if isdigit(c)
                if (!isdigit(c) && isdigit(lc)) 
                   coefRead = true; //if the last char was a digit and we reached the var name we stop reading the coefficient 
            }  //end if

            else if (coefRead && !powRead) //after coefficient is read we get the term's varname and power  
            { 
                if (isdigit(c)) 
                   { // just like in the case with coefficient we read the power until the current char is not a digit 
                    if (isdigit(lc)) 
                       pow = pow * 10 + int(c); 
                    else 
                         pow = int(c); 
                    } 

                else if (isalpha(c) && isdigit(lc) && !varStatus) 
                     { //if the last char was a digit and the current not we reached the var name 
                         var = c;                                            //also even though the variable is inputed more than once we save it only once 
                          varStatus = true; //we mark the var name as read 
                     } 
                else 
                     { 
                     if (isdigit(lc)) 
                        powRead = true; 
                     }    
            } //end else if 

        else 
             { 
             if (c == '+' || c == '-') 
                { // if a sign was inputed it means a new term is coming and we push the current term to the list and reset  
                  t.coef = coef;          // coefRead and powRead so we can read another term  
                  t.pow = pow; 
                  poly.push_back(t); 
                  sign = c; 
                  coefRead = false; 
                  powRead = false; 
                } 
              } 

       lc = c; // we save the last character 

        } //end else
    }  //end while
} //end function

EDIT

I also fixed the print function:

 void print(char var) 
    { 
        for ( i=poly.begin() ; i != poly.end(); i++ ) { //going through the entire list to retrieve the terms and print them  

            if (i == poly.end()) { // if we reached the last term  
                if (i->pow == 0) //if the last term's power is 0 we print only it's coefficient 
                    cout << i->coef;
                else  
                    cout << i->coef << var << "^" << i->pow; //otherwise we print both 
            } 

            else { 
                if (i->coef > 0) //if the coef value is positive  
                    cout << i->coef << var << "^" << i->pow << " + "; //we also add the '+' sign 
                else  
                    cout << i->coef << var << "^" << i->pow << " - "; // otherwise we add '-' sign 
            } 
        } 
    } 
JonH
well thanks for your help, but now it says that the use of unary * is illegal and also no match for operator poly.end() - 1
Vlad
@Vlad those are additional errors, this clears up only the error about braces.
JonH
@vlad you called poly.end(), does that even exist ?
JonH
yes it return the end of the list, see http://www.cplusplus.com/reference/stl/list/
Vlad
@vlad - one error might complain about something that doesn't seem to be an error. Look at this line: `if (*(i->pow == 0) //if the last term's power is 0 we print only` this will cause an error as this * is illegal within the context you are using it for. You are also missing a ) in your if condition
JonH
@vlad my advice would be to get rid of all of this code and write one function at a time. Do a little and compile a lot. Fix the bugs then add more code. You are adding more and more to this and you haven't fixed the initial bugs causing it to complain about stuff that might not even be wrong such as poly.end(). fix that if condition in the comment I just made and recompile.
JonH
well i'm testing the read function by printing the content of the list
Vlad
Also the print function is entirely wrong. Pow and Coef don't exist for object i.
JonH
well as i far as i know i->coef and i->pow points to the term[i].coef and term[i].pow
Vlad
BTW i fixed the unary error by removing the use of *, as i forgot that -> already means it points to a value.
Vlad
@Vlad see my edit in this post I fixed the print function you cannot do *i->pow...it *this.property is the same as this->property not *this->property.
JonH
Ah, i saw a little later that you did the same thing.Well atleast i don't have any compiler errors anymore but it seems the read function doesn't do as it should.
Vlad
@Vlad - yep that is an entire different monster, you have to debug it, the main thing is we cleared up a lot of errors. Do you know how to use a debugger and add watches to watch variables? Your read function is a little strange =).
JonH
Why do you think it's strange?
Vlad
+9  A: 

I found MANY missing curly braces and closing parens all throughout your code. After having spent several minutes fixing at least 10 of these, I thought you would be better served if I helped you to learn to fish, rather than giving you fish for tonight's dinner.

Your code is written like a stream of consciousness. As you are building your code your mind jumps around, thinking of other things you need to build and new requirements introduced by whatever you just wrote. When you think of these things, you go write them and come back to where you were. Before you know it, you have written hundreds of lines of code by jumping around, writing bits here and there. The problem with this is that you can't possibly keep juggling sections of code like this without missing little syntax bits along the way.

You should take a more iterative approach to writing code. How exactly you do this will come with experience, but here's some guidance:

  1. Start by stubbing out a class declaration with a few (preferably 1) core methods and member variables.
  2. Compile. You'll get linker errors and the like, but you shouldn't get any syntax errors like missing parens or semicolons. Fix any you do find before moving on.
  3. Implement the methods/functions you just stubbed. Compile & fix non-linker errors.
  4. As you think of minor or dependant requirements that came up during the above steps, write comments in your code, like // TODO: Implement bool DoTheThing(int); But don't implement them yet.
  5. Loop back to step 1, keeping the scope of what you're working on as limited and fundamental as possible. Never move beyond a compilation step without a clean compile.

Repeat until you have implemented everything. You might compile 50 times or more during this process.

John Dibling
Good answer. It gets to the root of the problem and suggests a long-term solution. You can see already from another answer that specifically fixing the compile errors doesn't help the asker because then he immediately runs into another error and still has no idea what to do.
indiv
@indiv - Saying that it doesn't help is probably not right as it certainly just helped the poster out. You can easily still try to help and explain things as I have done in the code along with comments. That is why we have comments as well.
JonH
A: 

Ok, i changed the reading function and here it is:

  void read(char &readStatus, char &varName, bool &varStatus) 
{ 
    term t; // term variable to push it into the list of terms 
    char c, lc = '=', sign = '+'; // c = current char, lc = lastchar and sign the '+' or '-' sign before a coefficient 
    int coef = 0, pow = 0; //variables to pass the coef and power to term t 
    bool coefRead = false, powRead = false; //reading status of coef and power  

     while (c != '\r') { //we read characters until carriage return 

     c = getch(); // get the new imputed char 
     if (tolower(c) == 'r' || tolower(c) == 'q') 
     { //if the user inputed r or q we reset the input or quit the program 
            readStatus = c; //pass current char value to readStatus so the program will know what to do next 
            return; //aborting the reading process 
     } 

     else  
     { 
            if (printable(c)) cout << c; //print on screen only the correct characters 

            if (!coefRead) 
            {
                if (!isdigit(lc)) {
                    if (lc == '+' || lc =='-') sign = lc;

                    if (isdigit(c) && (lc == '=' || lc == ' ' || lc == sign)) {
                        if (sign == '-') coef = -int(c);
                        else             coef = int(c);
                    }
                }

                else {
                    if (isdigit(c)) {
                        if (coef > 0) coef = coef * 10 + int(c);
                        else          coef = coef * 10 - int(c);
                    }

                    else { 
                        coefRead = true;
                        if (!varStatus && isalpha(c))
                            varName = c;
                    }
                }
            }

            else 
            {
                if (!powRead) {
                    if (isdigit(c)) {
                        if (lc == '^') pow = int(c);

                        else if (isdigit(lc)) pow = pow *10 + int(c);
                    }

                    else {
                        if (c == '+' || c == '-') {
                            sign = c;
                            powRead = true;
                        }
                    }
                }

                else {
                    t.coef = coef;
                    t.pow = pow;
                    poly.push_back(t);
                    coefRead = true;
                    powRead = true;
                }
            }
        }
        lc = c;
    }
}

But I don't see what's wrong with it and debugging it doesn't work!

Any help please?

Vlad
@Vlad - Why doesnt debugging work? And what is it not doing, can you tell us what it is outputting so far? I think I've helped you through most of your bugs (unfortunately with no upvotes :-|) and doing anymore is just takign a lot of time.
JonH
JonH did you received my question through your contact form on your site?
Vlad