• Support PF! Buy your school textbooks, materials and every day products Here!

C++ Reading a data file

  • #1
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

Answers and Replies

  • #2
RPinPA
Science Advisor
Homework Helper
564
317
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
85
2
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
RPinPA
Science Advisor
Homework Helper
564
317
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
85
2
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
1,929
228
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
RPinPA
Science Advisor
Homework Helper
564
317
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.

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
85
2
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
33,171
4,858
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];
How do I define minindex before the for loop?
Set it to a value that it won't ever have, like -1.
 
  • #10
85
2
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
33,171
4,858
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
85
2
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
85
2
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.
 

Related Threads for: C++ Reading a data file

Replies
0
Views
1K
  • Last Post
Replies
5
Views
6K
  • Last Post
Replies
8
Views
5K
  • Last Post
Replies
1
Views
3K
Replies
5
Views
38K
Replies
2
Views
2K
  • Last Post
Replies
2
Views
1K
Replies
4
Views
667
Top