有条件地逐行读取文件
conditional line-by-line reading from file
现在我有那个代码:
if (minimizator_weighted) {
while (dataFile >> t >> e >> sigma) { // read data file value by value
/* some code */
}
}
else {
while (dataFile >> t >> e) { // all the same but will not read standard deviation
/* almost the same code */
}
}
如您所见,if
和 else
流之间的唯一区别是 while
循环的条件。我想知道是否有可能优化该代码段并重新使用代码?如果我能写一些这样的东西就好了:
while ((minimizator_weighted) ? (dataFile >> t >> e >> sigma) : (dataFile >> t >> e)) { ... }
但我不确定这个技巧是否正确...你能给我一些优化建议吗?谢谢!
编辑
这是完整的代码片段
if (minimizator_weighted) {
while (dataFile >> t >> e >> sigma) { // read data file value by value
data_set::pt point;
point.t = t;
point.e = e;
point.c_vis = 0.0;
point.c_invis = 0.0;
if (std::abs(sigma) <= GSL_SQRT_DBL_MIN) // check for division-by-zero error
sigma = 1.0;
point.sigma = sigma;
set.curve.push_back(point); // store point
data_numPoints++; // collect some stats
set.curveAvg += e;
}
}
else {
while (dataFile >> t >> e) { // all the same but will not read standard deviation
data_set::pt point;
point.t = t;
point.e = e;
point.c_vis = 0.0;
point.c_invis = 0.0;
set.curve.push_back(point);
data_numPoints++;
set.curveAvg += e;
}
}
添加一个间接级别
bool read_data_line1(istream& dataFile, T& t, E& e, Sig& sigma)
{ return dataFile >> t >> e >> sigma; }
bool read_data_line2(istream& dataFile, T& t, E& e, Sig&)
{ return dataFile >> t >> e; }
auto read_data_line_func = minimizator_weighted ? read_data_line1 : read_data_line2;
while(read_data_line_func(dataFile, t, e, sigma))
{
data_set::pt point;
point.t = t;
point.e = e;
point.c_vis = 0.0;
point.c_invis = 0.0;
if (minimizator_weighted)
{
if (std::abs(sigma) <= GSL_SQRT_DBL_MIN) // check for division-by-zero error
sigma = 1.0;
point.sigma = sigma;
}
set.curve.push_back(point); // store point
data_numPoints++; // collect some stats
set.curveAvg += e;
}
我想我会这样表达:
data_set::pt collect_point(std::istream& is, bool minimizator_weighted)
{
data_set::pt point;
is >> point.t >> point.e;
point.c_vis = 0.0;
point.c_invis = 0.0;
if (minimizator_weighted) {
is >> point.sigma;
point.sigma = std::max(point.sigma, GSL_SQRT_DBL_MIN);
}
return point;
}
void test()
{
int data_numPoints = 0;
data_set set;
while (dataFile)
{
auto point = collect_point(dataFile, minimizator_weighted);
auto e = point.e;
set.curve.push_back(std::move(point)); // store point
data_numPoints++; // collect some stats
set.curveAvg += e;
}
}
您的架构向我们展示了 3 个错误:
sigma
是一些对象未使用的变量
- 对象行为由外部变量决定(
minimizator_weighted
)
每次访问这些对象之一时都必须使用 minimizator_weighted
这些是基本的设计缺陷,不仅在这里而且在整个程序中都会让你付出代价。不过,修复将需要重新架构。让我向您展示如何做到这一点,您可以决定是继续解决问题还是修复架构。
首先你需要 2 基本类型,第 1st 将与你的 data_set::pt
相匹配已经在没有 sigma
的情况下定义,那么我们将使用 data_set::pt_weighted
扩展它以添加 sigma
:
struct pt {
double t;
double e;
double c_vis;
double c_invis;
};
struct pt_weighted : pt {
double sigma;
};
现在我们将编写提取运算符,再次从 data_set::pt
的提取运算符开始并扩展 data_set::pt_weighted
:
istream& operator>> (istream& lhs, data_set::pt& rhs) {
rhs.c_vis = 0.0;
rhs.c_invis = 0.0;
return lhs >> rhs.t >> rhs.e;
}
istream& operator>> (istream& lhs, data_set::pt_weighted& rhs) {
lhs >> static_cast<data_set::pt&>(rhs) >> rhs.sigma;
// check for division-by-zero error
if(std::abs(rhs.sigma) <= GSL_SQRT_DBL_MIN) rhs.sigma = 1.0;
return lhs;
}
从这里开始,您需要开始使用模板。首先,您需要将 set.curve
模板化为 data_set::pt
或 data_set::pt_weighted
的容器,然后您的功能需要更改为:
template <typename T>
void foo() {
for(T point; dataFile >> point;) {
set.curve.push_back(point); // store point
data_numPoints++; // collect some stats
set.curveAvg += point.e;
}
}
如果在运行时之前无法建立 minimizator_weighted
,则需要调用 foo
,例如:
minimizator_weighted ? foo<data_set::pt_weighted>() : foo<data_set::pt>();
现在我有那个代码:
if (minimizator_weighted) {
while (dataFile >> t >> e >> sigma) { // read data file value by value
/* some code */
}
}
else {
while (dataFile >> t >> e) { // all the same but will not read standard deviation
/* almost the same code */
}
}
如您所见,if
和 else
流之间的唯一区别是 while
循环的条件。我想知道是否有可能优化该代码段并重新使用代码?如果我能写一些这样的东西就好了:
while ((minimizator_weighted) ? (dataFile >> t >> e >> sigma) : (dataFile >> t >> e)) { ... }
但我不确定这个技巧是否正确...你能给我一些优化建议吗?谢谢!
编辑 这是完整的代码片段
if (minimizator_weighted) {
while (dataFile >> t >> e >> sigma) { // read data file value by value
data_set::pt point;
point.t = t;
point.e = e;
point.c_vis = 0.0;
point.c_invis = 0.0;
if (std::abs(sigma) <= GSL_SQRT_DBL_MIN) // check for division-by-zero error
sigma = 1.0;
point.sigma = sigma;
set.curve.push_back(point); // store point
data_numPoints++; // collect some stats
set.curveAvg += e;
}
}
else {
while (dataFile >> t >> e) { // all the same but will not read standard deviation
data_set::pt point;
point.t = t;
point.e = e;
point.c_vis = 0.0;
point.c_invis = 0.0;
set.curve.push_back(point);
data_numPoints++;
set.curveAvg += e;
}
}
添加一个间接级别
bool read_data_line1(istream& dataFile, T& t, E& e, Sig& sigma)
{ return dataFile >> t >> e >> sigma; }
bool read_data_line2(istream& dataFile, T& t, E& e, Sig&)
{ return dataFile >> t >> e; }
auto read_data_line_func = minimizator_weighted ? read_data_line1 : read_data_line2;
while(read_data_line_func(dataFile, t, e, sigma))
{
data_set::pt point;
point.t = t;
point.e = e;
point.c_vis = 0.0;
point.c_invis = 0.0;
if (minimizator_weighted)
{
if (std::abs(sigma) <= GSL_SQRT_DBL_MIN) // check for division-by-zero error
sigma = 1.0;
point.sigma = sigma;
}
set.curve.push_back(point); // store point
data_numPoints++; // collect some stats
set.curveAvg += e;
}
我想我会这样表达:
data_set::pt collect_point(std::istream& is, bool minimizator_weighted)
{
data_set::pt point;
is >> point.t >> point.e;
point.c_vis = 0.0;
point.c_invis = 0.0;
if (minimizator_weighted) {
is >> point.sigma;
point.sigma = std::max(point.sigma, GSL_SQRT_DBL_MIN);
}
return point;
}
void test()
{
int data_numPoints = 0;
data_set set;
while (dataFile)
{
auto point = collect_point(dataFile, minimizator_weighted);
auto e = point.e;
set.curve.push_back(std::move(point)); // store point
data_numPoints++; // collect some stats
set.curveAvg += e;
}
}
您的架构向我们展示了 3 个错误:
sigma
是一些对象未使用的变量- 对象行为由外部变量决定(
minimizator_weighted
)
每次访问这些对象之一时都必须使用 minimizator_weighted
这些是基本的设计缺陷,不仅在这里而且在整个程序中都会让你付出代价。不过,修复将需要重新架构。让我向您展示如何做到这一点,您可以决定是继续解决问题还是修复架构。
首先你需要 2 基本类型,第 1st 将与你的 data_set::pt
相匹配已经在没有 sigma
的情况下定义,那么我们将使用 data_set::pt_weighted
扩展它以添加 sigma
:
struct pt {
double t;
double e;
double c_vis;
double c_invis;
};
struct pt_weighted : pt {
double sigma;
};
现在我们将编写提取运算符,再次从 data_set::pt
的提取运算符开始并扩展 data_set::pt_weighted
:
istream& operator>> (istream& lhs, data_set::pt& rhs) {
rhs.c_vis = 0.0;
rhs.c_invis = 0.0;
return lhs >> rhs.t >> rhs.e;
}
istream& operator>> (istream& lhs, data_set::pt_weighted& rhs) {
lhs >> static_cast<data_set::pt&>(rhs) >> rhs.sigma;
// check for division-by-zero error
if(std::abs(rhs.sigma) <= GSL_SQRT_DBL_MIN) rhs.sigma = 1.0;
return lhs;
}
从这里开始,您需要开始使用模板。首先,您需要将 set.curve
模板化为 data_set::pt
或 data_set::pt_weighted
的容器,然后您的功能需要更改为:
template <typename T>
void foo() {
for(T point; dataFile >> point;) {
set.curve.push_back(point); // store point
data_numPoints++; // collect some stats
set.curveAvg += point.e;
}
}
如果在运行时之前无法建立 minimizator_weighted
,则需要调用 foo
,例如:
minimizator_weighted ? foo<data_set::pt_weighted>() : foo<data_set::pt>();