Я покажу вам, что я думаю, что это правильный C ++ способ сделать это. Сначала определите класс для представления вашей первой строки и для выполнения ее ввода-вывода:
struct FirstLine
{
double x, y, z;
friend std::istream & operator>>(std::istream & is, FirstLine & data)
{
std::string line, ignore;
std::getline(is, line);
std::istringstream iss(line);
iss >> ignore >> data.x >> data.y >> data.z;
assert(ignore == "P" && iss);
return is;
}
friend std::ostream & operator<<(std::ostream & os, FirstLine const & data)
{
return os << "P " << data.x << " " << data.y << " " << data.z;
}
};
Я добавил некоторую базовую проверку ошибок с помощью assert, вы, вероятно, захотите что-то более надежное в вашей финальной программе.
Теперь класс для средних строк:
struct MiddleLine
{
double x, y;
friend std::istream & operator>>(std::istream & is, MiddleLine & data)
{
std::string line;
std::getline(is, line);
if(line == "T")
is.clear(std::ios::failbit);
else
{
int n = sscanf(line.c_str(), "%lf %lf", &data.x, &data.y);
assert(n == 2);
}
return is;
}
friend std::ostream & operator<<(std::ostream & os, MiddleLine const & data)
{
return os << data.x << " " << data.y;
}
};
Когда мы достигнем конца секции, где находятся средние линии, мы должны встретить букву "Т". В этом случае мы поднимаем бит сбоя потока, который сообщает клиенту, что больше нет средних строк для чтения.
Наконец, класс для последних строк:
struct LastLine
{
std::string identifier; // r, s or t
std::vector<double> values;
friend std::istream & operator>>(std::istream & is, LastLine & data)
{
std::string line;
std::getline(is, line);
std::istringstream iss(line);
iss >> data.identifier;
assert(data.identifier == "r" || data.identifier == "s"
|| data.identifier == "t");
std::copy(std::istream_iterator<double>(iss),
std::istream_iterator<double>(), std::back_inserter(data.values));
return is;
}
friend std::ostream & operator<<(std::ostream & os, LastLine const & data)
{
os << data.identifier << " ";
std::copy(data.values.begin(), data.values.end(),
std::ostream_iterator<double>(os, " "));
return os;
}
};
Последние строки более сложные, потому что мы не знаем, сколько значений в каждом, поэтому мы просто читаем столько, сколько можем.
Это была сложная часть. Теперь наша основная функция будет просто читать одну первую строку, затем неизвестное число средних строк и, наконец, неизвестное количество последних строк:
int main()
{
std::string const data = "P 0.5 0.6 0.3\n
"30 300\n"
"80 150\n"
"160 400\n"
"200 150\n"
"250 300\n"
"T\n"
"r 45 0 0\n"
"s 0.5 1.5 0 0\n"
"t 200 –150";
std::istringstream iss(data);
FirstLine first_line;
iss >> first_line;
std::vector<MiddleLine> middle_lines;
std::copy(std::istream_iterator<MiddleLine>(iss),
std::istream_iterator<MiddleLine>(),
std::back_inserter(middle_lines));
iss.clear();
std::vector<LastLine> last_lines;
std::copy(std::istream_iterator<LastLine>(iss),
std::istream_iterator<LastLine>(),
std::back_inserter(last_lines));
assert(iss.eof());
std::cout << first_line << "\n";
std::copy(middle_lines.begin(), middle_lines.end(),
std::ostream_iterator<MiddleLine>(std::cout, "\n"));
std::copy(last_lines.begin(), last_lines.end(),
std::ostream_iterator<LastLine>(std::cout, "\n"));
return 0;
}
Это вывод, который вы получите ::
P 0.5 0.6 0.3
30 300
80 150
160 400
200 150
250 300
r 45 0 0
s 45 0 0 0.5 1.5 0 0
t 45 0 0 0.5 1.5 0 0 200
Я использовал строку в качестве источника моих данных, но вы, вероятно, захотите прочитать из файла.
И это все, вы можете видеть, что я не написал ни одного цикла.
Вот код в кодовой панели.