First of all, I'm 17 learning C++ on my own! I've been enjoying Daniweb. and I did like to thank the community for that! Thank you all!

Here goes my Problem...
I have a small program that calculates time between two instances
and it worked fine... so I decided to extend it by making a derived class of the base class 'Time' which will hold first, and second Input and the final result. other features later....
here is a screenshot of the first one...

... this one works just fine and nice... its fun. please take note of the ans//the last figures******** Here is a screenshot of the extended program

...the result of the time difference is weirdThe input was the same with the first one... And you can actually see that the first one is correct if you do the calculations... Or whats the time difference between, the inputs Time2 = 3hrs, 4mins, 6sec Time1 = 9mins, 8sec isn't it Time difference = 2hrs, 54mins, 58sec as shown in the first screenshot... but the second is weird and nothing was changed in the base class! The first Screenshot was a direct interaction with the base class 'Time' no derived at that time. #include "time.h" The second is purely using the derived class 'Timer'...#include "timer.h" Its a multifile program... but I copied only relevant stuff here Now here is a well documented code,truncated a lot to save space, but all required info are here ...Actual total lines is about 860

/////////////Time class/////////////////////////////////////
class Time{
private:
    int yr;     int mnth;       int day;
    int hr;     int min;        int sec;
    short currentState;         //state, whether calculation is good or weird
    //0, if good i.e everything is ok
    //1, if the time value is weird such as 63sec, 20 000years etc
protected:
    bool order(const Time& t1, const Time& t2);   //For checking subtraction
                                                  //order or which is greater
                                                  //.. of t1, and t2
public:

    Time() : yr(0), mnth(0), day(0), hr(0), min(0), sec(0)
    { currentState = 0; }     //Constructor, initializes everything to zero
    
    Time(int y, int mn, int d, int h, int m, int s) :
            yr(y), mnth(mn), day(d), hr(h), min(m), sec(s)
    { currentState = 0; }     //Direct Call, Constructor 6 args

    void getInput();        //gets user input according to the parameter passed
                            //by getTime
    void getTime();         //Gets Time, Uses switch and calls getInput
                            //The rest of the Member Functions are Modifier Functions

    void validate();        //Checks User input and
                            // modifies "currentState" appropriately
                            
    void display();         //For displaying output
    Time operator - (Time& t2);     //For calculating time difference

    int State(){
        return currentState;
    }

};

////////////////////////////an Implementation///////////////////

Time Time::operator - (Time& t2){

    bool state;
        Time t1;
    state = Time::order(*this, t2);    //State will be true if t1 > t2
                                    //in that case, subtract directly
                                    //If state is false, Swap Time so that
                                    //We can have t1 > t2
                                    //THIS IS TO PREVENT NEGATIVE NUMBERS

    //Check Order of Subtraction
    if(state == false) timeSwap(*this, t2);
    //calls a fuction that swaps their values

    //Seconds
    if(sec > t2.sec) t1.sec = sec - t2.sec;
    else if(sec < t2.sec){
        min -= 1; t1.sec = 60 + sec - t2.sec;}

    //Minutes
    //Same things go on here
    
    //Hours
    //Same things go on here
    
    //Day
    if(day > t2.day) t1.day = day - t2.day;
    else if(day < t2.day){
        mnth -= 1; t1.day = 30 + day - t2.day;}//Add 30 days, reduce t1 by a month

    //Month
    //Same things go on here

    //Year
    //Same stuffs........


    //
        return t1;
}


////EXTENDED PART OF THE PROGRAM//////////!!!!!!!!!!!!!!!!!!
/////////////////////////Timer class//////////////////////////////////
//Actually I don't know a better name to call this class
// suggestions will be appreciated
const int LIMIT = 1000;
class Timer : public Time {
        private:

                static int count;
                char description[LIMIT];
                Time *time1;
                Time *time2;
                Time *time_diff;
        protected:
                void calculate();		//Called for calculating time_diff
        public:
                Timer()					//no-arg constructor
                { time1 = new Time;		//Create new instances for all time
                  time2 = new Time;
                  time_diff = new Time;
                        count++; }

                static int return_count();//shows number of calculations so far
                void get_time();		//Gets input from User
                void show_all();		//Shows all Time for object + desciption
                
                ~Timer()
                { delete time1;			//Destructor, Deletes objects memory
                  delete time2;
                  delete time_diff;
                }

};

////////////////Some Timer definition/////////////////////
//PROTECTED for calculating time_diff;
void Timer::calculate()
        {
                //Time_diff
        //Remaining Time
        *time_diff = *(time1) - *(time2);
        time_diff->validate();                        //Validate;
        }
