Hello
I have a problem with reading the coordinates of points which are extracted from (..txt ) file.I have read the file with ifstream but I don't know how to use the information then. Thanks in advance
the point are in File as followed :
u:1.2000 v:4.5400
u:2.5450 v:6.4500

Recommended Answers

All 21 Replies

Read a line in the file into a std::string with getline() and then parse that string with a stringstream.

I'm not sure it's the most efficient way to do it, but to start, break it in half on the space, then read the halves up until ':' and throw that part away, then read in the numbers.

Thanks for reply. I have written the following code:

#include <iostream>
#include <string>
#include <fstream>
#include <cctype>
#include <stdlib.h>


using namespace std;

struct point
{
	double x;
	double y;
	double height;
};

void main ()
{
	ifstream pts("rechteck.txt");
	string s;
			
	if (pts.is_open())
	{
					
	while (!pts.eof())
		{
		getline (pts,s);
		string xcor=s.substr(2,6);  cout<<"x:"<<xcor<<endl;
		string ycor=s.substr(11,6); cout<<"y:"<<ycor<<endl;
          pts.close();
}

but I don't know how I can convert the string to double , because I will use this coordinates later.

Are your numbers guaranteed to be a fixed number of digits? If not, you'll have to do the splitting like I was saying.

For the way you have it:

point pt;
stringstream ss(xcor); //set up a stringstream with the first string
ss >> pt.x;  //extract the number
ss.clear();  //reset the stream to the beginning
ss.str(ycor); //set the stringtream to the second string
ss >> pt.y;  //extract the second number

be sure to #include <sstream> Something like atof is also a possibility if you wanted to go that route.

Put your getline statement in the while loop to drive it rather than using .eof() (which can read the last line twice in some cases)

while(getline(pts,s))
{
}

Also, main is never void, it always returns an int according to the standard.

Thanks alot. Which arguments I need for atof and where should I put it in my code in order to work with all points.

You need to use the .c_str() method of your strings to get their C-string representation:

point pt;
pt.x = atof(xcor.c_str());
//etc.

Did you mean that have to use atof and C-string after:

point pt;
stringstream ss(xcor); //set up a stringstream with the first string
ss >> pt.x;  //extract the number
ss.clear();  //reset the stream to the beginning
ss.str(ycor); //set the stringtream to the second string
ss >> pt.y;  //extract the second numbers

without for loop.

No, apologies. It's either one or the other. Presumably you'll want an array of points, so you can incorporate the code into your while loop and increment an index to keep track of where you are in the points array.

Now my code is something like :

#include <iostream>
#include <string>
#include <fstream>
#include <cctype>
#include <stdlib.h>


using namespace std;

struct point
{
	double x;
	double y;
	double height;
};

int main ()
{
	ifstream pts("rechteck.txt");
	string s;
			
	if (pts.is_open())
	{
					
	
      while(getline(pts,s))	
	{
		getline (pts,s);
		string xcor=s.substr(2,6);  cout<<"x:"<<xcor<<endl;
		string ycor=s.substr(11,6); cout<<"y:"<<ycor<<endl;

stringstream ss(xcor); //set up a stringstream with the first string
ss >> pt.x; cout<<pt.x<<endl; //extract the number
ss.clear();  //reset the stream to the beginning
ss.str(ycor); //set the stringtream to the second string
ss >> pt.y;  cout<<pt.y<<endl; //extract the second number
          
pts.close();
}

coulde I now use pt.y and pt.x as numbers.

Line 28 should be eliminated.

You will probably want to declare an array of points (or a vector if you don't know how many you will have) somewhere around line 20 or wherever it makes sense.

In this example, as long as you have declared a point pt, you can use pt.x and pt.y anyplace you would ordinarily use a double.

If I write point pt[50] instead of (point pt) what should I change in my code to get a specific point every time.How can I use the integer ipcounter here.

#include <iostream>
#include <string>
#include <fstream>
#include <cctype>
#include <stdlib.h>
#include <sstream>


using namespace std;

struct point
{
	double x;
	double y;
	double height;
};

int main ()
{
	ifstream pts("rechteck.txt");
	string s;
	point pt;
	char x,y;
	int ipcounter=0;
	
	if (pts.is_open())
	{
		while(getline(pts,s))
	{
		
		string xcor=s.substr(2,6);  cout<<"x:"<<xcor<<endl;
		string ycor=s.substr(11,6); cout<<"y:"<<ycor<<endl;
		
stringstream ss(xcor); //set up a stringstream with the first string
ss >> pt.x; //cout<<pt.x<<endl; //extract the number
ss.clear();  //reset the stream to the beginning
ss.str(ycor); //set the stringtream to the second string
ss >> pt.y;  //cout<<pt.y<<endl; //extract the second number
ipcounter++;
}}
pts.close();
return 0;
}

You can access the x and y of the ipcounter-th point by pt[ipcounter].x and pt[ipcounter].y substitute those in on lines 35 and 38.

Thank you very much again ^-^.
In case that I want to get height in addition to x and y I should only add the following sentences to my code after line 38.

ss.clear();  //reset the stream to the beginning
ss.str(hcor); 
ss >> pt.height;

and the folowing line after line 32:

string hcor=s.substr(??,6); cout<<"h:"<<hcor<<endl;

is that right .

Right, so you want your substring to start at 20.

You should compile it and check, though.

I have another question .If I have another set of points in the file and I want to get them to draw two polygons ,how should I change my code to get the two separate set of points and the number of points for each polygon.

That sounds like the meat of your assignment. I will not be able to take you through the entire thing step by step. Give it a try on your own now that you have some of the basics covered. If permitted, post your code attempt and someone can take a look at it for you.

I am sorry, I know that I have asked too much questions.
But the last question is,what should I write in while loop instead of :

while(getline(pts,s))

in order to get only the first set of points and then to get the second one.

I'm not upset, it's just that it's your assignment, so you need to put in some effort on it.

Are the points for each of the shapes together? (sh1 = shape1, p1 = point1)

sh1_p1
sh1_p2
sh1_p3

sh2_p1
sh2_p2
sh2_p3

or are they intermingled

sh1_p1
sh2_p1
sh1_p2
sh2_p2

If it's the former, there should be some delineation between the two sets, so scan until you hit that (if it's a blank line check for s == ""). Then start another while loop where you left off (the ifstream will keep track of where you are).

If it's the latter you could do something like

string s1;
string s2;

while(getline(pts,s1))  //advances the file one line
{
   //process s1 for first list
   
   getline(pts,s2); //advances the file another line
   
   //process s2 for the second list
}

Thanks again.
My file hase the form :

up=1.25400 vp=2.54500 heightp=0.00000
up=5.45000 vp=6.87000 heightp=0.00520

uq=1.20000 vq=2.50000 heightq=0.00000
uq=5.30000 vq=2.40000 heightq=0.00520

and I have modified the code to see like:

#include <iostream>
#include <string>
#include <fstream>
#include <cctype>
#include <stdlib.h>
#include <sstream>


using namespace std;

struct point
{
	double x;
	double y;
	double height;
};

int main ()
{
	ifstream pts("point.txt");
	string s;
	point pt1[50],pt2[50];
	int ipcounter=0;
	int iqcounter=0;
	
	if (pts.is_open())
	{
		while(getline(pts,s))
	{
		if(s!="")
		{
		string xcor1=s.substr(s.rfind("up=")+3,7);  cout<<"x1:"<<xcor1<<endl;
		string ycor1=s.substr(s.rfind("vp=")+3,7); cout<<"y1:"<<ycor1<<endl;
		string hcor1=s.substr(s.rfind("heightp=")+8,7); cout<<"h1:"<<hcor1<<endl;
		
		stringstream ss(xcor1); //set up a stringstream with the first string
		ss >> pt1[ipcounter].x; //cout<<pt.x<<endl; //extract the number
		ss.clear();  //reset the stream to the beginning
		ss.str(ycor1); //set the stringtream to the second string
		ss >> pt1[ipcounter].y;  //cout<<pt.y<<endl; //extract the second number
		ss.clear();
		ss.str(hcor1);
		ss >> pt1[ipcounter].height;
		ss.clear();
		ipcounter++;
		}
		else { break;}
		}
		
		while(getline(pts,s))
	{
		if(s!="")
		{
		string xcor2=s.substr(s.rfind("uq=")+3,7);  cout<<"x2:"<<xcor2<<endl;
		string ycor2=s.substr(s.rfind("vq=")+3,7); cout<<"y2:"<<ycor2<<endl;
		string hcor2=s.substr(s.rfind("heightq=")+8,7); cout<<"h2:"<<hcor2<<endl;
		
		stringstream ff(xcor2);//set up a stringstream with the first string
		ff >> pt2[iqcounter].x; //cout<<pt.x<<endl; //extract the number
		ff.clear();  //reset the stream to the beginning
		ff.str(ycor2); //set the stringtream to the second string
		ff >> pt2[iqcounter].y;  //cout<<pt.y<<endl; //extract the second number
		ff.clear();
		ff.str(hcor2);
		ff >> pt2[iqcounter].height;
		iqcounter++;
		}
		else { break;}
						
	}	
	}
	else 
	{cout<<"there is a problem with opening the file...."<<endl;}
	
	
	for(int i=0;i<ipcounter;i++)
	{
		cout<<"x1:"<<pt1[i].x<<"\t";
		cout<<"y1:"<<pt1[i].y<<"\t";
		cout<<"h1:"<<pt1[i].height<<endl;
	}

	for(int j=0;j<iqcounter;j++)
	{
		cout<<"x2:"<<pt2[j].x<<"\t";
		cout<<"y2:"<<pt2[j].y<<"\t";
		cout<<"h2:"<<pt2[j].height<<endl;
	}
	
	pts.close();
	    
cin.get();
return 0;

}

Is this good or is there a way better than this?

Seems perfectly reasonable. You could eliminate some of the duplicate code by detecting whether a line with a space has been read (or if the leading "up" has changed to a "uq") to separate the two, but that's just window dressing.

If there's any flexibility in the data file configuration, you may need to adapt your code to account for that (splitting the string on spaces and equals signs like I had originally suggested.

I haven't understood the first part of your last post correctly, could you explain more plz.

Use a boolean variable to distinguish whether the program has passed the empty line in the file. Once the line has past, reset the counter. If the statement about passing the empty line is false, write into the first array. If it's true, write into the second array. What you have works, so if you don't need the extra headache right now, I wouldn't worry about it.

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.