Receiving a return of what looks like an address when trying to sort an array of a structure

I have created a program that reads a text file and stores into an array of a structure. For now I only have it set up to read entering a choice of 2 so as to test it. Not sure why it returns what looks to be an address. If anyone can offer some insight that would be great. Also if anyone can offer a suggestion on how to store the variable I have 'total' so it is accessible for the entirety of main I would appreciate it.

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>


using namespace std;

const int MAX_MOVIES = 100;
struct movies //movies structure
{
string moviesId;
string moviesName;
string moviesActor1;
string moviesActor2;
int moviesYear;
double moviesRating;
};

void displayMenu();


void displayMenuSpecific(struct movies movieInfo[], int total)
{
for(int i=0;i<total;i++)
{
cout << movieInfo[i].moviesName;
}
};


int main()
{
//testing if my file is found
ifstream inputLibrary;
inputLibrary.open("program2_library.txt");
if (!inputLibrary)
{
cout << "ERROR: File not found! " << endl;
}

int total = 0; //amount of movies
movies movieInfo[MAX_MOVIES];

while(!inputLibrary.eof())
{
inputLibrary >>ws;getline(inputLibrary, movieInfo[total].moviesId);
inputLibrary >>ws;getline(inputLibrary, movieInfo[total].moviesName);
inputLibrary >>ws;getline(inputLibrary, movieInfo[total].moviesActor1);
inputLibrary >>ws;getline(inputLibrary, movieInfo[total].moviesActor2);
inputLibrary >> movieInfo[total].moviesYear;
inputLibrary >> movieInfo[total].moviesRating;
total++;
}
inputLibrary.close();


int choice;

do{

displayMenu();
cin>>choice;

if (choice ==2)
{

for(int i = 0; i<=total;i++)
{

for(int j= 0; j<=total;i++)
{
if(movieInfo[i].moviesRating < movieInfo[j].moviesRating)
{

movies temp = movieInfo[i];
movieInfo[i] = movieInfo[j];
movieInfo[j] = temp;

};
}
}
displayMenuSpecific (movieInfo,total);
}




}while (choice != 5);

};

void displayMenu(){
cout << "Menu " << endl;
cout << endl;
cout << "1. Display movies sorted by title " << endl;
cout << "2. Display movies sorted by rating " << endl;
cout << "3. Lookup title and actors by id " << endl;
cout << "Lookup id by title and either actor " << endl;
cout << "Quit the program " << endl;

};
Last edited on
Please use code tags when posting code. See: https://www.cplusplus.com/articles/jEywvCM9/
Syntax highlight and intuitive indentation are "just" visual cues, yet surprisingly powerful.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (choice ==2)
{
  for (int i = 0; i<=total; i++)
  // Out-or-range error: In array that has 'total' elements, last element is total-1, not total
  {
    for (int j = 0; j<=total; i++) // looks wrong, if this should bubble-sort
    {
      if (movieInfo[i].moviesRating < movieInfo[j].moviesRating)
      { // C++ has a helper for swapping values: std::swap( movieInfo[i], movieInfo[j] );
        movies temp = movieInfo[i];
        movieInfo[i] = movieInfo[j];
        movieInfo[j] = temp;
      }
      ; // null statement
    }
  }
  displayMenuSpecific( movieInfo, total );
}

C++ Library has a sort algorithm too:
1
2
3
4
5
6
7
8
if (choice ==2)
{
  // descending, by moviesRating
  std::sort( movieInfo, movieInfo+total, [](const movies& lhs, const movies& rhs)
      { return lhs.moviesRating > rhs.moviesRating } );

  displayMenuSpecific( movieInfo, total );
}



1
2
3
4
5
6
7
8
9
10
int total = 0; //amount of movies
movies movieInfo[MAX_MOVIES];
// or
std::vector<movies> movieInfo; // vector has "total" in it

movies entry;
// read data into entry
movieInfo.push_back( entry );

// movieInfo has now movieInfo.size() movies in it 



