How to read file into multimap containing numbers and string

I have text file containing several numbers and string text. I would like to read text file into multimap. But don't know for sure whether my code is correctly done, because my code is crashing every time.

Sample text looks like:

7
Batman vs Superman
4
Batman vs Superman
5
Pirates of the Caribbean
3
Finding Dory
3
Batman vs Superman
4
Harry Potter and the Chamber of Secrets
5
Pirates of the Caribbean
4

Where number 7 - is quantity of movies, and other numbers are ratings of movies.

For now I have done 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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include<iostream>
#include<map>
#include<algorithm>
#include<iterator>
#include<string>
#include<fstream>
#include<cstring>
using namespace std;

int main()
{
    //multimap<pair<int,int>,string>mvList;
    multimap<string, map<int, int>> mapReview;
    string movieName;
    int numb,mvRating;
    char fileName[120];

    cout<<"Please enter the file name: ";
    cin>>fileName;

    ifstream read(fileName);

    if(!read){
		cout << "File not found!" << endl;
		return -1;
	}

    read >> numb;
    read.ignore();

	for (int temp = 0; temp < numb; temp++)
	{
        getline(read, movieName);
        read >> mvRating;
        read.ignore();
        ++mapReview[mvRating][movieName];

    }

    map<int, int>::iterator tempItr1;
	map<string, map<int, int>>::iterator tempItr2;
    for (tempItr2 = mvList.begin(); tempItr2 != mvList.end(); tempItr2++)
    {

      cout << "\n " << tempItr2->first << endl;

        for (tempItr1 = tempItr2->second.begin(); tempItr1 != tempItr2->second.end(); tempItr1++)
        {
			cout <<  "\n" <<  tempItr1->first << endl;
        }
    }
    return(0);


}
What's the benefit of using std::multimap and is it necessary? Using a struct:
1
2
3
4
5
struct MovieReview
{
    std::string m_movieName;
    int m_movieRating;
};

you could read off the first line of the file into a dummy string and then construct MovieReview instances from every 2 lines of the rest of the file and store these objects in a std::vector<MovieReview>

multimap<string, map<int, int>> mapReview;
this does not capture the layout of the data, try and match structs, containers to the arrangement of the data that you're working with. For example, here the string might correspond to the name of the film but what is supposed to be represented by the
 
map<int, int>
?
> because my code is crashing every time.
your code doesn't even compile.

multimap doesn't have bracket acess []
you commented out mvList
Use a map of name to vector of ratings (instead of a multimap). Something along these lines:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <map>
#include <vector>
#include <string>
#include <fstream>

// key == name of film; mapped value == vector of ratings
using database = std::map< std::string, std::vector<int> > ;

database create_db_from( std::istream& istm )
{
    database db ;

    std::string film ;
    int rating ;

    // note: the >> std::ws at the end is to extract and discard the
    // new line that would remain in the input buffer after istm >> rating
    while( std::getline( istm, film ) && istm >> rating >> std::ws )
        db[film].push_back(rating) ;

    return db ;
}

http://coliru.stacked-crooked.com/a/93a53c9ffa47b487
I have done for this moment 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
35
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <iterator>
using namespace std;

const std::string filePath = "movie.txt";

int main()
{
    ifstream read(filePath);
    if (read.is_open())
    {
        multimap<std::string, int> movies;
        string name;
        int valuation = 0;

        cout << "Films count: " << char(read.get()) << std::endl;
        while (read.get() != '\n' && read) {}

        while (std::getline(read, name))
        {
            read >> valuation;
            movies.emplace(name, valuation);
            while (read.get() != '\n' && read) {}
        }

        for (const auto& p : movies)
            cout << p.first << " " << p.second << std::endl;

        cout << "Finish." << std::endl;
    }
}


The question is how can I count the movie rating average and total number of each 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
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <fstream>
#include <iomanip>

// key == name of film; mapped value == vector of ratings
using database = std::map< std::string, std::vector<int> > ;

database create_db_from( std::istream& istm )
{
    database db ;

    std::string film ;
    int rating ;
    while( std::getline( istm, film ) && istm >> rating >> std::ws )
        db[film].push_back(rating) ;

    return db ;
}

void print_summary( const database& db )
{
    for( const auto& pair : db )
    {
        int sum = 0 ;
        std::cout << "name: " << std::quoted(pair.first) << "  ratings: [ " ;
        for( int r : pair.second ) { std::cout << r << ' ' ; sum += r ; }
        std::cout << "] average rating: " << double(sum) / pair.second.size() << '\n' ;
    }
}

int main()
{
    const std::string file_path = "movie.txt" ;
    std::ifstream file(file_path) ;

    // throw the first line away; we don't really need it
    int n ;
    file >> n >> std::ws ; // also discard trailing white space
    std::cout << "#entries == " << n << '\n' ; // for debugging purposes

    print_summary( create_db_from(file) ) ;
}
Multimap version (somewhat more convoluted):

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
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <fstream>
#include <iomanip>

// key == name of film; mapped value == rating
using database = std::multimap< std::string, int > ;

database create_db_from( std::istream& istm )
{
    database db ;

    std::string film ;
    int rating ;
    while( std::getline( istm, film ) && istm >> rating >> std::ws )
        db.emplace( film, rating ) ;

    return db ;
}

void print_summary( const database& db )
{
    auto iter = db.begin() ;

    while( iter != db.end() )
    {
        std::cout << "name: " << std::quoted( iter->first ) << "  ratings: [ " ;

        int sum = 0 ;
        int cnt = 0 ;
        const auto next = db.upper_bound(iter->first) ;
        for( ; iter != next ; ++iter )
        {
            const int rating = iter->second ;
            std::cout << rating << ' ' ;
            sum += rating ;
            ++cnt ;
        }

        std::cout << "] average rating: " << double(sum) / cnt << '\n' ;
        iter = next ;
    }
}

int main()
{
    const std::string file_path = "movie.txt" ;
    std::ifstream file(file_path) ;

    // throw the first line away; we don't really need it
    int n ;
    file >> n >> std::ws ; // also discard trailing white space
    std::cout << "#entries == " << n << '\n' ; // for debugging purposes

    print_summary( create_db_from(file) ) ;
}
Topic archived. No new replies allowed.