Storing data in a map of vector<double>'s

Hello everyone,

I am trying to read a file with a lot of data and store this data in a map with vectors. The file has one line of strings as the first line, which I want to use as keys, and all the other lines are data that I want to store in the vector<double>.

I read the file twice. The first time to store all the data (accept for the strings in the first line) in a vector "temp". The second time I sort the data in "temp" according to the key they belong to. I think the problem lies there, because the pogram prints "name" in the "for (int line)" - loop but then I get a segmentation violation..

Can someone help me with this?

Regards Nik

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 <sstream>
#include <string>
#include <string.h>
#include <fstream>
#include <vector>
#include <map>

  int main()
{	
		
	const char * data_file = "testWPS.txt" ;
		
		int NoC = 1259 ; 
		int NoL = 167 ;
		
		vector<double> temp ; // vector with all the data of the file
		double value ;
		// store the data in v_temp, v_temp is read out later
		ifstream file0(data_file) ;
		if (file0.is_open()) {
			for (int header = 0; header < NoC+1; header++) {
				file0 >> value ;
			} // end for header
			while (file0.good()) {
				file0 >> value ;
				temp.push_back(value) ;
				if( file0.eof() ) { break ; }
			} // end while good
			file0.close() ;
		} // end if open
		else { cout << "Unable to open data file!" << endl ; }
		
		map< string, vector<double> > WPS ;
		string name ;
	
		// store the data of v_temp with a key in the WPS map
		ifstream file1(data_file) ;
		if ( file1.is_open()) {
			for ( int column = 0; column < NoC; column++){
				file1 >> name ;
				for (int line = 0; line < NoL; line++) {
					cout << name << endl ;
					WPS[name].push_back(temp[line*NoC+column]) ;
				} // end for line*/
			} // end for column
			file1.close() ;
		} // end if open
		else { cout << "Unable to open data file!" << endl ; }

	vector<double> wps_pbb_c_ux = WPS["WPS_PBB_C_UX"] ;
	
	for (int i = 0; i < 1259; i++) {
		cout << "Value " << i << ": " << wps_pbb_c_ux[i] << endl ;
	}
	 
    return 0 ;
}
Last edited on
Morning chap.
Stick a breakpoint on line 34 and examine your temp vector. how many elements does it have?
I suspect your issue is here:

temp[line*NoC+column]

if 'line*NoC+column' is greater than the number of elements in 'temp' then it's going to blow up.

But..
I read the file twice.

I'm not entirely sure why you have to read the file twice to be honest.
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
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <map>
#include <string>
#include <vector>

using namespace std;

int main()
{	
	map< string, vector<double> > WPS;
	string name;

	name = "test";
	vector<double> values;
	values = { 1, 2, 3, 4, 5 };

	WPS.insert(pair<string,vector<double>>(name, values));

	// output the value associated with the string.
	for (int i = 0; i < WPS[name].size(); i++)
	{
		std::cout << WPS[name][i] << std::endl;
	}


	int x;
	cin >> x;
	return 0;
}
#include "stdafx.h"

why?
i'm using visual c++ compiler.
ignore that.
So am i.
Creating a blank project does not add that in for you.
Hi Mutexe and Reafae11,

Thanks for the help. I checked the size of the temp vector and it is zero, so that might be causing the problem. I am going to look into it further because I don't know why it is zero. I think there is something wrong with the while(file0.good()) statement because when I use a cout in the loop, nothing is printed on the screen.

1
2
3
4
5
6
7
8

			while ( file0.good() ) {
				file0 >> value ;
				temp.push_back(value) ;
				cout << value << endl ; // nothing is printed..
				if( file0.eof() ) { break ; }
			} // end while good


The reason I read the file twice is because first I want to store all the data in a temporary file, so I skip the first line with strings

1
2
3
4
5
6

			for (int header = 0; header < NoC+1; header++) {
				file0 >> value ;
				cout << value << endl ;
			} // end for header


And then during the second time I just read the first line, storing the strings as keys, and picking out the right data point from temp.


Hi again,

I fixed it, I think the size of the vector was indeed the problem. I made it into a function and it looks like this now:

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

void getMap (const char * file_name, map<string, vector<double> > &Map) {	

	int NoC = NumberOfColumns(file_name) ;
	int NoL = NumberOfLines(file_name) ;

	//map<string, vector<double> > Map ;
	vector<double> Vec (NoC*NoL) ;
	string key ;
	double data ;

	ifstream file (file_name) ;
	if ( file.is_open() ) {
		while ( key.compare("END") != 0 ) {
			file >> key ;
		} // end while not END
		for ( int CL = 0; CL < NoC*NoL; CL++ ) {
			file >> data ;
			Vec[CL] = data ;
		}
		file.close() ;
	} // end if open
	else { cout << "Unable to open file!" << endl ; }

	ifstream File (file_name) ;
	if ( File.is_open() ) {
		for ( int column = 0; column < NoC; column++ ) {
			File >> key ;
			if ( key.compare("END") == 0 ) { break ; }
			for ( int line = 0; line < NoL; line++ ) {
				Map[key].push_back(Vec[column+line*NoC]) ;
			} // end for line
		} // end for column
		File.close() ;
	}
	else { cout << "Unable to open file!" << endl ; }

	/*vector<double> x = Map["X"] ;

	for (int i = 0; i < NoL; i++) {
			cout << "Value " << i << ": " << x[i] << endl ;
	}*/

} // end void getMap