//For calculating time
void Timer::show_all()
        {
                //cout <<"\n---" << description <<"---\n";
                cout <<">>>Time (1):\n";
                time1->display();
                cout <<"\n>>>Time (2):\n";
                time2->display();
                cout <<"\n>>>Time Difference<<<\n";
                time_diff->display();
                cout <<"\n-------------------------------"<< endl;
        }


//Gets time input from user
void Timer::get_time()
        {
                do
                {
                cout <<"Enter Values for Time 1"<<endl;
                time1->getTime();                           //Get Time
                time1->validate();                          //Make sure it is valid
                }   while(time1->State() == 1);

                do
                {
                cout <<"\n***Enter Values for Time 2>>>>\n";
                time2->getTime();                           //Get Time
                time2->validate();                          //Validate it
                }   while(time2->State() == 1);

/////////////////MY PROBLEM HERE!!!
///Why does the program program become weird after this stage... and giving me
///very werid result?
                cout <<"\n   Enter Comment:";
                cin.getline(description, LIMIT, '\n');//**THIS LINE DOESN'T
                                                      //EVEN GET EXECUTED!
                
                Timer::calculate();
                //This function now behaves weird.
                
        }

        
int main(){
    const int rounds = 10;
    int redoState = 0;
    int n = 0;
    Timer session[rounds];
    //some intro and info here
    do{
           cin >> choice; cout << endl;
                switch(choice)
                        {
                            case 'm':
                                 session[n].get_time();
                                 break;
                            case 's':
                                 session[n].show_all();
                                 break;
                            case 'i':
                                 cout<<"  Round:";
                                 n = Input();
                                 n -= 1;
                                 break;

                            default:
                                 cerr <<"\nERROR: Bad choice or Selection!\n";
                                 break;

                        }

        cout<<"\n\n\nContinue?\nEnter 1 for yes\nEnter 2 for no(Exit)\n";
        cout <<"Option:";

        redoState = Input();
    } while(redoState != 2);

    return 0;
}

all necessary headers are are in place... I'm not a complete beginner or maybe...in the eyes of geeks.
I plan to integrate a UI and upload it on sourceforge if I canI'm beginning to get frustrated, or do I rewrite (Timer) from scratch in a better way I'm thinking...?
*Also What kind of bug do you classify the program's problem into?

Recommended Answers

All 4 Replies

>>What kind of bug do you classify the program's problem into?
const-correctness.

>>I plan to integrate a UI and upload it on sourceforge if I can
It's good to do these little projects as learning experiences, but don't mislead yourself into thinking that this kind of code would be worth anything to others. For instance, the Boost.Date-Time library is much more feature-rich and professionally implemented. Sorry for this, but the truth is better than wishful thinking. But keep up with it, as a learning experience.

Now, for my (constructive) remarks on your code:

- The Timer class is not a time, it has records of time. This means that inheritance is misplaced here. Timer should not inherit from Time. It should contain time records, which it does and that is good.

