HELP: store csv numerical data to vector of double

Pages: 12
Hi all, I'm new to c++ and currently i need to write a program to open csv file and store all data into a vector of double. I have read through the forum and i manage to write a program that can store data in a vector of string which is not suitable for my case because my algorithm function is expect a double type data. So I need help how to fix this problem. How to store the numerical data in vector of double?

My code:

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 main (int argc, char *argv[])
{
     std::vector<string> file;
    double *signal; 
    string filename, line; //added filename
    int linenum = 0;
	cout <<"Enter the filename " << endl;
	getline (cin, filename);

	ifstream inFile;
	inFile.open(filename.c_str());

	 if (!inFile){
        cout<<"Error opening - " <<filename<<endl;
		system("PAUSE");
        return -1;
    }

    while (getline (inFile, line))
    {
        istringstream lineStream(line);
        string item;
	getline(lineStream, item);	
	file.push_back (item);
        signal = &item; //*signal suppose to store the data from csv file
        InputSignal(signal); //my algorithm function	
        }

	
system("PAUSE");
return 0;
}


Example of my csv file data:

1223134360 13016 722 809 0.008 0 -0.002
1223134360 13017 612 723 0.012 0 -0.003
1223134360 13018 590 627 0.015 0 -0.004
1223134360 13019 609 600 0.018 0 -0.003
1223134360 13020 607 629 0.022 0 -0.004
1223134360 13021 629 624 0.025 0 -0.004
1223134360 13022 666 629 0.029 0 -0.003

Hope you guys can help me..Thanks in advanced.
1
2
3
istringstream lineStream(line);
string item;
getline(lineStream, item);

Instead of calling getline on this istringstream, you should use the istringstream's operator >> to extract the string as a double.
Hi shacktar, thanks for your reply. I have changed the getline to operator >> and there is an error when i'm compiling the code.

the error:

error C2440: '=' : cannot convert from 'std::string *' to 'double *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

Is my pointer problem?how can i pass the csv data into my InputSignal function?

Thanks.
Perhaps I should've been more explicit. You do not need to have string item; anymore since you will be getting a double.

1
2
3
4
double item;
lineStream>>item;
file.push_back(item); //file needs to be a vector<double> now
signal = &item;

That should work for you.
Why is your double a pointer anyways? That doesn't make any sense.

 
signal /*this a double*  */ = &item/*this is a string*  */;


You're trying to assign a pointer that's supposed to point to stuff like "hello" to a pointer that's supposed to point to stuff like 2.712 - I don't get why you're doing this.
Last edited on
Yeah, that compilation error should have shown up with the original code. Maybe it was declared double* in anticipation of actually receiving a double from the file.
Last edited on
Shacktar:

i have make the following correction but there is an error C2065: 'lineStream' : undeclared identifier shown up:

std::vector<string> file; changed to std::vector<double> file;
string item; changed to double item;
getline(lineStream, item); changed to lineStream>>item;

Hanst99:

i know my pointer is double and from my original code the pointer is pointing a string type. That's why i want to read my csv file into double instead of string so that my pointer can point to same data type and pass to InputSignal function.

I'm apologize that i might asking some silly question because i'm totally new to c++. Sorry about that and hope u guys can help me out. Thanks.
Last edited on
Shacktar:

I have solved the error already, but another issue is i use cout << *signal; to print out the data, but the result is shown below:

1223134360
1223134360
1223134360
1223134360
1223134360
1223134360
1223134360

What I am expecting is the *signal should contain only the last three column " 809 0.008 0 -0.002" data. Do I need to create another array and use the *signal pointing at array instead of &item?

Thanks.
Can you post the new code?

With your example text file and this code:

1
2
3
4
5
6
7
8
9
10
while (getline (inFile, line))
{
    istringstream lineStream(line);
    double item;
    lineStream>>item;	
    file.push_back (item);
    signal = &item;

    InputSignal(signal);	
}


then it makes sense that it's only grabbing the first column. You can make an array of doubles and extract the columns into there.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while (getline (inFile, line))
{
    istringstream lineStream(line);

    double data[6]; //one double for each column

    //extract each column for this line
    for(int i = 0; i < 6; i++)
    {
        lineStream>>data[i];
    }
    
    ...
}


data[3], data[4], and data[5] would contain the last three columns.
Last edited on
Thanks for your reply shacktar..I will try to work on it..will ask again if I couldn't solve it. :)
Hi, after trying my codes for few days, i have encountered a problem. I couldn't load all columns for data into an array.Please help me to check my codes where is the problem.
Thanks.

my main function codes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
while (getline(inFile, line))
    {
		double item[3];
		int nearestID	= CSOINN::NOT_FOUND;

		istringstream lineStream(line);
		for(j = 0; j < 3; j++){
		lineStream >> item[j];
		cout << "item: " <<item[j] <<endl;
		signal = &item[j];
		}
		pSOINN->InputSignal(signal);
}
cout << endl;
cout << "Input finished processing, classifying..." <<" " <<endl;

pSOINN->Classify();

system("PAUSE");
return 0;
}


Then "signal" should contain all the data from csv.file's column and pass data to InputSignal function.
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
bool CSOINN::InputSignal(const double *signal){

FindWinnerAndSecondWinner(winner, secondWinner, signal);

}

