I'm trying to get each line of text of a file split into words and then put into an array

I found an exmaple oc cpluscplus.com and their example works but when i try to edit to make changes to read the line of text from a file i get an error on this line:

char str[] = getline(filename, line);

error message:

error c2440: 'initializing' : cannot convert from 'std::basic_istream<_Elem,_Traits>' to 'char[]'

I need to be able to read in a line and spilt the words into an array so i can output them

#include <fstream>
#include <iostream>
#include <string>
#include <stdio.h>

using namespace std;

int main()
{
	string GetFileName;

	cout << "System >> Enter file to read: \n";

	cout  << "User >> ";
	cin >> GetFileName;
	
	ifstream filename( GetFileName.c_str() );

	if(! filename )
	{
		cout << "Unable to open file: " << GetFileName << endl;

		return EXIT_FAILURE;
	}
	else
	{
		while (getline(filename, line)) //Loop through lines
		{
			char str[] = getline(filename, line);
			char * pch;
			
			pch = strtok (str," ");
			while (pch != NULL)
			{
			printf ("%s\n",pch);
			pch = strtok (NULL, " ");
			}
		}	
		filename.close();
	}
	return EXIT_SUCCESS;
}

Recommended Answers

All 16 Replies

Why can't you use a vector? It would be a lot less painful.

Though ,not a good approach but the following approach does work.(if your input contains texts which are separated by more than a couple of newlines,expect some unexpected characters in the output)

Inside the while loop

while (getline(filename, line)) //Loop through lines
		{
			char str[BUFSIZ] ;//BUFSIZ 
 // already defined in stdio.h 
	
            for(int i=0;line[i];++i)
			str[i]=line[i];
            
            
            char * pch=NULL;
			
			pch = strtok (str," ");
			while (pch!=NULL)
			{
			printf ("%s\n",pch);
			pch = strtok (NULL, " ");
			}
}

Thanks zalezog

I'm actually getting somewhere.

It does loop through each of the lines but it only outputs the first "token" on each line

This is an example of what i need to get from my file

1.4 0 0.5
2.3 1.7 0.1
0.8 0 0
0.7 1.0 0.2
1.2 1.3 0.5

Is there a way of tweaking the code cos the output is going to be changed later anyway but I need to get the first line into the array pointers [0][0], [0][1],[0][2] etc and the same for the other lines so i can select 2 array pointers and an display the contents

I'm trying to get each line of text of a file split into words and then put into an array

I found an exmaple oc cpluscplus.com and their example works but when i try to edit to make changes to read the line of text from a file i get an error on this line:

char str[] = getline(filename, line);

error message:


I need to be able to read in a line and spilt the words into an array so i can output them

#include <fstream>
#include <iostream>
#include <string>
#include <stdio.h>

using namespace std;

int main()
{
	string GetFileName;

	cout << "System >> Enter file to read: \n";

	cout  << "User >> ";
	cin >> GetFileName;
	
	ifstream filename( GetFileName.c_str() );

	if(! filename )
	{
		cout << "Unable to open file: " << GetFileName << endl;

		return EXIT_FAILURE;
	}
	else
	{
		while (getline(filename, line)) //Loop through lines
		{
			char str[] = getline(filename, line);
			char * pch;
			
			pch = strtok (str," ");
			while (pch != NULL)
			{
			printf ("%s\n",pch);
			pch = strtok (NULL, " ");
			}
		}	
		filename.close();
	}
	return EXIT_SUCCESS;
}

Is this the whole program? I don't see where line is declared. You have two getline statements when you only need one.