Thanks for the help!
No worries. Whilst i haven't looked at it in detail i'm still fairly sure you'll only need to read the file once :)
Yeah there is probably a way to read it once, but I can't figure it out.
The problem I have is that in one line, there is a value for every key. So there are "the number of columns" amount of values in one line and each value in that line belongs to a different key.

So the only way I could do it was by reading the file twice but if you think of a different approach I would love to read it :)

Thanks anyway!
you only need to read once.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
map< string, vector<double> > Map;

ifstream file(file_name);
if (file.is_open()) 
{
	while (key.compare("END") != 0) 
	{
		file >> key;
	} // end while not END

	for (int CL = 0; CL < NoC*NoL; CL++) 
	{
		file >> data;
		Vec[CL] = data;
	}

        file.close();

       // insert your data here.
	Map.insert(pair<string, vector<double>>(key, Vec));
	
} // end if open
else { cout << "Unable to open file!" << endl; }
Hi Rafae11,

I tried this method but I get a segmentation violation instantly. I searched on the internet and I can only find examples of the use of insert if an int or a double in paired up with a key.

Vec contains all the unsorted data, don't you think I have to sort it first?

Thanks,
Nikkie
can you post a sample of the data file?

I don't think you need to sort the data.
Sure (sorry for the late reply I was on a holiday..)

A data sample:

1
2
3
4
5
6
7
MID	SEQ	G	A	T	X	Y	SCALE	ROTZ	SAMPLE_TIME	END
5622009	515331	4	-858993460	16	0.000000	0.000000	0.000000	0.000000	1415199540.000000
5622016	515332	0	0	16	0.000150	-0.008670	0.000000	0.000000	1415199597.000000
5622033	515333	0	0	16	-0.000540	-0.003080	0.000000	0.000000	1415199654.000000
5622040	515334	0	0	16	-0.005280	-0.013590	0.000000	0.000000	1415199711.000000
5622047	515335	0	0	16	-0.006660	-0.012390	0.000000	0.000000	1415199768.000000
5622054	515336	0	0	16	0.003760	0.071940	0.000000	0.000000	1415199826.000000


So I am lot further now, but when I want to manipulate the data, and plot it eventually, the code seems to become way more simple if I make a map of doubles[], but that is another thing I can't solve. So I changed my code to 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
// storing Data from file_name in a Map
void getMapArr (const char * file_name, map<string, double[]> &Map) {	

	int NoC = NumberOfColumns(file_name) ;
	int NoL = NumberOfLines(file_name) ;

	double * Complete_Data = new double[NoC*NoL] ;
	string * keys = new string[NoC] ;
	double data ;
	string key ;

	ifstream file (file_name) ;
	if ( file.is_open() ) {
		for ( int i = 0; i < NoC; i++ ) {
			file >> key ;
			keys[i] = key ;
		} // end for i
		for ( int i = 0; i < NoC*NoL; i++ ) {
			file >> data ;
			Complete_Data[i] = data ;
		}
		file.close() ;
	} // end if open
	else { cout << "Unable to open file!" << endl ; }
	
	for ( int i = 0; i < NoC; i++ ) {
		double * temp_data = new double[NoL] ;
		for ( int j = 0; j < NoL; j++ ) {
			temp_data[j] = Complete_Data[i+j*NoC] ;
		} // end for j
		Map.insert( pair<string, double[]>(keys[i], temp_data) ) ;
		delete temp_data ;
	} // end for i

} // end void getMap 


And now I get the error: no matching constructor for initialization of
'pair<string, double []>'
Map.insert( pair<string, double[]>(keys[i], temp_data) )

So now I don't open the file twice that's and improvement, but I want to store the columns in arrays of doubles and that I can't do..

Can someone help me with that?

Cheers Nikkie

your sample data columns don't match
you have 11 string column header but your data has only 10 columns.
i just placed dummy data at the end so that the columns match.
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
#include <cstdlib>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <fstream>

using namespace std;

// storing Data from file_name in a Map
void getMapArr (string file_name, map<string, vector<double>> &Map) {	

	int NoC = 11; // i don't have your number of column function.
	int NoL = 6; // i don't have your number of lines function.

	// avoid using new if possible use vectors instead for arrays. 	
	vector <double> Complete_Data;
	vector<string> keys;

	double data ;
	string key ;

	ifstream file (file_name.c_str()) ;
	
	if ( file.is_open() ) 
	{	
		// read keys
		for ( int i = 0; i < NoC; i++ ) 
		{
			file >> key ;
			keys.push_back(key);
		} // end reading keys
		
		// read all the data
		for ( int j= 0; j < (NoC * NoL); j++ ) 
		{
			file >> data ;
			Complete_Data.push_back(data);
		}// end reading data.

		file.close() ;
	} // end if open
	else 
	{ 
		cout << "Unable to open file!" << endl ; 
	}
		
	vector<double> temp;

	for ( int i = 0; i < NoC; i++ ) 
	{	
		for ( int j = 0; j < NoL; j++ ) 
		{				
			// store in buffer
			temp.push_back(Complete_Data[i+j*NoC]);
		}

		// insert in map
		Map.insert( pair<string, vector<double>>(keys[i], temp)) ;
		
		// clear temporary buffer
		temp.clear();
	} // end for i


	
	
} // end void getMap 
int main()
{			
	string filename("sample.txt");
	map< string, vector<double> > WPS;
	getMapArr(filename,WPS);

	// test output
	string name = "END";
	// output the value associated with the string.
	for (int i = 0; i < WPS[name].size(); i++)
	{
		std::cout << WPS[name][i] << std::endl;
	}	

	int x;
	cin >> x;
	return 0;
}

Topic archived. No new replies allowed.