Extracting XY coordinates from Gcode using c++ regex parser - c++

I am trying to parse through a gcode file and need to extract the XY coordinates from the uploaded gcode.
I tried to parse but after running my code only the X-coordinate is printing not XY coordinates.
Also, how can I add a stop in the parser when it encounters a G92 in the line.
I want it to parse when line has G1 and stop when it encounters a G92.
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
using namespace std;
int main()
{
ifstream gcode ("circuit.gcode");
string line;
regex coord_regex("[XY].?\\d+.\\d+");
smatch coord_match;
while (getline(gcode, line))
{
if (regex_search(line, coord_match, coord_regex))
{
cout << coord_match[0]<< " - "<< coord_match[1]<< endl;
}
}
return 0;
}
Image
Gcode input
Current Output

So, I figured it out instead of searching for Y in the line I took X as a start and parsed the whole string altogether.
This is the final code
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
using namespace std;
int main()
{
ifstream gcode (test1.gcode");
string line;
regex coord_regex("[X].?\\d+.\\d+.\\s.\\w+.\\d+\\d+");
smatch coord_match;
while (getline(gcode, line))
{
if (regex_search(line, coord_match, coord_regex))
{
if (line.find("G1") != std::string::npos)
{
cout << coord_match[0]<< endl;
}
else if (line.find("G92") != std::string::npos){
break;
}
}
}
return 0;
}

Related

How to accept an unknown number of lines in c++, each line has two strings

How do I accept an unknown number of lines in c++? Each line has two strings in it separated by a space. I tried the solutions mentioned in This cplusplus forum, but none of the solutions worked for me. One of the solutions works only when Enter is pressed at the end of each line. I am not sure if the \n char will be given at the end of my input lines. What are my options?
My current attempt requires me to press Ctrl+Z to end the lines.
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
int main(){
string line;
while(cin>>line and cin.eof()==false){
cout<<line<<'\n';
}
return 0;
}
I would like to take an unknown number of strings as shown below:
cool toolbox
aaa bb
aabaa babbaab
Please don't flag this as a duplicate, I really tried all I could find! I tried the following solution on the above given link by m4ster r0shi (2201), but it did not work for me.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> words;
string word;
string line;
// get the whole line ...
getline(cin, line);
// ... then use it to create
// a istringstream object ...
istringstream buffer(line);
// ... and then use that istringstream
// object the way you would use cin
while (buffer >> word) words.push_back(word);
cout << "\nyour words are:\n\n";
for (unsigned i = 0; i < words.size(); ++i)
cout << words[i] << endl;
}
And this other solution also did not work: other soln, and I tried this SO post too: Answers to similar ques. This one worked for my example, but when I pass only one line of input, it freezes.
// doesn't work for single line input
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
int main(){
string line ="-1";
vector<string>data;
while(1){
cin>>line;
if(line.compare("-1")==0) break;
data.push_back(line);
line = "-1";
}
for(int i =0;i<data.size();i+=2){
cout<<data[i]<<' '<<data[i+1]<<'\n';
}
return 0;
}
If each line has two words separated by whitespace, then perhaps you should have a Line struct which contains two std::strings and overloads the >> operator for std::istream.
Then you can just copy from std::cin into the vector.
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
struct Line {
std::string first;
std::string second;
};
std::istream& operator>>(std::istream& i, Line& line) {
return i >> line.first >> line.second;
}
int main() {
std::vector<Line> lines;
std::copy(
std::istream_iterator<Line>(std::cin),
std::istream_iterator<Line>(),
std::back_inserter(lines)
);
for (auto &[f, s] : lines) {
std::cout << f << ", " << s << std::endl;
}
return 0;
}
A test run:
% ./a.out
jkdgh kfk
dfgk 56
jkdgh, kfk
dfgk, 56

How to extract a particular line from an external txt file using C++ and then output the line as a string?

This code only works for printing the first line. What should I do to print only the second or third line?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(){
string str;
string lineFromFile;
ifstream myfile("./file.txt");
while(getline(myfile,lineFromFile)){
str = lineFromFile;
cout << str << endl;
break;}
}
You can count the lines and equate your expected line number with the counter to output your line as in the below example.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(){
int count = 1;
int line_count;
string str;
string lineFromFile;
ifstream myfile("./file.txt");
std::cin >> line_count;
while(getline(myfile,lineFromFile)){
if(line_count == count)
{
str = lineFromFile;
std::cout << str << std::endl;
break;
}
count++;
}
}

reading inputs from file up to specific character cpp

Im tryin to read input.txt include string (move_back; turn_around[radius];).
I should allocate string command and attribute like;
up to ";" is command // move_back; is a command
between "[" and "]" is attribute // [radius] is and attribute
ı write these two program for this but ı need to combine in one program. And also ı dont know how can ı read between "[" "]" ı think ı shoul start reading at "[", finish reading at sight "]" char. ı dont know how to write this code and combine all these.
input.txt
move_back;
turn_around[radius];
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
// reading input from file line by line
void read() {
ifstream file;
file.open("input.txt");
string line;
while (getline(file, line)) {
cout << line << endl;
}
file.close();
}
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
int main()
{
// to find commands reading up to ";"
string s = "move_back; turn_around [radius];move_back [time];";
string delimiter = ";";
vector<string> commands;
int pos = -1;
while (s.find(delimiter) != -1) {
pos = s.find(delimiter);
commands.push_back(s.substr(0, pos));
s = s.substr(pos + delimiter.length());
}
for (int i = 0; i < commands.size(); i++) {
if (isspace(commands[i].at(0)))
commands[i] = commands[i].substr(1);
}
}