1
2
while( !inputLibrary.eof() )
{

The eof() is mind-boggling and not suitable for this use. You will probably add one non-sense movies into your array.


PS. If one movies is info about one movie, why the name of the type is movies?
I see two problems with that inner loop:
for (int j = 0; j<=total; i++) // looks wrong, if this should bubble-sort
Thanks for answering, I cannot use vectors, or any of the built in sorting algorithms. I'll try your recommendations! What would you use over eof? I'm not sure what you mean by your last question?
Hello iamkairos,


PLEASE ALWAYS USE CODE TAGS (the <> formatting button), to the right of this box, when posting code.

Along with the proper indenting it makes it easier to read your code and also easier to respond to your post.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

Hint: You can edit your post, highlight your code and press the <> formatting button. This will not automatically indent your code. That part is up to you.

You can use the preview button at the bottom to see how it looks.

I found the second link to be the most help.



I found that there are a couple of places where you have some extra blank lines that you do not need and a couple of places where you do. That will come with time and more use of your IDE and how it works.When I put your code in my IDE it was refreshing to see code that is easy to read.

The struct is good and I do agree with keskiverto that the struct if for one movie, so the name should be "Movie" to be more accurate. Notice that the first is a capital letter. Many tend to start classes and structs with a capital letter, but you are free to use a variable name any way you want.

I do have a question about double moviesRating;. Why the "double"? Without having a better understand I feel this is over kill for something that is likely to hold a number of 1 to 7. I am thinking a 'short" or an "int" would be a better choice.

For an example:
1
2
3
4
5
6
7
void displayMenuSpecific(struct movies movieInfo[], int total)
{
    for (int i = 0; i < total; i++)
    {
        cout << movieInfo[i].moviesName;
    }
};

The semi-colon after the closing brace of the function is not needed. If I understand this the closing } ends the function not the semi-colon. I do not believe it will cause any problem if you leave it.

In "main" you have:
1
2
3
4
if (!inputLibrary)
{
    cout << "ERROR: File not found! " << endl;
}

The concept is good, but the implementation is wrong. If the file stream did not open you would continue on with the program wondering why it did not work. What you want is something more like this:
1
2
3
4
5
6
if (!inputLibrary)
{
    std::cerr << "ERROR: File \"program2_library\" not found! " << endl;

    return 1;
}

The "return" statement will leave the program because there is no point in continuing until you fix the problem. Any number greater than zero indicates the the program ended with a problem. Using a different number can help to indicate what or where the problem is.

For another option I like using this:
1
2
3
4
5
6
7
8
9
10
11
//testing if my file is found
const std::string inFileName{ "program2_library.txt" };

ifstream inputLibrary(inFileName);

if (!inputLibrary)
{
    std::cerr << "ERROR: File " << std::quoted(inFileName) << " not found! " << endl;

    return 1;
}

In both examples I used "cerr" in place of "cout". As it was pointed out to me "cout" can be redirected to something other than the screen whereas "cerr" is not likely to be changed.

By defining the file name as a constant variable you only have one place to change the name to be used in 2 or more places in the program. It is similar to the variable "MAX_MOVIES".

The "std::quoted" is from the "iomanip" header file and if someone does not tell you about it you may never know what it is for. This function will put double quotes around what is in the (), be it a variable or a constant string, ("program2_library.txt").

Changing the name of the struct to "Movie" you could change the name of the array to Movie movies[MAX_MOVIES];. Just a suggestion. What you have works.

As keskiverto pointed out the use of while (!inputLibrary.eof()) is not a good idea. It does not work the way that you are thinking and it is being used wrong.

When you get to the while loop the "eof" bit is not set, so you enter the loop and read the first bit of information which may set the "eof" bit, but you still store what you can not read before the while condition picks on the "eof" bit being set and fails.

Over time I have come to the conclusion that people are taught about the ".eof()" function, but not how to properly use it. If yo insist on or have to use the ".eof()" function you will need to do this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
getline(inputLibrary, movieInfo[total].moviesId);

while (!inputLibrary.eof())
{
    inputLibrary >> ws; getline(inputLibrary, movieInfo[total].moviesName);
    inputLibrary >> ws; getline(inputLibrary, movieInfo[total].moviesActor1);
    inputLibrary >> ws; getline(inputLibrary, movieInfo[total].moviesActor2);
    inputLibrary >> movieInfo[total].moviesYear;
    inputLibrary >> movieInfo[total].moviesRating;

    total++;

    getline(inputLibrary, movieInfo[total].moviesId);
}

If the first read line 1 sets the "eof" bit the while loop will fail. Line 13 will read the beginning of the next record and if that sets the "eof" bit the while condition will catch this at the proper time.

What is used more often to read a file of unknown length is:
1
2
3
4
5
6
7
8
9
10
while (getline(inputLibrary, movieInfo[total].moviesId))
{
    inputLibrary >> ws; getline(inputLibrary, movieInfo[total].moviesName);
    inputLibrary >> ws; getline(inputLibrary, movieInfo[total].moviesActor1);
    inputLibrary >> ws; getline(inputLibrary, movieInfo[total].moviesActor2);
    inputLibrary >> movieInfo[total].moviesYear;
    inputLibrary >> movieInfo[total].moviesRating;

    total++;
}

