Okay, so I have a program that lets a user input information about dvds...it's a dvd library basically. I'm having a bit of trouble with nice output.
I have data members for part of the info and vectors for the others. The output should show a movie title,length, year, actor/actresses, and characters.
It does this when there is only one dvd... when there are two or more, it tries to add the second movie title to the last line of the previous characters/actors.
Here is my code so far:

void list(vector<DVD> &vectorName, vector<string>&vectorCharName, DVD *mydvd)

{

         //table format
       cout << setw(10) << "\nMovie Title: "
           << setw(10) << "Length:"
           << setw(10) << "Year: "
           << setw(10) << "Actors/Actresses:"
           << setw(10) << "Characters:\n" << endl;

       cout << "------------------------------------------------------------\n";
    for (int i = 0; i < vectorName.size(); i++)
       {
       if(i <1)
       {
       if(mydvd[i].getLength()!=0)
       {
        cout <<endl<<setw(10)<< right << mydvd[i].getTitle()
       <<setw(10)   << mydvd[i].getLength()
           << setw(10) << mydvd[i].getYear();
       }
       else
       {
           cout <<setw(10)<< right << mydvd[i].getTitle();
       }
       }
       else
       {
              if(mydvd[i].getLength()!=0)
       {
        cout <<endl<<setw(10)<< right << mydvd[i].getTitle()
       <<setw(10)   << mydvd[i].getLength()
           << setw(10) << mydvd[i].getYear();
       }
       else
       {
           cout <<setw(10)<< right << mydvd[i].getTitle();
       }
       }


        if(i <1)
           cout<<"\t\t"<<vectorName[i].getName()
            << " "<<vectorCharName[i] << endl;
        else
        {
     cout<<"\t\t\t\t"<<vectorName[i].getName()
            << " "<<vectorCharName[i] << endl;
        }




       }
    }

Edited 1 Year Ago by kiail

It's hard to tell exactly without proper indenting and without seeing the full DVD class. But as a guess I'd say that there's an inconsistency here:

    if (i < 1)
    {
        if (mydvd[i].getLength() != 0)
        {
            cout << endl << setw(10) << right << mydvd[i].getTitle()
                << setw(10) << mydvd[i].getLength()
                << setw(10) << mydvd[i].getYear();
        }
        else
        {
            cout << setw(10) << right << mydvd[i].getTitle();
        }
    }
    else
    {
        if (mydvd[i].getLength() != 0)
        {
            cout << endl << setw(10) << right << mydvd[i].getTitle()
                << setw(10) << mydvd[i].getLength()
                << setw(10) << mydvd[i].getYear();
        }
        else
        {
            cout << setw(10) << right << mydvd[i].getTitle();
        }
    }

If the getLength() returns 0 then cout won't send a new line.

On a side not that code can be shorterned considerably by eliminating duplicate code:

void list(vector<DVD> &vectorName, vector<string>&vectorCharName, DVD *mydvd)
{
    //table format
    cout << setw(10) << "\nMovie Title: "
        << setw(10) << "Length:"
        << setw(10) << "Year: "
        << setw(10) << "Actors/Actresses:"
        << setw(10) << "Characters:\n" << endl;
    cout << "------------------------------------------------------------\n";
    for (int i = 0; i < vectorName.size(); i++)
    {
        cout << endl << setw(10) << right << mydvd[i].getTitle();
        if (i < 1)
        {
            if (mydvd[i].getLength() != 0)
            {

                    cout << setw(10) << mydvd[i].getLength()
                         << setw(10) << mydvd[i].getYear();
            }
            cout << "\t\t" << vectorName[i].getName()
                << " " << vectorCharName[i] << endl;
        }
        else
        {
            cout << "\t\t\t\t" << vectorName[i].getName()
                << " " << vectorCharName[i] << endl;
        }
    }
}

Write a program to instantiate the object of a class Time from the main() function and constructor is called of the class Time automatically to initialize the private data members of the class with 0. Time is printed on the screen in 12 hours format and 24 hours format as follows:

i found that if i enter a dvd number + the amount of actors from the last dvd entered, that it lines up properly...

I think with some refactoring to tighten up the separation of responsibility principle, it becomes easier to get the display you want.Put the display of an individual dvd in the dvd class. A static function to show the column headings allows you to show the headings when needed. Putting setter overloads accepting i/ostreams as parameters declutters your calling processes. Embedding a struct for the actor property allows you to tie the actor and the character(s) portrayed by that actor for that movie together. Now a vector of that struct allows you to keep as many actor/character combinations you want.

Something like this for the class:

class DVD
{
public:

private:
    struct ActorCharacter
    {
        string name = "";
        string character = "";
    };
    string movieTitle = "";
    vector<ActorCharacter> actors;
    double movieLength = 0.0;
    int movieYear = 0;

public:
    DVD()
    {

    }
    DVD(string title,double length = 0.0, int year = 0)
    {
        movieTitle = title;
        movieLength = length;
        movieYear = year;
    }

