我的数据文件如下所示:
x y z
0.068472 -0.024941 0.028884
.... .... ....
continued, there are more than 100 points.
我想在所有数据点中找到最接近点1的点(在
这种情况(0.068472,-0.024941,0.028884)。我的读取文件的代码在下面,我应该添加哪个函数以找到与点1最接近的点?我应该使用最小函数来找到点1和另一个点之间的最小距离吗?但是我不确定如何用代码编写。
// 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;
}
最佳答案
这些评论提供了正确的方向。如果要编写的最小距离查找器是C ++,则应从简单的2d点类开始,然后通过添加第3个坐标来派生一个类来处理该类中的3d点。如果您只是要使用单独的x, y, z
坐标和三个单独的double
数组-您最好使用C语言编写程序。
为2d点编写基类一点都不困难。为了从中派生3d类,您需要注意的唯一事情是将坐标成员声明为protected:
,以便2d点类的所有受保护成员都可以作为3d类(类(类)中的受保护成员)使用。成员默认情况下是私有的,除非有朋友,否则永远无法访问基础的私有成员)
那么最小的二维点基类是什么样的呢?好吧,您将需要x, y
坐标,并且需要一个默认的构造函数来将x
和y
设置为0.0 when the class is constructed, a constructor to take
x and
y values, and then a couple of accessor functions to get the
x and
y`值,以用于距离函数。
最小的二维点类可以是:
/* 2D Cartesian Coordinate Point */
class point2_t {
protected: /* allows derived class access to x, y when inherited */
double x, y; /* private members would not be accessible */
public:
point2_t () { x = 0.0, y = 0.0; } /* constructors */
point2_t (const double a, const double b) : x{a}, y{b} { }
const double& getx () const { return x; } /* access functions */
const double& gety () const { return y; }
double dist (const point2_t& p) { /* distance function */
return sqrt ((x-p.getx()) * (x-p.getx()) +
(y-p.gety()) * (y-p.gety()));
}
};
这将使您可以使用值初始化2d点,获取当前设置的值,然后计算与其他2d点的距离。尽管这很好用,但仍然需要从文件中读取
x
和y
值,然后通过将坐标传递给构造函数来创建点。 (您还可以编写一个setx(double x)
和相应的sety()
以允许您更改x, y
值)能够仅
cin >> point;
并自动设置x, y
值,并能够cout << point;
输出坐标,这将是非常不错的。您可以通过重载<<
和>>
运算符来实现。这使得读取和输出坐标数据非常方便。为此,您可以将以下内容添加为成员函数: /* overload output and input operators */
friend std::ostream& operator << (std::ostream& os, const point2_t& p) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
friend std::istream& operator >> (std::istream& is, point2_t& p) {
is >> p.x >> p.y;
return is;
}
一旦编写了2d点类,您所要做的就是从中派生3d点类,并添加一个
z
坐标和相应的函数来处理所有三个坐标而不是两个坐标。从包括该基类的受保护成员的基类派生一个类的基本形式是:class derived : public base {
/* additions */
};
从2d点类到3d点类(包括重载的
<<
和>>
运算符)的简单派生可能是:/* 3D Cartesian Coordinate Point derived from 2D point class */
class point_t: public point2_t {
protected:
double z; /* add z coordinate */
public:
point_t () { point2_t (0.0, 0.0); z = 0.0; }; /* default construct */
/* construct with initializer list */
point_t (const double a, const double b, const double c) :
point2_t (a, b), z{c} {}
const double& getz () const { return z; } /* add getz accessor */
double dist (const point_t& p) { /* extend distance */
return sqrt ((x-p.getx()) * (x-p.getx()) +
(y-p.gety()) * (y-p.gety()) +
(z-p.getz()) * (z-p.getz()));
}
/* extend operators */
friend std::ostream& operator << (std::ostream& os, const point_t& p) {
os << "(" << p.x << ", " << p.y << ", " << p.z << ")";
return os;
}
friend std::istream& operator >> (std::istream& is, point_t& p) {
is >> p.x >> p.y >> p.z;
return is;
}
};
现在您有了一个3d点类,可以计算点之间的距离。剩下的工作就是为第一个点创建一个类的实例,并为您的文件创建另一个临时实例以从文件中读取其他点,从而使您可以计算两者之间的距离。 (如果要保存最近点的坐标,则第三个实例很方便)
数据文件的唯一警告是您需要丢弃包含
x y z
标题的第一行。虽然您可以使用string
将行读入getline
并忽略它,但C ++还提供了流函数.ignore()
,它允许您忽略最多可读字符数,直到达到分隔符为止(换行)。只需包含limits
标头,即可使用: std::ifstream f (argv[1]); /* open file stream */
...
/* discard 1st line in file */
f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
(两种方法都可行)
无需将文件中的所有点都读取到容器中以供以后处理,而只需查找第一个点与其余点之间的最小距离即可。您需要做的就是存储第一个点(下面的
p1
),然后计算它与其余点之间的距离,并保存为每个后续比较找到的最小距离(下面的distmin
)。 (如果愿意,还可以保存最近点的坐标)将其组合成一个简短的
main()
可能看起来像:int main (int argc, char **argv) {
if (argc < 2) { /* validate argument available for filename */
std::cerr << "error: insufficient input.\n";
return 1;
}
std::ifstream f (argv[1]); /* open file stream */
point_t p1, min, tmp; /* 1st, mininum & temporary points */
/* initialize minimum distance to maximum allowable */
double distmin = std::numeric_limits<double>::max();
/* discard 1st line in file */
f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (!(f >> p1)) { /* read 1st point */
std::cerr << "error: failed read of p1\n";
return 1;
}
while (f >> tmp) { /* read remaining points */
double dist = tmp.dist (p1); /* get distance from p1 */
if (dist < distmin) { /* check less than distmin? */
distmin = dist; /* set new distmin */
min = tmp; /* set new closest point */
}
}
/* output results */
std::cout << "\nclosest point to " << p1 << "\n\n" << min <<
"\n\ndistance: " << distmin << '\n';
}
完整的示例如下:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cmath>
#include <limits>
/* 2D Cartesian Coordinate Point */
class point2_t {
protected: /* allows derived class access to x, y when inherited */
double x, y; /* private members would not be accessible */
public:
point2_t () { x = 0.0, y = 0.0; } /* constructors */
point2_t (const double a, const double b) : x{a}, y{b} { }
const double& getx () const { return x; } /* access functions */
const double& gety () const { return y; }
double dist (const point2_t& p) { /* distance function */
return sqrt ((x-p.getx()) * (x-p.getx()) +
(y-p.gety()) * (y-p.gety()));
}
/* overload output and input operators */
friend std::ostream& operator << (std::ostream& os, const point2_t& p) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
friend std::istream& operator >> (std::istream& is, point2_t& p) {
is >> p.x >> p.y;
return is;
}
};
/* 3D Cartesian Coordinate Point derived from 2D point class */
class point_t: public point2_t {
protected:
double z; /* add z coordinate */
public:
point_t () { point2_t (0.0, 0.0); z = 0.0; }; /* default construct */
/* construct with initializer list */
point_t (const double a, const double b, const double c) :
point2_t (a, b), z{c} {}
const double& getz () const { return z; } /* add getz accessor */
double dist (const point_t& p) { /* extend distance */
return sqrt ((x-p.getx()) * (x-p.getx()) +
(y-p.gety()) * (y-p.gety()) +
(z-p.getz()) * (z-p.getz()));
}
/* extend operators */
friend std::ostream& operator << (std::ostream& os, const point_t& p) {
os << "(" << p.x << ", " << p.y << ", " << p.z << ")";
return os;
}
friend std::istream& operator >> (std::istream& is, point_t& p) {
is >> p.x >> p.y >> p.z;
return is;
}
};
int main (int argc, char **argv) {
if (argc < 2) { /* validate argument available for filename */
std::cerr << "error: insufficient input.\n";
return 1;
}
std::ifstream f (argv[1]); /* open file stream */
point_t p1, min, tmp; /* 1st, mininum & temporary points */
/* initialize minimum distance to maximum allowable */
double distmin = std::numeric_limits<double>::max();
/* discard 1st line in file */
f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (!(f >> p1)) { /* read 1st point */
std::cerr << "error: failed read of p1\n";
return 1;
}
while (f >> tmp) { /* read remaining points */
double dist = tmp.dist (p1); /* get distance from p1 */
if (dist < distmin) { /* check less than distmin? */
distmin = dist; /* set new distmin */
min = tmp; /* set new closest point */
}
}
/* output results */
std::cout << "\nclosest point to " << p1 << "\n\n" << min <<
"\n\ndistance: " << distmin << '\n';
}
输入文件示例
在与您的值相同的范围内生成一些其他随机点将为您提供一个总点数为10的数据文件,用于验证程序,例如
$ cat dat/3dpoints-10.txt
x y z
0.068472 -0.024941 0.028884
-0.023238 0.028574 -0.021372
0.015325 -0.086100 0.011980
-0.028137 -0.025350 0.021614
-0.013860 0.015710 -0.022659
0.026026 -0.093600 0.019175
0.010445 -0.098790 0.023332
-0.021594 0.017428 -0.025986
0.021800 -0.027678 0.017078
-0.016704 0.017951 0.011059
使用/输出示例
然后,运行程序将找到最接近您的第一个点(
p1
)的点,并提供以下答案:$ ./bin/point_distmin dat/3dpoints-10.txt
closest point to (0.068472, -0.024941, 0.028884)
(0.0218, -0.027678, 0.017078)
distance: 0.0482198
仔细检查一下,如果您有任何问题,请告诉我。 cpprefernce.com是最好的参考文献之一(除了标准本身)。请将该书签放在手边,并花一些时间来了解该语言和网站。
关于c++ - 如何在数据文件上找到最接近第一个点的点? C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55192641/