bool CSOINN::FindWinnerAndSecondWinner(int &winner, int &secondWinner, const double *signal){
dist = Distance(m_nodeInfo[i].m_signal, signal);
}

double CSOINN::Distance(const double *signal1, const double *signal2)
{
	int i;
	double sum;
	double error;
	if (signal1 == NULL || signal2 == NULL) return 0.0;
	
	error = 0.0;
	sum = 0.0;
	for (i=0; i<m_dimension; i++)
	{
		sum += (signal1[i]-signal2[i])*(signal1[i]-signal2[i]);
	}
	
	return sqrt(sum)/(double)m_dimension;
}


How can i use a pointer to store all data from the csv.file's column and pass to these functions?hope you can help me out. I have been stuck for few days ago..
Thanks..
Sorry i have forgotten to show the output..The output for de code is:

item: 1
item: 2.54183e-317
item: 8.2609e-318

item: 6
item: 2.54183e-317
item: 8.2609e-318

item: 0.1
iitem: 2.54183e-317
item: 8.2609e-318

and so on...

but my csv file data is below:

1 2 3 4 5
6 7 8 9 10
0.1 0.2 0.3 0.4 0.5
3.5 0.7 0.8 0.9 1
1.1 1.2 1.3 1.4 1.5
2.11 2.12 2.13 2.14 2.15

Thanks
1
2
item: 2.54183e-317
item: 8.2609e-318

These results are strange. Assuming those are the lines it's reading, then there shouldn't be a problem with the output here. Did you print line (and lineStream.str()) to make sure they match with the file? Also, I assume j is declared somewhere?

signal = &item[j];

There's a problem here because signal will point to the last member in the array after that loop is over. That means signal[i] where i >= 1 would mean an array out of bounds. If you want to access all three elements of the array, then you can just pass data into InputSignal.
Thanks for the reply shacktar..

the j has been declared and I forgot to paste it in previous post. Thanks for your reminding and i realized the signal only point to the last member of array.

Can you show me how to pass 1 row of data frm csv file into InputSignal function? Because my idea is i want to pass row by row of data into InputSignal but i have no idea how to do it. For example, data 1 2 3 4 5 should pass into InputSignal then next data will be 6 7 8 9 10.

Thanks.
Well, it would be mostly like what you have:

1
2
3
4
5
6
7
8
9
10
11
12
double item[5];
int nearestID = CSOINN::NOT_FOUND;

istringstream lineStream(line);

for(int j = 0; j < 5; j++)
{
    lineStream >> item[j];
    cout << "item: " <<item[j] <<endl;
}

pSOINN->InputSignal(item);


InputSignal would have the same signature as you have it:

bool CSOINN::InputSignal(const double *signal)

There (and any function you pass signal to), you can do signal[i] to access members of item for i from 0 to 4, inclusive.

What's bugging me though is the garbage that's being printed out when j is 1 or 2. At this point, I would say that that would happen if the line being read is not matching the file.
Hi shacktar, i have modified the code and the output still the same. the output still printed out whn j is 1 and 2.

Code below is how i read the csv file:
1
2
3
4
5
6
7
8
9
10
11
12
13
string filename, line; //added filename
int linenum = 0;
cout <<"Enter the filename " << endl;
getline (cin, filename);

ifstream inFile;
inFile.open(filename.c_str());

	 if (!inFile){
        cout<<"Error opening - " <<filename<<endl;
		system("PAUSE");
        return -1;
    }


Please help me to check if there is any mistake of my code to read a csv file.
Thanks..
That code looks right. You should try printing line before passing it to the stringstream to make sure the string is what you expect. Besides that, all I can think of is there's some kind of undefined behaviour (division by zero, dereference null pointer, etc.) that's happening before the population of the item array that's causing the corruption. Posting the rest of the relevant code may be helpful.
csv = comma-separated value
jayden118 wrote:
Example of my csv file data:
1223134360 13016 722 809 0.008 0 -0.002
That is not csv ¿?

jayden118 wrote:
Code below is how i read the csv file:
1
2
/* Code that shows how you are openning the file
But no how you are reading it */


¿Why are you using an stringstream for?
Last edited on
Well, that would cause the stringstream to put garbage into all but the first double. If your line is this:

1, 2, 3, 4, 5

then lineStream >> item[1] would try to put a comma into item[1] and the stringstream would be in a bad state.

To read a particular line from the file, you should do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
while (getline (inFile, line))
{
    //knowing there are 5 entries
    double item[5];
    string dataEntry; //a particular entry as a string

    istringstream lineStream(line);

    for(int i = 0; i < 5; i++)
    {
        //get one entry
        getline( lineStream, dataEntry, ',');
        lineStream >> ws; //remove whitespace after the comma and before the next entry

        istringstream( dataEntry ) >> item[i];
    }

    pSOINN->InputSignal(item);
}

Last edited on
Hi shactar and ne555, the code is working finally. Thank you so much for spending your time to help me.

One more question is:
How can i just read the last three columns of csv file and skip the 1st and 2nd columns. Because some of my csv file i do not need the 1st and 2nd columns.


Thanks.
Pages: 12