如何给c++ getline()函数添加过滤器?

l2osamch  于 2023-02-17  发布在  其他
关注(0)|答案(2)|浏览(136)

我正在尝试解析一个gcode,并且只想从每行中提取G1的x和y坐标
GCODE示例
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;
}
tez616oj

tez616oj1#

不能向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
jdgnovmf

jdgnovmf2#

处理结构化数据的常用方法是...使用struct。

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读入这些项,这样就得到了结构化数据,可以对这些数据做任何想做的事情,比如创建一个只存储您关心的项的辅助结构体。

相关问题