maemo.org - Talk

maemo.org - Talk (https://talk.maemo.org/index.php)
-   Development (https://talk.maemo.org/forumdisplay.php?f=13)
-   -   Help with a small problem in C++ (https://talk.maemo.org/showthread.php?t=91868)

bandora 2013-11-26 06:30

Help with a small problem in C++
 
Hey guys,

In the past you guys have been extremely generous and helpful, not to mention very informative! And that's the reason why I keep on asking you guys for help! So I want to thank you guys in advance for your help!

Ok onto the problem... I am creating a program for my C++ class that asks for a movie name and a bunch of ratings twice.. Then displays the average rating for each movie.. I got the code to work but with one small issue.. It only takes the first string from the cin.. So like if someone enters "American Pie" for example it will only read it as American... Now I managed to go around the issue and by using a small while loop and that worked for the first movie but it messed up the second cin...

Here's the code so you can see what I'm talking about:

Code:

#include <iostream>
#include <string>

using namespace std;

class Movie
{
private:
        string movieName, MPAARating;
        int numRate[5];

public:
        Movie(string movie)
        {
                movieName = movie;
                MPAARating=5;
                numRate[0]=0;
                numRate[1]=0;
                numRate[2]=0;
                numRate[3]=0;
                numRate[4]=0;
        }

        Movie() // Default Constructor
        {
                MPAARating=5;
                numRate[0]=0;
                numRate[1]=0;
                numRate[2]=0;
                numRate[3]=0;
                numRate[4]=0;
        }
       
        string getMovieName()
        {
                return movieName;
        }
       
        void setMovieName (string str)
        {
                movieName = str;
        }
       
        string getMPAARating()
        {
                return MPAARating;
        }
       
        void setMPAARating (string str)
        {
                MPAARating = str;
        }
       
        void addRating(int num)
        {
                int i = num;
                if( num>0 && num <= 5)
                {
                        this->numRate[i-1]++;
                }
               
                else
                {
                        cout <<"Number out of range."<<endl;
                }
        }
       
        double getAverage()
        {
                double num = numRate[0]+numRate[1]+numRate[2]+numRate[3]+numRate[4];
                double denom = 5.0;
                double result = num/denom;

                return result;
        }
};
       
int main()
{       
        string setMovieName;
        int rating;
        char again = 'y';

        cout << "Insert a movie name: ";
        char c = 0;
        while(c !='\n')
        {
                c = cin.get();
                setMovieName.push_back(c);
        }
       
        setMovieName.erase(setMovieName.end() - 1); //setMovieName.erase(setMovieName.begin() + setMovieName.size() - 1);

        Movie obj1(setMovieName);

        while (again == 'y' || again == 'Y')
        {
                cout << "Add the rating of the movie (1-5): ";
                cin >> rating;
                obj1.addRating(rating);

                cout << "Add more ratings? (y/n): ";
                cin >> again;
        }

        cout << "\nInsert a movie name: ";
        c = 0;
        while(c !='\n')            // PROGRAM TOTALLY SKIPS THIS WHILE LOOP (checked by debugging)..
        {
                c = cin.get();
                setMovieName.push_back(c);
        }
       
        setMovieName.erase(setMovieName.end() - 1);

        Movie obj2(setMovieName);

        again = 'y';

        while (again == 'y' || again == 'Y')
        {
                cout << "Add the rating of the movie (1-5): ";
                cin >> rating;
                obj2.addRating(rating);

                cout << "Add more ratings? (y/n): ";
                cin >> again;
        }
               
        double ave1 = obj1.getAverage();
        double ave2 = obj2.getAverage();

        cout <<"\nAverage rating for "<<  obj1.getMovieName() <<": " <<ave1<<endl;
        cout <<"Average rating for "<< obj2.getMovieName() <<": " <<ave2<<endl;

        system("pause");
        return 0;
}

Any help would be GREATLY appreciated!

EDIT: I tried different things like using a different char (d instead of c) for the second movie.. I tried to even make another contructor called setMovieName2... It just does the same..

This is what's happening when I run the program:
http://dl.farahfa.com/tmp/meh.jpg

nicolai 2013-11-26 06:46

Re: Help with a small problem in C++
 
try the getline function:
http://en.cppreference.com/w/cpp/str...string/getline

std::string moviename
std::getline(std::cin, moviename);

bandora 2013-11-26 07:29

Re: Help with a small problem in C++
 
I should've mentioned that I've tried doing that and it didn't work either.. :/

I actually tried doing that before going for that small while loop... :/

pichlo 2013-11-26 08:52

Re: Help with a small problem in C++
 
Your main problem is that your cin.get(); on line 110 reads the '\n' that was left over in the input buffer after cin >> again; on line 103. You can try replacing the loop around the line 110 with something like
Code:

    c = cin.get();
    if (c != '\n')
    {
        cin.unget();
    }
    while((c = cin.get()) != '\n')
    {
        setMovieName.push_back(c);
    }

Having done that, you can then refactor the whole thing using getline() instead of spelling out the loops manually.

I am also a bit perplexed by the way you calculate the average rating, but I leave that bit to your tutor :)

Lastly, your system("pause"); is not portable. But you probably already know that.

humble 2013-11-26 09:41

Re: Help with a small problem in C++
 
@bandora, I took a look at your code, and i say.. make a function out of your loops

ex. loop() and run that twice(or evenmore) and incorporate some kind of database to get the data generated.

pichlo 2013-11-26 10:26

Re: Help with a small problem in C++
 
Incidentally, for line-based input like yours, the best practice is to always read a line at a time using standard functions like getline() that consume the terminating '\n', then parsing the string, as opposed to parsing the standard input directly. That way you not only avoid surprises of the "'\n' left over in the buffer" kind, but also get extra robustness for cases when the user replies with "3, you silly old program" to queries requesting only a number (hint: cin << number will only swallow the 3, the rest including the comma will be left in the input buffer for the next cin operation to read).

bandora 2013-11-26 20:06

Re: Help with a small problem in C++
 
Quote:

Originally Posted by pichlo (Post 1389060)
...

Thank you so much for taking the time to help me out! I have added that to my code and that particular problem got fixed, but now I am getting a new problem (I think due to the input buffer not getting cleared?) Please look at EDIT2..

Here's the updated code:

Code:

#include <iostream>
#include <string>

using namespace std;

class Movie
{
private:
        string movieName, MPAARating;
        int numRate[5];

public:
        Movie(string movie)
        {
                movieName = movie;
                MPAARating=5;
                numRate[0]=0;
                numRate[1]=0;
                numRate[2]=0;
                numRate[3]=0;
                numRate[4]=0;
        }

        Movie() // Default Constructor
        {
                MPAARating=5;
                numRate[0]=0;
                numRate[1]=0;
                numRate[2]=0;
                numRate[3]=0;
                numRate[4]=0;
        }
       
        string getMovieName()
        {
                return movieName;
        }
       
        void setMovieName(string str)
        {
                movieName = str;
        }
       
        string getMPAARating()
        {
                return MPAARating;
        }
       
        void setMPAARating(string str)
        {
                MPAARating = str;
        }
       
        void addRating(int num)
        {
                int i = num;
                if( num>0 && num <= 5)
                {
                        this->numRate[i-1]++;
                }
               
                else
                {
                        cout <<"Number out of range."<<endl;
                }
        }
       
        double getAverage()
        {
                double num = numRate[0]+numRate[1]+numRate[2]+numRate[3]+numRate[4];
                double denom = 5.0;
                double result = num/denom;

                return result;
        }
};
       
int main()
{       
        string setMovieName;
        int rating;
        char again = 'y';

        cout << "Insert a movie name: ";
        char c = 0;
        c = cin.get();
    if (c != '\n')
    {
        cin.unget();
    }
    while((c = cin.get()) != '\n')
    {
        setMovieName.push_back(c);
    }

        Movie obj1(setMovieName);
        //char c = 0;
        //while(c !='\n')
        //{
        //        c = cin.get();
        //        setMovieName.push_back(c);
        //}
        //
        //setMovieName.erase(setMovieName.end() - 1); //setMovieName.erase(setMovieName.begin() + setMovieName.size() - 1);


        while (again == 'y' || again == 'Y')
        {
                cout << "Add the rating of the movie (1-5): ";
                cin >> rating;
                obj1.addRating(rating);

                cout << "Add more ratings? (y/n): ";
                cin >> again;
        }

        cout << "\nInsert a movie name: ";
        c = cin.get();
    if (c != '\n')
    {
        cin.unget();
    }
    while((c = cin.get()) != '\n')
    {
        setMovieName.push_back(c);
    }

        Movie obj2(setMovieName);

        //c = 0;
        //while(c !='\n')
        //{
        //        c = cin.get();
        //        setMovieName.push_back(c);
        //}
        //
        //setMovieName.erase(setMovieName.end() - 1);

        again = 'y';

        while (again == 'y' || again == 'Y')
        {
                cout << "Add the rating of the movie (1-5): ";
                cin >> rating;
                obj2.addRating(rating);

                cout << "Add more ratings? (y/n): ";
                cin >> again;
        }
               
        double ave1 = obj1.getAverage();
        double ave2 = obj2.getAverage();

        cout <<"\nAverage rating for "<<  obj1.getMovieName() <<": " <<ave1<<endl;
        cout <<"Average rating for "<< obj2.getMovieName() <<": " <<ave2<<endl;

        system("pause");
        return 0;
}

And here's the output:

http://dl.farahfa.com/tmp/meh2.jpg

I tried putting cin.clear(); after the first cin but that didn't do anything..

Also, would you care to elaborate what you meant about the average calculations please.. Are my calculations wrong? :/

Oh and also yes the system("pause"); is there only temporarily, only because when I start it without debugging the program would quit immediately after showing the averages!

Also, @Humble, I really do appreciate your input, however I didn't want to go over the top by doing all that for this program because it's only a homework problem, so honestly I was just being lazy in regards to that! haha :D

EDIT: Should I create another constructor with the name setMovieName2? To store the second movie name to that? Because right now it's just adding the values for the second movie onto the same setMovieName... (Checked that by debugging)..

EDIT2: Creating another constructor named setMovieName2 worked!!! So now my question is.. Is the calculation for the average wrong?? I really would like to know because I honestly thought that there's nothing wrong with the calculations and now I am worried that I did it wrong lol..

pichlo 2013-11-26 20:44

Re: Help with a small problem in C++
 
Your movie names get concatenated. Why do you think this is? What do you use to contain the names and how do you initialize it? (Hinr: you use a single string and you get the name into it by appending one character at a time.) What happens when you enter a new name?

Regarding your average ratings, I find I do not understand how you calculate them. In your own example, you rated American Pie as 4 and Thor as 5. You gave each of them just one rating, so I would expect the averages to be 4 and 5, respectively. Why are they 0.2? Maybe it's as intended, but it's not what I would expect, which is why I said I'd leave it to your tutor.

Humble is right, your code layout is a bit awkward. There is a lot of repetition. In general, if you find yourself writing the same code twice, you are doing something wrong. Even as few as two copies call for separating the common code into a function.

Maybe I'm wrong. I do not know what your assignemt says exactly, but the way I would have approached is something like this (in pseudocode)...
Code:

loop
  read_movie_name

  loop
      read_rating
      ask "rate again?"
      if (answer_was_no)
        break loop
  end loop

  calculate_averages

  ask "another movie?"
  if (answer_was_no)
      break loop
end loop

To calculate averages, I would divide the sum of all ratings by their number.

bandora 2013-11-26 22:32

Re: Help with a small problem in C++
 
Quote:

Originally Posted by pichlo (Post 1389175)
...

Thank you for the input! That's very helpful for future programs, but in this particular homework, I don't need more than 2 movies that's why I just did it this way..

Btw, I see what you mean about the average.. But if I am not asking for much could you give me a hint on how to do it? Like how do I get the program to count how many times I've entered a rating and divide by that number...

Should I do a for loop in the main function when I enter the ratings? But if I do how do I return it to the getAverage() constructor..? That's not even possible right?

Or do I change the void addRating(int num) constructor to a int addRating(int num) and return a value?

Hmm.. I am a bit confused not to mention my brain is fried lol.. Too many homework due at the same time! D: :mad:

pichlo 2013-11-27 08:48

Re: Help with a small problem in C++
 
Doing something even just twice is good enough a reason to make it a loop. 2 is a special case of N. If your assignment calls explicitly for doing it twice, unlikely as it sounds, then I would still write it as a loop that runs twice.

But enough of that, now to your averages. What is an average? A sum of all inputs divided by their number. Your assignment does not require to remember all the ratings, only the average. So you need just three variables. One temporary for reading the input, one for holding the sum of the inputs and one for holding their number. So get rid of MPAARating (it is not used anywhere) and replace numRate[5] with just two numbers, one for the sum and one for the number. Initialize both to 0, then each time the user enters a rating, add the rating to the sum and add 1 to the number. At the end, divide the sum with the number.


All times are GMT. The time now is 21:07.

vBulletin® Version 3.8.8