This way when the read fails so does the loop.
inputLibrary >> ws; This should not be necessary, but I do not know what your file looks like. If you need it you could write it like this: getline(inputLibrary >> ws, movieInfo[total].moviesId) and it would work just the same.

As it has been pointed out your sort portion is not workable.

Thing about the for loops with an array having a size of 5 elements, numbered 0 - 4 the "<=" would allow "i" to reach the number 5. So something like "movieInfo[i].moviesRating" with "i" being 5 this is beyond the end of the array and not what you want.

Using "<=" in a for loop has the tendency to loop 1 time more than you want. Starting a for loop at zero and checking i < total tends to work better, but in this case it is not 100% correct as the outer for loop should not read the last element of the array.

The inner for loop is starting at the wrong place and the "<=" is causing the same problem going past the end of the array.

Look at the line:
if (movieInfo[i].moviesRating < movieInfo[j].moviesRating)
or another way
if (movieInfo[0].moviesRating < movieInfo[0].moviesRating)
Comparing one element to its-self is not what you want. What you do want is
1
2
3
if (movieInfo[0].moviesRating < movieInfo[1].moviesRating)
              ^                           ^
              i                           j

Looking at this how would you change the for loops to make this work?

At this point I have to ask if writing your own sort code is required? Or could you use "std::sort()" and "std::swap()" from the "algorithm" header file?

I also have to ask if you have learned about "vectors" yet? This would make things much easier over arrays.

Last point. You are reading from a file. It is best to include this file with your code so everyone can see what it looks like and if your code is reading correctly. Also it gives everyone the same information to use.

Andy

The semi-colon after the closing brace of the function is not needed. If I understand this the closing } ends the function not the semi-colon. I do not believe it will cause any problem if you leave it.

Actually g++ will produce an error when it is setup to be pedantic, it really should be treated as an error.

main.cpp error: extra ‘;’ [-Wpedantic]|


@jlb,

Thank you. I know that the ";" should no be at the end of a function, but I did not realize that it should produce an error.

Andy
Over time I have come to the conclusion that people are taught about the ".eof()" function, but not how to properly use it. If yo insist on or have to use the ".eof()" function you will need to do this:


There are still issues with your method of using eof() to control a read loop.

First eof() is not the only error that can be generated by reading a file. So if something other that eof() causes a failure in the stream you will most likely get an endless loop.

Second, and this is even a problem when properly reading the file as well. This program is using an array to hold the contents of the file so you must always check that you are still inside the bounds of the array before trying to use "total" as the index of the array.
1
2
3
...
while (total < MAX_MOVIES && getline(inputLibrary >> ws, movieInfo[total].moviesId))
...


Hi Handy Andy,

I apologize for not familiarizing myself with the posting guidelines.

I do have to create my own sorting algorithm and am not allowed to use vectors, I'll implement the change to make the name of my struct to make it more coherent.

The text file I am grabbing from reads as such:

A201 //movie id
Avengers: Endgame //movieTitle
Scarlett Johansson //movieActor1
Chris Evans //movieActor2
2019 8.6 //movieYear and movieRating
B331
Despicable Me 3
Steve Carell
Kristen Wiig
2017 6.1
D210
Neighbors
Zac Efron
Rose Byrne
2014 6.3
Z122
Beauty and the Beast
Emma Watson
Dan Stevens
2017 7.2

I implemented the change to the reading of the file and entering them into their specified variables. Your second option of entering ws in the while loop has it reading it correctly and storing correctly so thank you for that! I will better my understanding of eof before attempting to implement it again.

Do you know if after creating my total variable in that while loop if it will be accessible to the entirety of my main function?

I need to create my program such that it is robust enough to read up to one hundred movies, and I am attempting to create a variable that I can then use as the cut off point after that. I hope that makes sense.

For the sorting algorithm I changed j to read as starting at 1, but after calling my displaySpecificMenu option, I am still being returned an odd number? I apologize for my rudimentary understanding, I am trying to be better.

My code now reads as such

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>


using namespace std;

const int MAX_MOVIES = 100;
struct movies //movies structure
{
    string moviesId;
    string moviesName;
    string moviesActor1;
    string moviesActor2;
    int    moviesYear;
    double moviesRating;
};