How to parse table of numbers in C++

I need to parse a table of numbers formatted as ascii text. There are 36 space delimited signed integers per line of text and about 3000 lines in the file. The input file is generated by me in Matlab so I could modify the format. On the other hand, I also want to be able to parse the same file in VHDL and so ascii text is about the only format possible.
So far, I have a little program like this that can loop through all the lines of the input file. I just haven't found a way to get individual numbers out of the line. I am not a C++ purest. I would consider fscanf() but 36 numbers is a bit much for that. Please suggest practical ways to get numbers out of a text file.
int main()
{
string line;
ifstream myfile("CorrOut.dat");
if (!myfile.is_open())
cout << "Unable to open file";
else{
while (getline(myfile, line))
{
cout << line << '\n';
}
myfile.close();
}
return 0;
}
Use std::istringstream. Here is an example:
#include <sstream>
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
string line;
istringstream strm;
int num;
ifstream ifs("YourData");
while (getline(ifs, line))
{
istringstream strm(line);
while ( strm >> num )
cout << num << " ";
cout << "\n";
}
}
Live Example
If you want to create a table, use a std::vector or other suitable container:
#include <sstream>
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
string line;
// our 2 dimensional table
vector<vector<int>> table;
istringstream strm;
int num;
ifstream ifs("YourData");
while (getline(ifs, line))
{
vector<int> vInt;
istringstream strm(line);
while ( strm >> num )
vInt.push_back(num);
table.push_back(vInt);
}
}
The table vector gets populated, row by row. Note we created an intermediate vector to store each row, and then that row gets added to the table.
Live Example
You can use a few different approaches, the one offered above is probable the quickest of them, however in case you have different delimitation characters you may consider one of the following solutions:
The first solution, read strings line by line. After that it use the find function in order to find the first position o the specific delimiter. It then removes the number read and continues till the delimiter is not found anymore.
You can customize the delimiter by modifying the delimiter variable value.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string line;
ifstream myfile("CorrOut.dat");
string delimiter = " ";
size_t pos = 0;
string token;
vector<vector<int>> data;
if (!myfile.is_open())
cout << "Unable to open file";
else {
while (getline(myfile, line))
{
vector<int> temp;
pos = 0;
while ((pos = line.find(delimiter)) != std::string::npos) {
token = line.substr(0, pos);
std::cout << token << std::endl;
line.erase(0, pos + delimiter.length());
temp.push_back(atoi(token.c_str()));
}
data.push_back(temp);
}
myfile.close();
}
return 0;
}
The second solution make use of regex and it doesn't care about the delimiter use, it will search and match any integers found in the string.
#include <iostream>
#include <string>
#include <regex> // The new library introduced in C++ 11
#include <fstream>
using namespace std;
int main()
{
string line;
ifstream myfile("CorrOut.dat");
std::smatch m;
std::regex e("[-+]?\\d+");
vector<vector<int>> data;
if (!myfile.is_open())
cout << "Unable to open file";
else {
while (getline(myfile, line))
{
vector<int> temp;
while (regex_search(line, m, e)) {
for (auto x : m) {
std::cout << x.str() << " ";
temp.push_back(atoi(x.str().c_str()));
}
std::cout << std::endl;
line = m.suffix().str();
}
data.push_back(temp);
}
myfile.close();
}
return 0;
}

How do I skip reading a line in a file in C++?

The file contains the following data:
#10000000 AAA 22.145 21.676 21.588
10 TTT 22.145 21.676 21.588
1 ACC 22.145 21.676 21.588
I tried to skip lines starting with "#" using the following code:
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
using namespace std;
int main() {
while( getline("myfile.txt", qlline)) {
stringstream sq(qlline);
int tableEntry;
sq >> tableEntry;
if (tableEntry.find("#") != tableEntry.npos) {
continue;
}
int data = tableEntry;
}
}
But for some reason it gives this error:
Mycode.cc:13: error: request for
member 'find' in 'tableEntry', which
is of non-class type 'int'
Is this more like what you want?
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
fstream fin("myfile.txt");
string line;
while(getline(fin, line))
{
//the following line trims white space from the beginning of the string
line.erase(line.begin(), find_if(line.begin(), line.end(), not1(ptr_fun<int, int>(isspace))));
if(line[0] == '#') continue;
int data;
stringstream(line) >> data;
cout << "Data: " << data << endl;
}
return 0;
}
You try to extract an integer from the line, and then try to find a "#" in the integer. This doesn't make sense, and the compiler complains that there is no find method for integers.
You probably should check the "#" directly on the read line at the beginning of the loop.
Besides that you need to declare qlline and actually open the file somewhere and not just pass a string with it's name to getline. Basically like this:
ifstream myfile("myfile.txt");
string qlline;
while (getline(myfile, qlline)) {
if (qlline.find("#") == 0) {
continue;
}
...
}