Как игнорировать последнюю пустую строку при использовании istream_iterator
Допустим, у меня есть простой текстовый файл 2D точек, например:
10
0.000 0.010
0.000 0.260
0.000 0.510
0.000 0.760
0.000 1.010
0.000 1.260
0.000 1.510
0.000 1.760
0.000 2.010
0.000 2.260
// Blank line here
Я использую простую структуру для ввода-вывода:
template <typename T>
struct point
{
point (T x = 0, T y = 0) : x (x), y (y) {}
T x ;
T y ;
friend std::istream& operator>> (std::istream &is, point &p) {
is >> p.x >> p.y ;
return is ;
}
};
Мой оригинальный код был:
int main (void)
{
std::string strFile = "Points.txt" ;
std::ifstream file ;
file.exceptions (std::ios::failbit | std::ios::badbit) ;
std::vector <point <double> > vec ;
try {
file.open (strFile) ;
int nPoints = 0 ;
file >> nPoints ;
for (int n = 0; n < nPoints; ++n) {
point <double> p ;
file >> p ;
vec.push_back (p) ;
}
}
catch (std::ios_base::failure &e) {
std::cerr << e.what () << "\n" ;
return 1 ;
}
return 0 ;
}
Это прекрасно работает, но в духе отсутствия сырых циклов я бы хотел избавиться от цикла for.
Вот мой новый код:
int main (void)
{
std::string strFile = "Points.txt" ;
std::ifstream file ;
file.exceptions (std::ios::failbit | std::ios::badbit) ;
std::vector <point <double> > vec ;
try {
file.open (strFile) ;
int nPoints = 0 ;
file >> nPoints ;
std::copy (
std::istream_iterator <point <double> > (file),
std::istream_iterator <point <double> > (),
std::back_inserter (vec)
) ;
}
catch (std::ios_base::failure &e) {
std::cerr << e.what () << "\n" ;
return 1 ;
}
return 0 ;
}
Все копируется нормально, но, к сожалению, чтение последней пустой строки вызывает бит сбоя.
Единственные способы, которые я могу придумать, чтобы исправить это, довольно уродливы. Я мог бы:
- Поместите предложение "поймать-поймать" в
point::operator>>()
функция - Проверьте
vec.size()
в предложении catch, которое уже существует.
Есть ли элегантный способ игнорирования последней пустой строки?
1 ответ
Решение
+ Изменить
std::copy (
std::istream_iterator <point <double> > (file),
std::istream_iterator <point <double> > (),
std::back_inserter (vec)
) ;
в
std::copy_n (
std::istream_iterator <point <double> > (file),
nPoints,
std::back_inserter (vec)
) ;