void displayMenu();


void displayMenuSpecific( movies movieInfo[], int total)
{
    for(int i=0;i<total+1;i++)
    {
        cout << "name of movie"<<movieInfo[i].moviesName;
    }
};


int main()
{
    //testing if my file is found
    ifstream inputLibrary;
             inputLibrary.open("program2_library.txt");
    if (!inputLibrary)
    {
        cout << "ERROR: File not found! " << endl;
        return 1;
    }

    int total = 0; //amount of movies
    movies movieInfo[MAX_MOVIES];
    while (getline(inputLibrary >> ws, movieInfo[total].moviesId))
    {

        inputLibrary >> ws; getline(inputLibrary, movieInfo[total].moviesName);
        inputLibrary >> ws; getline(inputLibrary, movieInfo[total].moviesActor1);
        inputLibrary >> ws; getline(inputLibrary, movieInfo[total].moviesActor2);
        inputLibrary >> movieInfo[total].moviesYear;
        inputLibrary >> movieInfo[total].moviesRating;

        total++;
    }


        for(int i=0;i<total;i++) //testing everything assigned correctly
    {
        cout << movieInfo[i].moviesId<<endl;
        cout << movieInfo[i].moviesName<<endl;
        cout << movieInfo[i].moviesActor1<<endl;
        cout << movieInfo[i].moviesActor2<<endl;
        

    }


    int choice;

    do{

    displayMenu();
    cin>>choice;

    if (choice ==2)
    {

       for(int i = 0; i<total+1;i++)
        {

            for(int j= 1; j<total+1;i++)
            {
                 if(movieInfo[i].moviesRating > movieInfo[j].moviesRating)
                    {

                       movies temp = movieInfo[i];
                       movieInfo[i] = movieInfo[j];
                       movieInfo[j] = temp;
                    }
             }
        }
        displayMenuSpecific (movieInfo,total);
    }




    }while (choice != 5);

};

void displayMenu(){
cout << "Menu " << endl;
cout << endl;
cout << "1. Display movies sorted by title " << endl;
cout << "2. Display movies sorted by rating " << endl;
cout << "3. Lookup title and actors by id " << endl;
cout << "Lookup id by title and either actor " << endl;
cout << "Quit the program " << endl;

};


It does seem to work but is returning some odd stuff before returning the sorted data. So I am working to debug that.

I am also refraining from using cerr as I have not been taught that.

I would like to thank you so much for all you have offered so far, I appreciate you.


Last edited on
Upon reviewing my code it seems I did not have the second for loop set to increment j.
Thank you all so much for your help!

@jlb thank you for that advice I need to work on my understanding on reading files very obviously. :)
Last edited on
you don't make total in the loop you just use it there.
you may want to read a web page on c++ and variable scopes, but for now, its fine like it is.
a variable 'exists/is usable' if it is in scope where you try to use it. Generally that means it is at either the current or higher level current scope, and defined before it is used.

some languages (notably sql) can use a 'variable' (using the term very loosely here) before it is made:
z = x //this actually works
more stuff...
define things as x

c++ is not like that.
so you can't say
cout << x; //does not exist here
int x = 3;
and must reverse the two for that to work.

C++ flows top to bottom. So it needs to be created 'above' any attempt to use it. If you want it available to 'all of main' make it the first statement inside main ... eg you can't use total on line 35 but you can on line 44.
Last edited on
Hello iamkairos,


Do you know if after creating my total variable in that while loop if it will be accessible to the entirety of my main function?


Actually no. If you define the variable "total" inside the {}s of the while it will be destroyed when the while loop is finished. But since you have define the variable outside the while loop as you did it is available inside the while loop and to the rest of "main". Add that to what jonnin said.


I am also refraining from using cerr as I have not been taught that.


You were taught to use "iostream" for the input and output functions of "cin" and "cout" along with "endl". I may have a different way of looking at everything, but once you are told to use "iostream" you have access to anything that is available in that header file. Some of that may never be taught in a class and that is where some place like here can fill in the gaps. "cerr" may not have been taught in your class and may never be, but it is good to know about.

Back when I was in school I found that there are some parts of the language that are never mentioned in a class room lecture, but that should not stop you from learning something new.

If you do not understand let me know and I will try to focus more on "cerr".

In the while (getline(inputLibrary >> ws, movieInfo[total].moviesId)) the inputLibrary >> ws was meant to show you a better way to do this. It may be my fault, but I meant to use this in every "getline" not just in the while condition. After seeing you input file there is not need for the ">> ws" in any of the input statements because there is no white space to read past.

