C++ Reading Data File: Calculating Distances and Finding Closest Point

In summary: Read in the data count = 0; while(!eof(inFile)) { infile >> x >> y >> z; count++; // Increment the counter every time you read a point} // Save the data xcoordinates[count] = x; ycoordinates[count] = y; zcoordinates[count] = z; }In summary, the code reads in a file of points, calculates the distances between the points, and stores the data in
  • #1
Joon
85
2

Homework Statement



I have successfully opened and discarded the headers. Then I calculated the distances between point 1 and others and the minimum distance as well. However, I am not sure how to make the code work for more than 4 points. The attached text file is what I am trying to read and extract data from.

Also, I need to tell which is the closest point to point 1 and the distance between point 1 and the closest point on the output screen, what would be the best way of doing this?

Your help would be appreciated. Thank you.

Homework Equations

The Attempt at a Solution



C:
// Program to read an input file 

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;

int main() {

    double x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, dist_12, dist_13, dist_14, minimum_distance;
    ifstream inFile("input-week6-ad-q4-2.txt"); // ifstream function to read the file
    string line, c; // To read the characters
    char ch;    if (inFile.is_open())
    {
        getline(inFile, line); // To read the header of the input file then discard it
        getline(inFile, line);       
        inFile >> x1 >> y1 >> z1;
        inFile >> x2 >> y2 >> z2;
        inFile >> x3 >> y3 >> z3;
        inFile >> x4 >> y4 >> z4;

        inFile.close();        dist_12 = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1) + (z2 - z1)*(z2 - z1));
        dist_13 = sqrt((x3 - x1)*(x3 - x1) + (y3 - y1)*(y3 - y1) + (z3 - z1)*(z3 - z1));
        dist_14 = sqrt((x4 - x1)*(x4 - x1) + (y4 - y1)*(y4 - y1) + (z4 - z1)*(z4 - z1));

        minimum_distance = min(min(dist_12, dist_13), min(dist_13, dist_14));

        cout << "The distance between point 1 and 2 is " << dist_12 << "\n";
        cout << "The distance between point 1 and 3 is " << dist_13 << "\n";
        cout << "The distance between point 1 and 4 is " << dist_14 << "\n";
        cout << "The minimum distance between point 1 and another point is " << minimum_distance << "\n";
           }    else
        cout << "The file could not be opened." << "\n"; // To check for any error

    system("pause");
    return 0;
}
 

Attachments

  • input-week6-ad-q4-2.txt
    9.8 KB · Views: 314
Physics news on Phys.org
  • #2
Have you used arrays? Have you used for or while loops? You need both of those to generalize this to an arbitrary number of points.

You would define x, y and z are arrays of whatever your expected maximum size is. My C++ is a little rusty but I think you can even figure out at runtime what the maximum size is and allocate the space for the arrays then.

Then your input code would be something like:

Code:
int i = 0;
while(!eof(infile)) {
    infile << x[i] << y[i] << z[i] ;
    i++;    // Increment this every time you read a point
}
int number_of_points = i;
The while loop condition is however you test for end-of-file (EOF) in C++. Again, I'm rusty on this.

The calculation of distance would be done in a for loop, looping from point 2 to the last point and keeping the distances in another array. And the comparison to find the smallest would be done in another for loop.
 
Last edited:
  • #3
I have tried to modify the code, could you check please?
Thank you.
The code now reads the data all the way through the end.
How do I tell which is the closest point to point 1 and the distance between point 1 and the said closest point?

C:
// Program to read an input file 

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;

int main() {

    const int MAXI = 1000;    double x, y, z, xcoordinates[MAXI], ycoordinates[MAXI], zcoordinates[MAXI];
    int i, count;

    ifstream inFile("input-week6-ad-q4-2.txt"); // ifstream function to read the file
    string line, c; // To read the characters
   

    if (inFile.is_open())
    {
        getline(inFile, line); // To read the header of the input file then discard it
        getline(inFile, line);        i = 0;
        count = 0;
        while (inFile >> x >> y >> z){
           
            xcoordinates[count] = x;
            ycoordinates[count] = y;
            zcoordinates[count] = z;
            count = count + 1;
        }

        for (i = 0; i < count; i++) {
            cout << xcoordinates[i] << " " << ycoordinates[i] << " " << zcoordinates[i] << "\n";
        }
       

        inFile.close();      
    }    else
        cout << "The file could not be opened." << "\n"; // To check for any error

    system("pause");
    return 0;
}