    void setTitle(string title)
    {
        movieTitle = title;
    }
    void setTitle(istream& input, ostream& output)
    {
        output << "\nEnter Title: ";
        input.sync();
        getline(input, movieTitle);
    }
    void setLength(double length)
    {
        movieLength = length;
    }
    void setLength(istream& input, ostream& output)
    {
        output << "\nEnter Length(in minutes): ";
        input >> movieLength;
    }
    void setYear(int year)
    {
        movieYear = year;
    }
    void setYear(istream& input, ostream& output)
    {
        output << "\nEnter Year: ";
        input >> movieYear;
    }
    void addActors(istream& input, ostream& output)
    {
        bool done = false;
        while (!done)
        {
            ActorCharacter temp;
            output << "\nEnter the Actor(s) Name(s)('q' when done): ";
            input.sync();
            getline(input, temp.name, '\n');
            if (temp.name == "q")
            {
                break;
            }
            output << "\nEnter the Actor's character(s)(separate multiple characters with a '/'): ";
            input.sync();
            getline(input, temp.character);
            actors.push_back(temp);
        }


    }
    vector<ActorCharacter> getActors()
    {
        return actors;
    }

    string getTitle()
    {
        return movieTitle;
    }

    double getLength()
    {
        return movieLength;
    }

    int getYear()
    {
        return movieYear;
    }
    static void showColumnHeaders(ostream& output)
    {
        output << setw(12) << "\nMovie Title"
            << setw(12) << "Length"
            << setw(12) << "Year"
            << setw(12) << "Actors:"
            << setw(24) << "Characters\n";

        output << "------------------------------------------------------------------------\n";
    }
    void listDVDData(ostream& output)
    {
        if (movieTitle == "")
        {
            output << "\nNo Data";
            return;
        }
        output  << setw(12) << movieTitle 
                << setw(12) << movieLength 
                << setw(12) << movieYear;
        if (actors.size() > 0)
        {
            output  << setw(12) << actors[0].name 
                    << setw(24) << actors[0].character << '\n';
            size_t size = actors.size();
            for (size_t i = 1; i < size; i++)
            {
                output  << setw(36) << " " 
                        << setw(12) << actors[i].name 
                        << setw(24) << actors[i].character << '\n';
            }
        }

    }
};

The front end could use some separation as well:

char showMenu()
{
    char c;
    bool done = false;
    while (!done)
    {
        cout << "Welcome to the DVD Collection Program! \n What do you want to do?\n " << endl;
        cout << "1. Add DVD" << endl;

        cout << "2. Remove DVD" << endl;

        cout << "3. Edit DVD" << endl;

        cout << "4. Show All DVDs" << endl;

        cout << "5. EXIT" << endl;

        cin >> c;
        if (c >= '1' && c <= '5')
        {
            done = true;
        }
        else
        {
            cout << "Wrong choice\n\n";
        }
    }
    return c;
}
void AddDVD(map<string,DVD>& collection)
{
    bool done = false;
    while(!done)
    {
        DVD temp;
        temp.setTitle(cin, cout);
        temp.setLength(cin, cout);
        temp.setYear(cin, cout);
        temp.addActors(cin, cout);
        DVD::showColumnHeaders(cout);
        temp.listDVDData(cout);
        cout << "Is the info correct?(y/n) : ";
        char choice = 'n';
        cin >> choice;
        if (tolower(choice) == 'y')
        {
            collection[temp.getTitle()] = temp;
            done = true;
        }
    }
}
void RemoveDVD(map<string, DVD>& collection)
{
    cout << "\nEnter Movie Title you wan to remove: ";
    string title = "";
    cin.sync();
    getline(cin, title);
    map<string,DVD>::iterator result = collection.find(title);
    if (result == collection.end())
    {
        cout << "\nNo records found. None were removed.";
        return;
    }
    cout << "\nThis dvd was found:";
    (*result).second.listDVDData(cout);
    char confirm;
    cout << "\nConfirm removal(y/n): ";
    cin >> confirm;
    if (tolower(confirm) == 'y')
    {
        collection.erase(result);
    }
}
void EditDVD(map<string, DVD>& collection)
{

}
void ListAllDVDs(map<string, DVD>& collection)
{

}
int main()
{
    const char SHOW_LIST = '4', ADD_DVD = '1', REMOVE_DVD = '2', EDIT_DVD = '3', QUIT_CHOICE = '5';
    map<string,DVD> dvdCollection;
    while (true)
    {
        switch (showMenu())
        {
        case ADD_DVD:
            AddDVD(dvdCollection);
            break;
        case REMOVE_DVD:
            RemoveDVD(dvdCollection);
            break;
        case EDIT_DVD:
            EditDVD(dvdCollection);
            break;
        case SHOW_LIST:
            ListAllDVDs(dvdCollection);
            break;
        case QUIT_CHOICE:
            return 0;
        }
    }
    return 0;
}

Noticed how uncluttered main is. When using a menu system you'll find accepting a char instead of an int less prone to exceptions being thrown and is easier to trap wrong input. A map<string, DVD> works very well for a collection like this.

Edited 1 Year Ago by tinstaafl

This article has been dead for over six months. Start a new discussion instead.