Another fix in the while loop is:
1
2
3
4
5
6
7
8
9
10
11
12
13
while (getline(inputLibrary, movieInfo[total].moviesId))
{
    getline(inputLibrary, movieInfo[total].moviesName);
    getline(inputLibrary, movieInfo[total].moviesActor1);
    getline(inputLibrary, movieInfo[total].moviesActor2);

    inputLibrary >> movieInfo[total].moviesYear;
    inputLibrary >> movieInfo[total].moviesRating;

    inputLibrary.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.

    total++;
}

After line 8 you need to add line 10 to clear the input buffer before the next "getline".

Formatted input as you have used inputLibrary >> movieInfo[total].moviesRating will leave the new line (\n) in the input buffer, so when you get to the next "getline" it reads what is left in the input buffer and not the file. This will through off the reading of the file and cause a problem when you try to read a string into "moviesYear" because the formatted input is expecting a number and it it is reading a string. This will cause the file stream to be put in a failed state and nothing else can be read from the file until it is fixed.

I think you need to revisit your book on loops, arrays and how they work.

Your sort routine is better, but not quite there yet.

You started with:
1
2
3
4
5
6
7
8
9
10
11
12
13
for (int i = 0; i <= total; i++)
{
    for (int j = 0; j <= total; i++)
    {
        if (movieInfo[i].moviesRating < movieInfo[j].moviesRating)
        {
            movies temp = movieInfo[i];
            movieInfo[i] = movieInfo[j];
            movieInfo[j] = temp;

        };
    }
}

The extra blank lines you have are not needed. This will work just fine.

In line 1 the "<=" will do 1 more loop than you realize and that is going past the end of the array. Or in this case it is going to 1 element past what should be the end of what part of the array is used.

In your new code:
1
2
3
4
5
6
7
8
9
10
11
12
13
for (int i = 0; i < total + 1; i++)
{
    for (int j = 0; j < total + 1; j++)
    {
        if (movieInfo[i].moviesRating < movieInfo[j].moviesRating)
        {
            movies temp = movieInfo[i];
            movieInfo[i] = movieInfo[j];
            movieInfo[j] = temp;

        };
    }
}

in line 1 the "total + 1" is doing the same as "<=". And the same applies to the inner for loop.

I know it was not the greatest explanation, but I was meaning that "i" should start at (0) and "j" should start at 1, so that you are comparing 2 different elements of the array.

To work the for loops as you need:
1
2
3
4
5
6
7
8
9
10
11
12
for (int i = 0; i < total - 1; i++)
{
    for (int j = i + 1; j < total; j++)
    {
        if (movieInfo[i].moviesRating > movieInfo[j].moviesRating)
        {
            movies temp = movieInfo[i];
            movieInfo[i] = movieInfo[j];
            movieInfo[j] = temp;
        }
    }
}

The outer for loop needs to stop 1 less than "total" so that the inner for loop does not go past the end of the array.

The inner for loop needs to start at 1 more than "i" so that you are always comparing 2 different elements. And the inner for loop needs to go to less than "total" to check all the elements in the array or just the part of the array that is used.

If you really want to test the for loops change "MAX_MOVIES" to 4 and use your IDE to check the values if "i" and "j" along with each element of the array to see what happens. Later change "MAX_MOVIES" to 10 until you get the program working. In the end you will be able to set "MAX_MOVIES" to any size that you need.

This part is totally up to you, but I was playing with "mainMenu", as I like to call it, and tend to do a function Like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int mainMenu()
{
    int choice{};

    do
    {
        cout << '\n' << std::string(18, ' ') <<
            "Menu\n\n"
            " 1. Display movies sorted by title\n"
            " 2. Display movies sorted by rating\n"
            " 3. Lookup title and actors by id\n"
            " 4. Lookup id by title and either actor\n"
            " 5. Quit the program\n"
            " Enter choice: ";
        std::cin >> choice;

        if (!std::cin || (choice < 1 || choice  >5))
        {
            if (!std::cin)
            {
                std::cerr << "\n     Invalid entry! Must be a number.\n";

                std::cin.clear();
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
            }
            else if (choice < 1 || choice  > 5)
            {
                std::cerr << "\n     Invalid choice! Try again.\n";
            }
        }
    } while (choice < 1 || choice  > 5);

    return choice;
}

The "cout" statement makes it easier to work with the menu and gives a better representation of what it will look like on the screen.