- Don't use dynamic allocation when it is clearly not necessary. You Timer class holds the Time records via pointers that it deletes upon destruction. That is very wrong. There is no reason, as far as I can see, why they could not be held by value. As it is now, you have a bug because you did not respect the rule of Three in C++. The compiler is going to supply the Timer class with a default implementation of the copy-constructor and assignment operator which will both be problematic since they will do a simple copy of the pointers (not of the pointed-to objects). When two copies of a Timer object get deleted, your program will crash. If you store the Time records by value, this won't be a problem (and you won't even need the destructor of Timer), always favour stored-by-value over stored-by-reference or pointer in a class (C++ has value-semantics for a good reason!). This is basically RAII (Resource Acquisition Is Initialization), which is arguably the single most important and powerful design pattern in C++.

- Your type for the "description" data member is bad. First of all, in C++, prefer to use the better tools that C++ offers, in this case, std::string (#include <string>). Second, since you are holding this static array of char by value in the class, you are making this Timer class unnecessarily large (storing a std::string will be much better).

- Const-correctness: You should read up on the topic of const-correctness in C++. When designing this kind of class, it can help identify certain bugs very easily by forcing yourself to obey your own rules of constness. In a nutshell, you need to qualify member functions and parameters with a const keyword when it does not make any sense for them to be modified in that function's body. Many of your functions should be const (like display, getStatus, etc.), and so should the substraction operator. I have easily spotted several instances of unintentional modifications that could be the source of the problem.

- Line 161 does execute, but you have a stray newline character on the input stream (because inputting numbers does not eliminate the newline character for the stream). So, after you have input a number from cin, you should call cin.ignore() to ignore whatever is left on the input stream. Also, if you change the "description" variable to std::string, you will need to use another version of getline, as such: std::getline(cin, description, '\n'); .

- Try to use more sensible names. For instance, your "order" function really is just a less-than operator, it probably should be implemented as such (it also should be a public friend free-function, not a member function). One might think that "order" somehow reorders the times, but it simple checks that they are in the right order (but what does that even mean?). Similarly, functions like getInput and getTime seem ambiguous, what's the difference? Shouldn't there be just one function with clear semantics.

- Design-wise, you are exporting, out of the Time class, the handling of the validity of the Time it holds. Why? OOP should favour encapsulation as much as possible. Shouldn't the getTime function do the looping that verifies the validity of the input time. Why should the user care whether times are valid or not? This should be encapsulated (and throw an exception if invalid operations are attempted).


That's it for now. I would suggest you make those changes and I'm sure, by that time, the small bug will be apparent (especially once const-correctness is respected).

Thanks a lot Mike!
I really appreciate this!
I will take all you said into deep practice.
I guess it is advisable to
1. get all the fundamentals of C++
2. learn the STL and how to use them completely!
3. learn to use libraries like Boost(free)
4. Checkout some source code of simple programs
5. ...then you can try modifying some of those codes

Info: Is the ordered list above Ok? if not please add; :-)
Question:With consistency and dedication, is it possible to realize these in 2months all on my own? ...I started learning C++ this year and all I've been doing is making some BASIC crazy console programs ...thinking I've almost arrived! till I realized there is never an end to programming!
Question: Do you recommend I also learn C programming in linux ...I'm a fan of Open-source ...I can handle that... I'm a very quick learner.
Question: does C++ has a stand in Web technologies... such as server utilities? It seems only C has a ground on that.
Question:
Also... I'm very interested in web programming. Will being a C++ pro help me when I eventually venture into web technologies and Programming.. perl, php, varnish-cache, etc. and other server side .... blah blah

Just realized programming is a though JOB, now I know why many cool software are expensive... with hundreds of thousands to millions of lines of interconnected and bug free code! darn! I wish to join someday... Oh! I t took them PROFESSIONAL years...

OK I will discard this program, after getting solid foundation on C++ OOP skills, I will try a better one... probably next

DaniWeb is the coolest forum site! What have I been doing getting frustrated most of the time?!
Thanks a lot Mike... you're real good! and a teacher

Glad to help!

To answer your questions:

>>Is the ordered list above Ok? if not please add; :-)

It seems good to me. You probably should interleave it with "Challenge yourself and do cool things that are interesting to you". That pretty much fits in-between each point on that list. It is very important for sustained interest and to learn by experience. It is by making mistakes (like the bugs you had in that code) that you learn the value of certain techniques (like RAII and const-correctness in this case).

>>With consistency and dedication, is it possible to realize these in 2 months all on my own?

With consistency and dedication I realized those things after several years. Read this article for example. This pretty much applies to me, but I also did many mistakes (what I like to call "reinventing the wheel, making it square and breaking your back using it"). Never say "I know best", always look around at what is available and how people solve certain problems before tackling them yourself, it will avoid you a lot of pain and should speed things up.

>>...thinking I've almost arrived! till I realized there is never an end to programming!

Isn't that the fun part? You can never stop learning and improving as a programmer, never. Every year since I have started programming, I can look back at the stuff I programmed a year before and be disgusted by the poor quality of it. And that is still the case today (after some 12 years or so).

>>Do you recommend I also learn C programming in linux

I recommend learning C/C++, period. Cross-platform development is the only reasonable way to do general-purpose programming (don't use platform-specific code unless you have to get real "close to the metal"). But, surely, Linux is a great platform to develop on, especially for the open-source stuff. If there is one platform you could dedicate to, it is that one.

>>I'm a fan of Open-source

Then, join an open-source project, there are tons of them on source-forge.

For the Web development stuff, I really have no idea about that, it's far from my field.

>>Just realized programming is a though JOB

Nothing is easy!

>>DaniWeb is the coolest forum site! What have I been doing getting frustrated most of the time?!

Come back anytime!

Thanks a lot, the article was helpful.
I guess I had the feeling that any new stuff I think of, If I don't know how to go about it, Someone else will surely execute such project. I mean, get ideas, write them down but totally blank on what to do or when you will ever be able to know the core. Definitely, someone else will.
>>>>>>
You know, today, I started on STL and was feeling dumb cause most of the algorithms I've written to fit some of my small programs, are all in the STL!!!
really good and easy, except for the complexity of iterators and "Data Structures(containers) and Algorithm"... well from that article, I will take my time learn it and write as many small and better programs as I can write, so as to get used to many class libraries... as for boost::... I don't know how to learn using it... OK ONE AT A TIME!

Yups I downloaded some C++ source code for some calculators and other little programs ... Its amazing that they use a lot of different library codes. The problem is the codes aren't even straightforward... cause the codes are not well commented and They probably expect you to know. ok I will enjoy and take it easy.
not to be narrowly minded... started learning Blender3D, GIMP, Inkscape and Adobe After Effects... Great talking to you

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.