while (getline(filename, line)) //Loop through lines
		{
			char str[] = getline(filename, line);

The second one, even if it was syntactically correct, which it is not, overwrites line , which I imagine is supposed to be a string.

You can use char* or string with getline:

http://www.cplusplus.com/reference/iostream/istream/getline.html
http://www.cplusplus.com/reference/string/getline.html

The links above have examples of each.

Thanks zalezog

I'm actually getting somewhere.

It does loop through each of the lines but it only outputs the first "token" on each line

This is an example of what i need to get from my file

1.4 0 0.5
2.3 1.7 0.1
0.8 0 0
0.7 1.0 0.2
1.2 1.3 0.5

Is there a way of tweaking the code cos the output is going to be changed later anyway but I need to get the first line into the array pointers [0][0], [0][1],[0][2] etc and the same for the other lines so i can select 2 array pointers and an display the contents

If you want the whole line to be printed ,then replace every call with..

pch=strtok(str,"\n");

I don't understand,when you say

tweaking the code

If you want to store each word in your file(if that's what you mean)
then something like this might help:

//fragment code
string get_content[10][BUFSIZ];
    string words_per_line[5];
    //if memory isn't your constraint
	//if there are 10 lines in your file 
	//and if there are more than 5 words in your file
int count_line=0;
	 int count_word=0;

Then update them in your 'while' loop

while(getline(filename, line))
{
 for(int i=0;line[i];++i)
str[i]=line[i];
            
            
 char * pch=NULL;
char str[BUFSIZ]={0} ;


pch = strtok (str," ");
count_word=0;//reset after each line
while (pch!=NULL)
{
			
		get_content[count_line][count_word]=pch;
            pch = strtok (NULL, " ");
			
		array_words[count_line]=++count_word;
}
		++count_line;
        }

and display them using loops whose control variables are

count_word
count_line

Many thanks for helping me out....i've only been doing C++ for a month

Have i got the code right? It's complaining about 2 undeclared variables

"str" and "array_words"

Once i can get those words or whatever is in the file into my arrays i should be on a roll

#include <fstream>
#include <iostream>
#include <string>
#include <cstdio>

using namespace std;

int main()
{
	string GetFileName;
	string line;

	cout << "System >> Enter file to read: \n";

	cout  << "User >> ";
	cin >> GetFileName;
	
	ifstream filename( GetFileName.c_str() );

	if(! filename )
	{
		cout << "Unable to open file: " << GetFileName << endl;

		return EXIT_FAILURE;
	}
	else
	{
		//fragment code
		string get_content[10][BUFSIZ];
		string words_per_line[5];
		//if memory isn't your constraint
		//if there are 10 lines in your file 
		//and if there are more than 5 words in your file
		int count_line=0;
		int count_word=0;
	 
		while(getline(filename, line))
		{
			for(int i=0;line[i];++i)
				str[i]=line[i];
                       
				char * pch=NULL;
				char str[BUFSIZ]={0} ;

				pch = strtok (str," ");
				count_word=0;//reset after each line
				while (pch!=NULL)
				{	
					get_content[count_line][count_word]=pch;
					pch = strtok (NULL, " ");
						
					array_words[count_line]=++count_word;
				}
			++count_line;
        }	
		filename.close();
	}
	return EXIT_SUCCESS;
}

If the compiler is complaining, the code is obviously still not right.

Maybe you should define the missing symbols?

try int array_words[10]; right next to where you declare get_content. (They're both used in the same place.)

The declaration for char str[BUFSIZ] needs to come before the for loop that copies into it:

for(int i =0; line[i];++i)
    str[i]=line[i];

That code sure looks like a strcpy() to me, maybe you should look into it.

PS- When posting c++ code, please use c++ code tags
[code=c++] // Your code here

[/code]

That code sure looks like a strcpy() to me, maybe you should look into it.

string line;
char str[BUFSIZ];

1. Murtan is absolutely right when he says that declaration of

str[BUFSIZ];
int array_words[10];

should be before the loop where the content of 'str' is copied into 'line',same goes with array_words[10]
2.As the declarations of 'str' and 'line' are not ,C-styled strings,i had to use a for loop.Perhaps, AdRock tried using

strtok(..,..)

with string line and got stuck, that's how the whole thread began.:icon_lol:

So line is a string and str is a C style string so you can use strtok on it.

Why not just use strcpy(str, line.c_str()) ?


So line is a string and str is a C style string so you can use strtok on it.

Why not just use strcpy(str, line.c_str()) ?

That's done Murtan suggested a better way to solve the problem,I got your point and may be we utilize the memory a bit more efficiently this time in our while loop..

//fragment code
while (getline(filename, line)) //Loop through lines
		{
			
            char *str;
	        str=new char[line.length()+1];
            strcpy(str,line.c_str());            
            
            char * pch=NULL;
			count_word=0;
			pch = strtok (str," ");
			while (pch!=NULL)
			{
			
			get_content[count_line][count_word]=pch;
            pch = strtok (NULL, " ");
			
			array_words[count_line]=++count_word;
            }
		++count_line;
        delete []str;
        }	
		filename.close();
	}
//display each word	
for(int p=0;p<count_line;++p)
	for(int u=0;u<array_words[p];++u)
    cout<<get_content[p][u]<<endl;;

Perhaps we could welcome him to the world of C++, rather than staying in the dark ages of C. Vectors, as have already been suggested would be a better approach....as would stringstreams.

#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <string>

using namespace std;

int main(void){
    ifstream data("test.dat", ios::in);
    string line, temp;
    istringstream oss;
    int count = 0;
    vector< vector<string> > DataFromFile;

    while(getline(data, line)){
        DataFromFile.push_back( vector<string>() );
        oss.clear();
        oss.str(line);
        while(oss >> temp)
            DataFromFile[count].push_back(temp);
        count++;
    }

    for(int i = 0; i < DataFromFile.size(); i++){
        for(int x = 0; x < DataFromFile[i].size(); x++)
            cout << DataFromFile[i][x] << '\t';
        cout << endl;
    }
    return 0;
}

Chris

I've come back to this cos it was doing my head in

I have to do this

In order to make the matrix implementation as flexible as possible, we will not place an a priori limit on the size of the matrix that can be represented. This will require the use of dynamic memory allocation. Consequently, the private data members for matrix is consist of the variable rows and cols, which will be used to store the row and column dimensions of a matrix, and element, which will be used to store a variable of type pointer-to-pointer-to-double. For a given matrix, the variable element will point to an array of pointers, and each element in this array of pointers will point to another array that contains the elements belonging to a single row of the matrix.

Each "row" and "col" has a name (string data type) and is identified by an identifier (int type) in the matrix. To elaborate further, each row in the matrix represents a "row" and each column index represents a unique name of a "col".

I've attached the type of file i want to read

I have been thinking the last couple of days the best way to do this.I was thinking about creating a function to read the file once, count the number of lines between the <rows> tags and create a vector or array. Then another function to count the number of lines between the <col> tags and create another vector or array and add whatever is between those tags to the vector/array.

I just need a point in the right direction and to find out what is the best way of doing this so i can crack on.

I am going to have another crack at it now and see how far i get

I have been working on this for a little while and have come up with this which isn't perfect by far

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

void number_rows(string file)
{
	ifstream myfile(file);
	if (!myfile)
	{
		cout << "I could not open the file.\n";
		//return EXIT_FAILURE;
    }
	else 
    {
		string line;
	
		vector<string> rows;
	
		while (getline( myfile, line ))
		{
			string str1 = "<row>";
			string str2 = "</row>";
			int pos = line.find(str1, 0);
			if(pos !=string:: npos)
				continue;
			else
			pos = line.find(str2, 0);
			if(pos != string::npos)
				break;
			else
				rows.push_back(line);	
		}
	}
    myfile.close();
}

void number_cols(string file)
{
	ifstream myfile(file);
	if (!myfile)
	{
		cout << "I could not open the file.\n";
		//return EXIT_FAILURE;
    }
	else 
    {
		string line;
	
		vector<string> cols;
	
		while (getline( myfile, line ))
		{
			string str1 = "<col>";
			string str2 = "</col>";
			int pos = line.find(str1, 0);
			if(pos !=string:: npos)
				continue;
			else
			pos = line.find(str2, 0);
			if(pos != string::npos)
				break;
			else
				cols.push_back(line);	
		}
	}
    myfile.close();
}

void get_matrix(string file)
{
	/*ifstream data(file, ios::in);
    string line, temp;
    istringstream oss;
    int count = 0;
    vector< vector<string> > DataFromFile;

    while(getline(data, line)){
        DataFromFile.push_back( vector<string>() );
        oss.clear();
        oss.str(line);
        while(oss >> temp)
            DataFromFile[count].push_back(temp);
        count++;
    }*/
}

int main()
{

	string file = "words.txt";

	ifstream myfile(file);
	if (!myfile)
	{
		cout << "I could not open the file. Fooey.\n";
		return EXIT_FAILURE;
	}
	else 
	{
		number_rows(file);
		number_cols(file);
		//matrix(myfile);
	}
	return EXIT_SUCCESS;
}

what the plan is, is to have seperate functions that adds anything between the <row></row> and <col></col> tags.

I just want to declare a filename once and pass that as a parameter but i get these errors

crap.cpp(10) : error C2664: 'std::basic_ifstream<_Elem,_Traits>::basic_ifstream(const char *,std::ios_base::openmode,int)' : cannot convert parameter 1 from 'std::string' to 'const char *'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called crap.cpp(42) : error C2664: 'std::basic_ifstream<_Elem,_Traits>::basic_ifstream(const char *,std::ios_base::openmode,int)' : cannot convert parameter 1 from 'std::string' to 'const char *'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called crap.cpp(95) : error C2664: 'std::basic_ifstream<_Elem,_Traits>::basic_ifstream(const char *,std::ios_base::openmode,int)' : cannot convert parameter 1 from 'std::string' to 'const char *'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

am i on the right track?

I have been working on this for a little while and have come up with this which isn't perfect by far

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

void number_rows(string file)
{
	ifstream myfile(file);
	if (!myfile)
	{
		cout << "I could not open the file.\n";
		//return EXIT_FAILURE;
    }
	else 
    {
		string line;
	
		vector<string> rows;
	
		while (getline( myfile, line ))
		{
			string str1 = "<row>";
			string str2 = "</row>";
			int pos = line.find(str1, 0);
			if(pos !=string:: npos)
				continue;
			else
			pos = line.find(str2, 0);
			if(pos != string::npos)
				break;
			else
				rows.push_back(line);	
		}
	}
    myfile.close();
}

void number_cols(string file)
{
	ifstream myfile(file);
	if (!myfile)
	{
		cout << "I could not open the file.\n";
		//return EXIT_FAILURE;
    }
	else 
    {
		string line;
	
		vector<string> cols;
	
		while (getline( myfile, line ))
		{
			string str1 = "<col>";
			string str2 = "</col>";
			int pos = line.find(str1, 0);
			if(pos !=string:: npos)
				continue;
			else
			pos = line.find(str2, 0);
			if(pos != string::npos)
				break;
			else
				cols.push_back(line);	
		}
	}
    myfile.close();
}

void get_matrix(string file)
{
	/*ifstream data(file, ios::in);
    string line, temp;
    istringstream oss;
    int count = 0;
    vector< vector<string> > DataFromFile;

    while(getline(data, line)){
        DataFromFile.push_back( vector<string>() );
        oss.clear();
        oss.str(line);
        while(oss >> temp)
            DataFromFile[count].push_back(temp);
        count++;
    }*/
}

int main()
{

	string file = "words.txt";

	ifstream myfile(file);
	if (!myfile)
	{
		cout << "I could not open the file. Fooey.\n";
		return EXIT_FAILURE;
	}
	else 
	{
		number_rows(file);
		number_cols(file);
		//matrix(myfile);
	}
	return EXIT_SUCCESS;
}

what the plan is, is to have seperate functions that adds anything between the <row></row> and <col></col> tags.

I just want to declare a filename once and pass that as a parameter but i get these errors


am i on the right track?

As far as the errors you are encountering,

ifstream myfile(file);

should be replaced with:

ifstream myfile;
myfile.open(file.c_str());

or

ifstream myfile(file.c_str());

@Zalezog

Don't quote the whole message if you only want to comment on a few lines.

@AdRock
When posting c++ code, please use c++ code tags
[code=c++] // Your code here

[/code]

(Don't make me tell you again)

With vectors, you don't have to make a 'first pass' to count the number of records and a 'second pass' to read the data. The vectors don't have a size limit.

If you want to confirm that your matrix is rectangular, you could verify the counts after you're done reading.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.