Since the formatted input of std::cin >> choice; is expecting a number any non numerical value will cause "cin" to fail.

The following if and if/else if will deal with a failed "cin" or an input being out of range. This may be ahead of your class, but now is a good time to learn and get use to it.

The while condition will keep the loop running until you have a valid input and only then do you return a valid input.

Give it a try and feel free to change the error messages to whatever you want.

Andy
Consider changing some of your variable names to make the code more readable:
- No need to put "movies" in the name of each member
- Change "movies" to "movie" because the struct describes a single movie
- Change "movieInfo" to "movies" to more accurately indicate that it's a collection of movies:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>


using namespace std;

const int MAX_MOVIES = 100;
struct movie  // One movie
{
    string Id;
    string Name;
    string Actor1;
    string Actor2;
    int    Year;
    double Rating;
};

void displayMenu();


void displayMenuSpecific( movie movies[], int total)
{
    for(int i=0;i<total+1;i++)
    {
        cout << "name of movie"<<movies[i].Name;
    }
};


int main()
{
    //testing if my file is found
    ifstream inputLibrary;
             inputLibrary.open("program2_library.txt");
    if (!inputLibrary)
    {
        cout << "ERROR: File not found! " << endl;
        return 1;
    }

    int total = 0; //amount of movies
    movie movies[MAX_MOVIES];
    while (getline(inputLibrary >> ws, movies[total].Id))
    {

        inputLibrary >> ws; getline(inputLibrary, movies[total].Name);
        inputLibrary >> ws; getline(inputLibrary, movies[total].Actor1);
        inputLibrary >> ws; getline(inputLibrary, movies[total].Actor2);
        inputLibrary >> movies[total].Year;
        inputLibrary >> movies[total].Rating;

        total++;
    }


        for(int i=0;i<total;i++) //testing everything assigned correctly
    {
        cout << movies[i].Id<<endl;
        cout << movies[i].Name<<endl;
        cout << movies[i].Actor1<<endl;
        cout << movies[i].Actor2<<endl;
        

    }


    int choice;

    do{

    displayMenu();
    cin>>choice;

    if (choice ==2)
    {

       for(int i = 0; i<total+1;i++)
        {

            for(int j= 1; j<total+1;i++)
            {
                 if(movies[i].Rating > movies[j].Rating)
                    {

                       movie temp = movies[i];
                       movies[i] = movies[j];
                       movies[j] = temp;
                    }
             }
        }
        displayMenuSpecific (movies,total);
    }




    }while (choice != 5);

};

void displayMenu(){
cout << "Menu " << endl;
cout << endl;
cout << "1. Display movies sorted by title " << endl;
cout << "2. Display movies sorted by rating " << endl;
cout << "3. Lookup title and actors by id " << endl;
cout << "Lookup id by title and either actor " << endl;
cout << "Quit the program " << endl;

};

If you test success of only the first field of a record, then you don't know yet whether you can read the whole record.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    int total = 0; //amount of movies
    movie movies[MAX_MOVIES];
    movie entry;
    while ( total < MAX_MOVIES && inputLibrary ) // Can we read more?
    {
        inputLibrary >> ws; getline(inputLibrary, entry.Id);
        inputLibrary >> ws; getline(inputLibrary, entry.Name);
        inputLibrary >> ws; getline(inputLibrary, entry.Actor1);
        inputLibrary >> ws; getline(inputLibrary, entry.Actor2);
        inputLibrary >> entry.Year;
        inputLibrary >> entry.Rating;

        if ( inputLibrary ) { // Did we read more?
            movies[total] = entry;
            total++;
        }
    }

There is a way to make this more compact:
1
2
3
4
5
6
7
8
    int total = 0; //amount of movies
    movie movies[MAX_MOVIES];
    movie entry;
    while ( total < MAX_MOVIES && inputLibrary >> entry )
    {
          movies[total] = entry;
          total++;
    }

But it requires that we define what inputLibrary >> entry does.
That is operator overloading.
1
2
3
4
5
6
7
8
9
std::istream& operator>> ( std::istream& in, movie& rhs ) {
        in >> ws; getline(in, rhs.Id);
        in >> ws; getline(in, rhs.Name);
        in >> ws; getline(in, rhs.Actor1);
        in >> ws; getline(in, rhs.Actor2);
        in >> rhs.Year;
        in >> rhs.Rating;
        return in;
}

The operator>> is a standalone function that you can make correct separately.
Topic archived. No new replies allowed.