Я пытаюсь проанализировать gcode и хочу извлечь из каждой строки только координаты x и y G1.
ПРИМЕР GКОДА
G1 X123.456 Y125.425 Z34.321
Я попробовал базовую функцию getline()
, но она печатает всю строку, не понимаю, как добавить фильтры к getline()
, чтобы просто извлекать только числовые значения x и y и только для строк с G1 в начале.
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <fstream>
using std::cout; using std::cerr;
using std::endl; using std::string;
using std::ifstream; using std::vector;
int main()
{
string filename("test1.gcode");
vector<string> lines;
string line;
ifstream input_file(filename);
if (!input_file.is_open()) {
cerr << "Could not open the file - '"
<< filename << "'" << endl;
return EXIT_FAILURE;
}
while (getline(input_file, line)){
lines.push_back(line);
}
for (const auto &i : lines)
cout << i << endl;
input_file.close();
return EXIT_SUCCESS;
}
Чтобы отфильтровать файл, нужно прочитать все, а затем игнорировать те биты, которые вам не нужны.
Вы не можете добавлять фильтры к getline()
; его задача — прочитать строку. Полная остановка. После прочтения строки вы можете делать с результатом все, что вам нужно. Нравится поиск 'X'
, а затем 'Y'
.
@PeteBecker, можете ли вы показать, как после этого искать X и Y?
@Mohit -- начните с чтения документации для std::string.
Обычный способ обработки структурированных данных... с помощью структуры.
struct line_item {
int g;
double x;
double y;
double z;
};
std::istream& operator>>(std::istream& in, line_item& item) {
line_item temp;
item = {};
in >> 'G' >> temp.g >> 'X' >> temp.x >> 'Y' >> temp.y >> 'Z' >> temp.z;
if (in)
item = temp;
return in;
}
std::ostream& operator<<(std::ostream& out, const line_item& item) {
return out << 'G' << item.g << " X" << item.x << " Y" << item.y << " Z" << item.z;
}
Обычно это невозможно istream >> 'G'
, поэтому у меня есть помощник для этого.
//helper function for "reading in" character literals
template<class e, class t>
std::basic_istream<e,t>& operator>>(std::basic_istream<e,t>& in, const e& char_literal) {
e buffer; //get buffer
in >> buffer; //read data
if (buffer != char_literal) //if it failed
in.setstate(in.rdstate() | std::ios::failbit); //set the state
return in;
}
http://coliru.stacked-crooked.com/a/6af1f3c881cc9e6e
Затем вы читаете элементы, используя обычный istream>>line_item
, и оттуда у вас есть структурированные данные, с которыми вы можете делать все, что хотите, например, создавать вторичную структуру, в которой хранятся только те элементы, которые вам нужны.
Вы не можете добавлять фильтры к getline()
. Он всегда будет возвращать полную следующую строку ввода.
Что вы можете сделать, так это проанализировать эту строку самостоятельно и извлечь нужные значения. Это можно сделать несколькими способами. Один из них продемонстрирован ниже.
Я использовал std::string::find, чтобы получить смещение для символа «X»/«Y», обозначающего координаты x/y.
Затем я использовал std::atof, чтобы преобразовать соответствующую часть строки в значение double
.
Я также использовал std::string::find
, чтобы проверить, начинается ли строка с необходимого префикса для этой команды.
#include <string>
#include <iostream>
#include <cstdlib>
int main()
{
std::string line = "G1 X123.456 Y125.425 Z34.321";
if (line.find("G1") == 0)
{
size_t xpos = line.find('X');
if (xpos == std::string::npos) { /* handle error */ }
double x = std::atof(line.data() + xpos + 1); // skip over the 'X'
size_t ypos = line.find('Y');
if (ypos == std::string::npos) { /* handle error */ }
double y = std::atof(line.data() + ypos + 1); // skip over the 'Y'
std::cout << "X: " << x << ", Y: " << y << std::endl;
}
}
Выход:
X: 123.456, Y: 125.425
Второстепенный момент: вам не нужно звонить
input_file.close();
; это сделает деструктор.