[code/c]
 
  • #4
Well, you see the syntax of a for loop in that example. Use that structure.
The general way you find a minimum in a for loop is this (not real code, insert your variables and proper syntax):

Code:
minval = SOME_BIG_NUMBER;
for (i = 0; i < n; i++) {
  if (array[i] < minval) minval = array[i];
}

"minval" is tracking the smallest value found so far. If the next one you check is smaller than "minval", you update "minval" to the new smallest value.

If you're trying to track WHERE the minimum occurred, you might have this structure.
Code:
minval = SOME_BIG_NUMBER;
minindex = SOMETHING_NOT_IN_YOUR_ARRAY;
for (i = 0; i < n; i++) {
  if (array[i] < minval) {
      minval = array[i];
      minindex = i;
}

Notice how when I find a new lowest value, I update minindex to store where it happened. Assigning nonsense initial values gives you something to check afterward to see if the algorithm worked right. If the nonsense values are still there, something went wrong.

What you're finding is the minimum distance from your first point. Arrays in C++ start at 0 not 1. So you want to start the for loop at i = 1, meaning the second point, and each time through you'll calculate the distance from point 0.
Code:
minval = SOME_BIG_NUMBER;
minindex = SOMETHING_NOT_IN_YOUR_ARRAY;
for (i = 1; i < n; i++) {  // Notice it starts at 1 now.
  array[i] = distance of point[i] from point[0];
  if (array[i] < minval) {
      minval = array[i];
      minindex = i;
}
 
  • #5
Thank you for your reply.
I get what you explained. Do I need to include something like #include <fstream> to be able to use the array function?

Also, where would be the best place to put the code? Do I just need to add the code you explained to my previous code or do I need to modify something else in addition to that?

I wonder how array defines the distance from the closest point to point 0.
 
Last edited:
  • #6
Joon said:
Thank you for your reply.
I get what you explained. Do I need to include something like #include <fstream> to be able to use the array function?
Array is not a function, just an example of an array as you already use to store the coordinates.
You just need a declaration: double array[SIZE]; (you might want to use another name such as distance instead of array)
Also, where would be the best place to put the code? Do I just need to add the code you explained to my previous code or do I need to modify something else in addition to that?
Should work at any place after reading in the points.
I wonder how array defines the distance from the closest point to point 0.
array[] just stores the distances to point 0. It's not really necessary to do that because minval also stores the value of the minium distance, and minindex stores the number of the point with the minimum distance to point 0. You could get the coordinates of the closest point from (xcoordinates[minindex], ycoordinates[minindex], zcoordinates[minindex]) if you need them later.
 
  • #7
Joon said:
Thank you for your reply.
I get what you explained. Do I need to include something like #include <fstream> to be able to use the array function?

There's no "array" function. I wasn't showing you exact code. I was showing you the structure of the code, picking my own names. "array" was the name I chose for the array that's going to store distance values, but you should probably choose a more meaningful name like "distances" or "array_of_distances". That's a style question and style is YOUR style, though there is lots of stuff written about good style. Probably a name like "arrayOfDistances" would be preferred by many people. Note the mix of upper and lower case which is called "camelcase".

I was suggesting you define an array to store the distance of the i-th point from the 0-th point. Define it by using the syntax for defining an array. Give it an appropriate type based on what sort of values you are storing in it. Give it a name which is meaningful to you.

Joon said:
Also, where would be the best place to put the code? Do I just need to add the code you explained to my previous code or do I need to modify something else in addition to that?

It's your code. You need to figure out the sequence of steps, then put the code that does each step in the proper order.

I wonder how array defines the distance from the closest point to point 0.

The way I sketched (it's not a program, it's just an outline), "array" is an array that stores the distance of EVERY point from point 0. See the line that says you're going to put the distance of point from point[0] in array? It will have that distance because you will write the code that calculates that distance and stores it there.

The variable which I called "minval" stores the smallest value so far, because each time through the loop it checks if it is the smallest found so far and updates if not. Again, calling it "minval" was my choice for illustration purposes but preferred style these days would be to use complete words with camelcase in defining a meaningful name. But it's YOUR variable, which you give YOUR name.

In fact you don't even need a variable which does that. The variable which I called "minindex" contains the index of where the smallest value is to be found. That's all you need to keep track of. When you want the smallest value from the distances array (whatever it's called), you can just get the value at the location whose number is the minimum index variable (whatever it's called).

I don't want to write this code for you. This is presumably your course, you should be doing your own work. And if you don't know what variables are, as appears to be the case, you need to do some reviewing.
 
Last edited:
  • #8
Sorry I confused myself. Below is the code I made changes to, I have several questions.
Is it correct to define minval with the min algorithm? How do I define minindex before the for loop?
C:
// Program to read an input file

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;

int main() {

    const int MAXI = 1000;    double x, y, z, xcoordinates[MAXI], ycoordinates[MAXI], zcoordinates[MAXI], minval, minindex, distances[i];
    int i, count;

    ifstream inFile("input-week6-ad-q4-2.txt"); // ifstream function to read the file
    string line, c; // To read the characters    if (inFile.is_open())
    {
        getline(inFile, line); // To read the header of the input file then discard it
        getline(inFile, line);        i = 0;
        count = 0;
        while (inFile >> x >> y >> z) {

            xcoordinates[count] = x;
            ycoordinates[count] = y;
            zcoordinates[count] = z;
            count = count + 1;
        }

        for (i = 0; i < count; i++) {
            cout << xcoordinates[i] << " " << ycoordinates[i] << " " << zcoordinates[i] << "\n";
        }        minval = min(distances[i], distances[i+1]);
        minindex = ;
        for (i = 1; i < 1000; i++) {
            distances[i] = sqrt((xcoordinates[i] - xcoordinates[0])*(xcoordinates[i] - xcoordinates[0]) + (ycoordinates[i] - ycoordinates[0])*(ycoordinates[i] - ycoordinates[0]) + (zcoordinates[i] - zcoordinates[0])*(zcoordinates[i] - zcoordinates[0]);
            if (distances[i] < minval) {
                minval = distances[i];
                minindex = i;
          

            inFile.close();
        }
      else
        cout << "The file could not be opened." << "\n"; // To check for any error

    system("pause");
    return 0;
}
 
  • #9
Joon said:
Is it correct to define minval with the min algorithm?
It's not incorrect, but I wouldn't do it.
Since you're just comparing two things, it's nearly as easy to do this:
C:
if (distances[i] < distances[i + 1]) minval = distances[i];
else minval = distances[i + 1];
Note that because my if and else clauses were single statements, I didn't use and don't need a pair of braces around each of them. This is a shortcut that can backfire on you if you aren't careful, and wind up putting another statement in either place.
Or you could do this, if you know about the ternary operator.
C:
minval = distances[i] < distances[i + 1]) ? distances[i] : distances[i + 1];

Joon said:
How do I define minindex before the for loop?
Set it to a value that it won't ever have, like -1.
 
  • #10
I have modified the code. Could you check and inform me what's wrong? Thanks.

C:
// Program to read an input file

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;

int main() {

    const int MAXI = 1000;    double x, y, z, xcoordinates[MAXI], ycoordinates[MAXI], zcoordinates[MAXI], minval, minindex, distances[i];
    int i, count;

    ifstream inFile("input-week6-ad-q4-2.txt"); // ifstream function to read the file
    string line, c; // To read the characters    if (inFile.is_open())
    {
        getline(inFile, line); // To read the header of the input file then discard it
        getline(inFile, line);        i = 0;
        count = 0;
        while (inFile >> x >> y >> z) {

            xcoordinates[count] = x;
            ycoordinates[count] = y;
            zcoordinates[count] = z;
            count = count + 1;
        }

        for (i = 0; i < count; i++) {
            cout << xcoordinates[i] << " " << ycoordinates[i] << " " << zcoordinates[i] << "\n";
        }       
        for (i = 1; i < 1000; i++) {
            distances[i] = sqrt((xcoordinates[i] - xcoordinates[0])*(xcoordinates[i] - xcoordinates[0]) + (ycoordinates[i] - ycoordinates[0])*(ycoordinates[i] - ycoordinates[0]) + (zcoordinates[i] - zcoordinates[0])*(zcoordinates[i] - zcoordinates[0]);
            if (distances[i] < distances[i + 1]) minval = distances[i];
            else minval = distances[i + 1];
            minindex = -1;
           
            if (distances[i] < minval) {
                minval = distances[i];
                minindex = i;                inFile.close();
            }
            else
                cout << "The file could not be opened." << "\n"; // To check for any error

            system("pause");
            return 0;
        }
 
  • #11
Joon said:
Could you check and inform me what's wrong?
Is there something wrong with your code? What does it do or not do?

BTW, you have this comment near the top of your code:
C:
// ifstream function to read the file
ifstream is ***not** a function. The "function", or better, operator that does the work of inputting data is this one >>, the stream extraction operator. For example, in the condition expression in your while loop -- inFile >> x >> y >> z

ifstream is a class, and your variable inFile is an instance of this class. In this declaration --
C:
ifstream inFile("input-week6-ad-q4-2.txt");
you are defining an ifstream instance named inFile, and calling the ifstream constructor to associate the inFile stream with a file on a hard drive.

Try to work on getting a better understanding of the difference between types of data (such as int, double, class, array) and functions such as getline(), main(), and so on.
 
  • #12
I completely understand what you mean by class and function. I'll have a deeper look into it.
I have run the code, with the code below. But it does not show distances between point 1 and (2,3,4, so on...).
Also, the minimum distance value seems wrong. I think I'm doing something wrong, please let me know what's the problem.

EDIT: I found that for the distances between point 1 and others, cout must be placed earlier. However, the distances seem wrong.

C:
// Program to read an input file

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;

int main() {

    const int MAXI = 1000;    double x, y, z, xcoordinates[MAXI], ycoordinates[MAXI], zcoordinates[MAXI], minval, minindex, distances[1];
    int i, count;

    ifstream inFile("input-week6-ad-q4-2.txt");
    string line, c; // To read the characters    if (inFile.is_open())
    {
        getline(inFile, line); // To read the header of the input file then discard it
        i = 0;
        count = 0;
        while (inFile >> x >> y >> z) {

            xcoordinates[count] = x;
            ycoordinates[count] = y;
            zcoordinates[count] = z;
            count = count + 1;
        }

        for (i = 0; i < count; i++) {
            cout << xcoordinates[i] << " " << ycoordinates[i] << " " << zcoordinates[i] << "\n";
        }
        for (i = 1; i < 1000; i++) {
            distances[i] = sqrt((xcoordinates[i] - xcoordinates[0])*(xcoordinates[i] - xcoordinates[0]) + (ycoordinates[i] - ycoordinates[0])*(ycoordinates[i] - ycoordinates[0]) + (zcoordinates[i] - zcoordinates[0])*(zcoordinates[i] - zcoordinates[0]));
cout << "Distances between point 1 and other points are" << distances[i] << "\n";

            if (distances[i] < distances[i + 1]) minval = distances[i];
            else minval = distances[i + 1];
            minindex = -1;

        }        inFile.close();

       
        cout << "The closest point to point 1 is :(" << minindex << "), [Minimum distance= " << minval << "]";

    }
            else
                cout << "The file could not be opened." << "\n"; // To check for any error

            system("pause");
         
        }
 
Last edited:
  • #13
The latest code you posted has several problems.

First, you declare the variable distances as double distances[1] but later you set
Code:
distances[i] = ...
for ##1 <= i < 1000##. I'm guessing you wanted to declare double distances[MAXI] instead, so that you do not overrun the array bounds.

Second, in
C:
for (i = 1; i < 1000; i++) {
  distances[i] = sqrt((xcoordinates[i] - xcoordinates[0])*(xcoordinates[i] - xcoordinates[0]) + (ycoordinates[i] - ycoordinates[0])*(ycoordinates[i] - ycoordinates[0]) + (zcoordinates[i] - zcoordinates[0])*(zcoordinates[i] - zcoordinates[0]));
  ...
}
you read from
Code:
{x,y,z}coordinates[i]
for ##0 <= i < 1000## even though they have only been assigned for 0 <= i < count so you probably want to change the bound of that for-loop from i < 1000 to i < count.

Third, again in this same loop, you write
C:
if (distances[i] < distances[i + 1]) minval = distances[i];
else minval = distances[i + 1];
which reads from the uninitialized (not to mention out-of-bounds) location distances[i+1]. Instead, you should write
C:
if (distances[i] < minval) {
  minval = distances[i];
  minindex = i;
}
with no else block. This raises the question of how to initialize minval and minindex, since for i=1 you want to set both of them with no comparison. One alternative is to initialize minval as std::numeric_limits<double>::max(), and this is probably what I would recommend in this case.

Eyeballing the math it looks correct (although I would prefer the IMO more readable

C:
double delta_x = xcoordinates[i] - xcoordinates[0];
double delta_y = ycoordinates[i] - ycoordinates[0];
double delta_z = zcoordinates[i] - zcoordinates[0];
distances[i] = std::sqrt(delta_x * delta_x + delta_y * delta_y + delta_z * delta_z);

to your

C:
distances[i] = sqrt((xcoordinates[i] - xcoordinates[0])*(xcoordinates[i] - xcoordinates[0]) + (ycoordinates[i] - ycoordinates[0])*(ycoordinates[i] - ycoordinates[0]) + (zcoordinates[i] - zcoordinates[0])*(zcoordinates[i] - zcoordinates[0]));
). However, before spending too much more time trying to debug the maths (plural, this is programming after all ;) ), I would fix those uninitialized-read and out-of-bounds issues, since they could easily be the cause of the problem.

Also, on a side note: it is an unfortunate reality of consumer hardware and the low-level nature of the C and C++ programming languages that stack space is limited, and so for instance double large_array[1000000] (an array containing 8 megabytes of doubles) is very likely to crash on startup due to a stack overflow. Therefore, if you want to compute with large amounts of numbers, either learn to use dynamic memory allocation (such as using std::vector<double> or std::shared_ptr<double[]> or use a different language that automates such things - such as Haskell.
 
Last edited:
  • #14
Thanks a lot, my code works !
 
  • #15
Oh, and instead of initializing minval to std::numeric_limits<double>::max(), you can initialize it to std::numeric_limits<decltype(minval)>::max() for more stable code. If you change the type of minval to float, or to a higher-precision fractional type, then you won't have to also change the value it's initialized to.
 
  • Like
Likes Joon

1. What is C++?

C++ is a high-level programming language that is used to develop a wide range of software applications. It is known for its efficiency, speed, and ability to handle complex tasks.

2. How do I read data from a file in C++?

To read data from a file in C++, you can use the ifstream class and its associated functions. First, you need to open the file using the open() function, then you can use the getline() function to read each line of data and store it in a variable.

3. How do I calculate distances in C++?

To calculate distances in C++, you can use the sqrt() function from the <cmath> library. This function calculates the square root of a number, which can be used to find the distance between two points using the Pythagorean theorem.

4. How do I find the closest point in C++?

To find the closest point in C++, you can use a loop to iterate through all the points and calculate the distance between each point and the target point. Keep track of the smallest distance and the corresponding point, and update them if a closer point is found.

5. Can I use C++ to visualize the results of the calculations?

Yes, you can use C++ to create visualizations of the results by using libraries such as OpenGL or SDL. These libraries allow you to create graphics and animations in your C++ programs.

Similar threads

  • Engineering and Comp Sci Homework Help
Replies
1
Views
1K
  • Engineering and Comp Sci Homework Help
Replies
16
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
15
Views
2K
  • Precalculus Mathematics Homework Help
Replies
7
Views
881
  • MATLAB, Maple, Mathematica, LaTeX
Replies
1
Views
126
  • General Math
Replies
4
Views
2K
  • Linear and Abstract Algebra
Replies
17
Views
4K
Replies
2
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
6
Views
2K
Back
Top