Simple parser with regular expression

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
5
down vote

favorite












If I draw something in Illustrator and extract it with AI2Canvas I want it to be customizable so I wrote this simple program. It adds two variables: one to resize and one to shift the path coordinate.



#include <fstream>
#include <regex>
#include <string>

int main(int argc, char *argv)
std::string path = argv[1];
std::ifstream input(path);

std::size_t found_name = path.find_last_of("/\");
std::size_t found_extension = path.find_last_of(".");
const int steps = found_extension - found_name - 1;
std::ofstream output(path.substr(found_name + 1, steps) + ".txt");

std::regex pattern("(\d+(\.\d+)?), (\d+(\.\d+)?)");
std::string in;
while (!input.eof())
std::getline(input, in);
output << std::regex_replace(in, pattern, "($1 * resize.x) + pos.x, ($3 * resize.y) + pos.y")
<< 'n';

return 0;



Test file Raw: https://pastebin.com/fDh9qbd8



Test file Resolved: https://pastebin.com/R2gpXD8Q







share|improve this question

















  • 1




    Instead of modifying each pair of coordinates, you could also insert a single ctx.translate and ctx.rotate before the drawing commands.
    – Roland Illig
    Apr 27 at 18:03










  • “Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.” — Jamie Zawinski
    – JDługosz
    Apr 27 at 20:49

















up vote
5
down vote

favorite












If I draw something in Illustrator and extract it with AI2Canvas I want it to be customizable so I wrote this simple program. It adds two variables: one to resize and one to shift the path coordinate.



#include <fstream>
#include <regex>
#include <string>

int main(int argc, char *argv)
std::string path = argv[1];
std::ifstream input(path);

std::size_t found_name = path.find_last_of("/\");
std::size_t found_extension = path.find_last_of(".");
const int steps = found_extension - found_name - 1;
std::ofstream output(path.substr(found_name + 1, steps) + ".txt");

std::regex pattern("(\d+(\.\d+)?), (\d+(\.\d+)?)");
std::string in;
while (!input.eof())
std::getline(input, in);
output << std::regex_replace(in, pattern, "($1 * resize.x) + pos.x, ($3 * resize.y) + pos.y")
<< 'n';

return 0;



Test file Raw: https://pastebin.com/fDh9qbd8



Test file Resolved: https://pastebin.com/R2gpXD8Q







share|improve this question

















  • 1




    Instead of modifying each pair of coordinates, you could also insert a single ctx.translate and ctx.rotate before the drawing commands.
    – Roland Illig
    Apr 27 at 18:03










  • “Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.” — Jamie Zawinski
    – JDługosz
    Apr 27 at 20:49













up vote
5
down vote

favorite









up vote
5
down vote

favorite











If I draw something in Illustrator and extract it with AI2Canvas I want it to be customizable so I wrote this simple program. It adds two variables: one to resize and one to shift the path coordinate.



#include <fstream>
#include <regex>
#include <string>

int main(int argc, char *argv)
std::string path = argv[1];
std::ifstream input(path);

std::size_t found_name = path.find_last_of("/\");
std::size_t found_extension = path.find_last_of(".");
const int steps = found_extension - found_name - 1;
std::ofstream output(path.substr(found_name + 1, steps) + ".txt");

std::regex pattern("(\d+(\.\d+)?), (\d+(\.\d+)?)");
std::string in;
while (!input.eof())
std::getline(input, in);
output << std::regex_replace(in, pattern, "($1 * resize.x) + pos.x, ($3 * resize.y) + pos.y")
<< 'n';

return 0;



Test file Raw: https://pastebin.com/fDh9qbd8



Test file Resolved: https://pastebin.com/R2gpXD8Q







share|improve this question













If I draw something in Illustrator and extract it with AI2Canvas I want it to be customizable so I wrote this simple program. It adds two variables: one to resize and one to shift the path coordinate.



#include <fstream>
#include <regex>
#include <string>

int main(int argc, char *argv)
std::string path = argv[1];
std::ifstream input(path);

std::size_t found_name = path.find_last_of("/\");
std::size_t found_extension = path.find_last_of(".");
const int steps = found_extension - found_name - 1;
std::ofstream output(path.substr(found_name + 1, steps) + ".txt");

std::regex pattern("(\d+(\.\d+)?), (\d+(\.\d+)?)");
std::string in;
while (!input.eof())
std::getline(input, in);
output << std::regex_replace(in, pattern, "($1 * resize.x) + pos.x, ($3 * resize.y) + pos.y")
<< 'n';

return 0;



Test file Raw: https://pastebin.com/fDh9qbd8



Test file Resolved: https://pastebin.com/R2gpXD8Q









share|improve this question












share|improve this question




share|improve this question








edited Apr 27 at 17:21









yuri

3,3852832




3,3852832









asked Apr 27 at 16:19









DiDi

926




926







  • 1




    Instead of modifying each pair of coordinates, you could also insert a single ctx.translate and ctx.rotate before the drawing commands.
    – Roland Illig
    Apr 27 at 18:03










  • “Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.” — Jamie Zawinski
    – JDługosz
    Apr 27 at 20:49













  • 1




    Instead of modifying each pair of coordinates, you could also insert a single ctx.translate and ctx.rotate before the drawing commands.
    – Roland Illig
    Apr 27 at 18:03










  • “Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.” — Jamie Zawinski
    – JDługosz
    Apr 27 at 20:49








1




1




Instead of modifying each pair of coordinates, you could also insert a single ctx.translate and ctx.rotate before the drawing commands.
– Roland Illig
Apr 27 at 18:03




Instead of modifying each pair of coordinates, you could also insert a single ctx.translate and ctx.rotate before the drawing commands.
– Roland Illig
Apr 27 at 18:03












“Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.” — Jamie Zawinski
– JDługosz
Apr 27 at 20:49





“Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.” — Jamie Zawinski
– JDługosz
Apr 27 at 20:49











2 Answers
2






active

oldest

votes

















up vote
4
down vote



accepted










Overall, good code. There is a trap code fell into though.



while (!input.eof())


One of the frequently encountered problems with iostreams. Check the output if it has one extra newline. I'm sure you'll find it. intput.eof() is true when EOF is read, not before it.



Instead, use stream >> variable as a condition or the function that behaves like that. The expression returns a reference to stream itself, but the stream is convertible to bool to see if some failure occured. Basically, the expression above is all these steps:



  1. Try to read.

  2. Set failure flags if error encountered

  3. Return the status

Put in a condition, it is the exact combination one needs to perform more or less controlled input. One needs to check if the read succeeded before doing anything. Some other functions in standard library behave like operator>>, std::getline() included.



As a result of above, the first line of the loop would just become a condition, and everything else intact.



while (std::getline(input, in)) 
output << std::regex_replace(in, pattern, "($1 * resize.x) + pos.x, ($3 * resize.y) + pos.y")
<< 'n';




Smaller things follow.



Usage message would be nice. Usually frequently used utilities are put away from the code. Though in case of single argument programs it might not be much of a problem.



std::ofstream output(path.substr(found_name + 1, steps) + ".txt");


Is a little bit alerting. Since this is end user program (e.g. for a human), they might get something wrong.



Some missing consts here and there.



return 0 is redundant.






share|improve this answer























  • I don't have much experience with regex, but it looks correct and seem to run correctly too. I hope I didn't miss the elephant in the room.
    – Incomputable
    Apr 27 at 18:01






  • 1




    @RolandIllig, I guess I amended my post just before you posted the comment :) I added more words into the sentence about operator>>. I just wanted to base my explanation off of operator>>, then build from there.
    – Incomputable
    Apr 27 at 18:04











  • How about while (input.good() && std::getline(input, line)) ?
    – yuri
    Apr 27 at 18:11










  • Regarding the regex it probably could be simplified to ([0-9.]+), ([0-9.]+)
    – yuri
    Apr 27 at 18:15










  • @yuri, it seems like operator bool is a superset of good() (1, 2, 3). They have different tables, look at the first link. Thus good() is redundant. I could perform parsing of standard, but that will take more than a day :)
    – Incomputable
    Apr 27 at 18:15


















up vote
2
down vote













a short tip: use Raw strings to avoid the nested escapes.



Use auto (almost everywhere).



const int steps = found_extension - found_name - 1;


and by using auto you won’t have this unsigned to signed implicit conversion cluttering up your warnings window. You do compile without generating warnings, right?






share|improve this answer





















  • Yes, I do compile without warnings. I come back to cpp after 4 month, I started learning JavaScript in the meanwhile, so when I was declearing that variable I just put const, than the compiler droped an error and I realize that I was writing cpp, so I added int and left It has It is... Sad story
    – DiDi
    Apr 27 at 21:07










Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193092%2fsimple-parser-with-regular-expression%23new-answer', 'question_page');

);

Post as a guest






























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
4
down vote



accepted










Overall, good code. There is a trap code fell into though.



while (!input.eof())


One of the frequently encountered problems with iostreams. Check the output if it has one extra newline. I'm sure you'll find it. intput.eof() is true when EOF is read, not before it.



Instead, use stream >> variable as a condition or the function that behaves like that. The expression returns a reference to stream itself, but the stream is convertible to bool to see if some failure occured. Basically, the expression above is all these steps:



  1. Try to read.

  2. Set failure flags if error encountered

  3. Return the status

Put in a condition, it is the exact combination one needs to perform more or less controlled input. One needs to check if the read succeeded before doing anything. Some other functions in standard library behave like operator>>, std::getline() included.



As a result of above, the first line of the loop would just become a condition, and everything else intact.



while (std::getline(input, in)) 
output << std::regex_replace(in, pattern, "($1 * resize.x) + pos.x, ($3 * resize.y) + pos.y")
<< 'n';




Smaller things follow.



Usage message would be nice. Usually frequently used utilities are put away from the code. Though in case of single argument programs it might not be much of a problem.



std::ofstream output(path.substr(found_name + 1, steps) + ".txt");


Is a little bit alerting. Since this is end user program (e.g. for a human), they might get something wrong.



Some missing consts here and there.



return 0 is redundant.






share|improve this answer























  • I don't have much experience with regex, but it looks correct and seem to run correctly too. I hope I didn't miss the elephant in the room.
    – Incomputable
    Apr 27 at 18:01






  • 1




    @RolandIllig, I guess I amended my post just before you posted the comment :) I added more words into the sentence about operator>>. I just wanted to base my explanation off of operator>>, then build from there.
    – Incomputable
    Apr 27 at 18:04











  • How about while (input.good() && std::getline(input, line)) ?
    – yuri
    Apr 27 at 18:11










  • Regarding the regex it probably could be simplified to ([0-9.]+), ([0-9.]+)
    – yuri
    Apr 27 at 18:15










  • @yuri, it seems like operator bool is a superset of good() (1, 2, 3). They have different tables, look at the first link. Thus good() is redundant. I could perform parsing of standard, but that will take more than a day :)
    – Incomputable
    Apr 27 at 18:15















up vote
4
down vote



accepted










Overall, good code. There is a trap code fell into though.



while (!input.eof())


One of the frequently encountered problems with iostreams. Check the output if it has one extra newline. I'm sure you'll find it. intput.eof() is true when EOF is read, not before it.



Instead, use stream >> variable as a condition or the function that behaves like that. The expression returns a reference to stream itself, but the stream is convertible to bool to see if some failure occured. Basically, the expression above is all these steps:



  1. Try to read.

  2. Set failure flags if error encountered

  3. Return the status

Put in a condition, it is the exact combination one needs to perform more or less controlled input. One needs to check if the read succeeded before doing anything. Some other functions in standard library behave like operator>>, std::getline() included.



As a result of above, the first line of the loop would just become a condition, and everything else intact.



while (std::getline(input, in)) 
output << std::regex_replace(in, pattern, "($1 * resize.x) + pos.x, ($3 * resize.y) + pos.y")
<< 'n';




Smaller things follow.



Usage message would be nice. Usually frequently used utilities are put away from the code. Though in case of single argument programs it might not be much of a problem.



std::ofstream output(path.substr(found_name + 1, steps) + ".txt");


Is a little bit alerting. Since this is end user program (e.g. for a human), they might get something wrong.



Some missing consts here and there.



return 0 is redundant.






share|improve this answer























  • I don't have much experience with regex, but it looks correct and seem to run correctly too. I hope I didn't miss the elephant in the room.
    – Incomputable
    Apr 27 at 18:01






  • 1




    @RolandIllig, I guess I amended my post just before you posted the comment :) I added more words into the sentence about operator>>. I just wanted to base my explanation off of operator>>, then build from there.
    – Incomputable
    Apr 27 at 18:04











  • How about while (input.good() && std::getline(input, line)) ?
    – yuri
    Apr 27 at 18:11










  • Regarding the regex it probably could be simplified to ([0-9.]+), ([0-9.]+)
    – yuri
    Apr 27 at 18:15










  • @yuri, it seems like operator bool is a superset of good() (1, 2, 3). They have different tables, look at the first link. Thus good() is redundant. I could perform parsing of standard, but that will take more than a day :)
    – Incomputable
    Apr 27 at 18:15













up vote
4
down vote



accepted







up vote
4
down vote



accepted






Overall, good code. There is a trap code fell into though.



while (!input.eof())


One of the frequently encountered problems with iostreams. Check the output if it has one extra newline. I'm sure you'll find it. intput.eof() is true when EOF is read, not before it.



Instead, use stream >> variable as a condition or the function that behaves like that. The expression returns a reference to stream itself, but the stream is convertible to bool to see if some failure occured. Basically, the expression above is all these steps:



  1. Try to read.

  2. Set failure flags if error encountered

  3. Return the status

Put in a condition, it is the exact combination one needs to perform more or less controlled input. One needs to check if the read succeeded before doing anything. Some other functions in standard library behave like operator>>, std::getline() included.



As a result of above, the first line of the loop would just become a condition, and everything else intact.



while (std::getline(input, in)) 
output << std::regex_replace(in, pattern, "($1 * resize.x) + pos.x, ($3 * resize.y) + pos.y")
<< 'n';




Smaller things follow.



Usage message would be nice. Usually frequently used utilities are put away from the code. Though in case of single argument programs it might not be much of a problem.



std::ofstream output(path.substr(found_name + 1, steps) + ".txt");


Is a little bit alerting. Since this is end user program (e.g. for a human), they might get something wrong.



Some missing consts here and there.



return 0 is redundant.






share|improve this answer















Overall, good code. There is a trap code fell into though.



while (!input.eof())


One of the frequently encountered problems with iostreams. Check the output if it has one extra newline. I'm sure you'll find it. intput.eof() is true when EOF is read, not before it.



Instead, use stream >> variable as a condition or the function that behaves like that. The expression returns a reference to stream itself, but the stream is convertible to bool to see if some failure occured. Basically, the expression above is all these steps:



  1. Try to read.

  2. Set failure flags if error encountered

  3. Return the status

Put in a condition, it is the exact combination one needs to perform more or less controlled input. One needs to check if the read succeeded before doing anything. Some other functions in standard library behave like operator>>, std::getline() included.



As a result of above, the first line of the loop would just become a condition, and everything else intact.



while (std::getline(input, in)) 
output << std::regex_replace(in, pattern, "($1 * resize.x) + pos.x, ($3 * resize.y) + pos.y")
<< 'n';




Smaller things follow.



Usage message would be nice. Usually frequently used utilities are put away from the code. Though in case of single argument programs it might not be much of a problem.



std::ofstream output(path.substr(found_name + 1, steps) + ".txt");


Is a little bit alerting. Since this is end user program (e.g. for a human), they might get something wrong.



Some missing consts here and there.



return 0 is redundant.







share|improve this answer















share|improve this answer



share|improve this answer








edited Apr 27 at 18:05


























answered Apr 27 at 17:35









Incomputable

6,00721145




6,00721145











  • I don't have much experience with regex, but it looks correct and seem to run correctly too. I hope I didn't miss the elephant in the room.
    – Incomputable
    Apr 27 at 18:01






  • 1




    @RolandIllig, I guess I amended my post just before you posted the comment :) I added more words into the sentence about operator>>. I just wanted to base my explanation off of operator>>, then build from there.
    – Incomputable
    Apr 27 at 18:04











  • How about while (input.good() && std::getline(input, line)) ?
    – yuri
    Apr 27 at 18:11










  • Regarding the regex it probably could be simplified to ([0-9.]+), ([0-9.]+)
    – yuri
    Apr 27 at 18:15










  • @yuri, it seems like operator bool is a superset of good() (1, 2, 3). They have different tables, look at the first link. Thus good() is redundant. I could perform parsing of standard, but that will take more than a day :)
    – Incomputable
    Apr 27 at 18:15

















  • I don't have much experience with regex, but it looks correct and seem to run correctly too. I hope I didn't miss the elephant in the room.
    – Incomputable
    Apr 27 at 18:01






  • 1




    @RolandIllig, I guess I amended my post just before you posted the comment :) I added more words into the sentence about operator>>. I just wanted to base my explanation off of operator>>, then build from there.
    – Incomputable
    Apr 27 at 18:04











  • How about while (input.good() && std::getline(input, line)) ?
    – yuri
    Apr 27 at 18:11










  • Regarding the regex it probably could be simplified to ([0-9.]+), ([0-9.]+)
    – yuri
    Apr 27 at 18:15










  • @yuri, it seems like operator bool is a superset of good() (1, 2, 3). They have different tables, look at the first link. Thus good() is redundant. I could perform parsing of standard, but that will take more than a day :)
    – Incomputable
    Apr 27 at 18:15
















I don't have much experience with regex, but it looks correct and seem to run correctly too. I hope I didn't miss the elephant in the room.
– Incomputable
Apr 27 at 18:01




I don't have much experience with regex, but it looks correct and seem to run correctly too. I hope I didn't miss the elephant in the room.
– Incomputable
Apr 27 at 18:01




1




1




@RolandIllig, I guess I amended my post just before you posted the comment :) I added more words into the sentence about operator>>. I just wanted to base my explanation off of operator>>, then build from there.
– Incomputable
Apr 27 at 18:04





@RolandIllig, I guess I amended my post just before you posted the comment :) I added more words into the sentence about operator>>. I just wanted to base my explanation off of operator>>, then build from there.
– Incomputable
Apr 27 at 18:04













How about while (input.good() && std::getline(input, line)) ?
– yuri
Apr 27 at 18:11




How about while (input.good() && std::getline(input, line)) ?
– yuri
Apr 27 at 18:11












Regarding the regex it probably could be simplified to ([0-9.]+), ([0-9.]+)
– yuri
Apr 27 at 18:15




Regarding the regex it probably could be simplified to ([0-9.]+), ([0-9.]+)
– yuri
Apr 27 at 18:15












@yuri, it seems like operator bool is a superset of good() (1, 2, 3). They have different tables, look at the first link. Thus good() is redundant. I could perform parsing of standard, but that will take more than a day :)
– Incomputable
Apr 27 at 18:15





@yuri, it seems like operator bool is a superset of good() (1, 2, 3). They have different tables, look at the first link. Thus good() is redundant. I could perform parsing of standard, but that will take more than a day :)
– Incomputable
Apr 27 at 18:15













up vote
2
down vote













a short tip: use Raw strings to avoid the nested escapes.



Use auto (almost everywhere).



const int steps = found_extension - found_name - 1;


and by using auto you won’t have this unsigned to signed implicit conversion cluttering up your warnings window. You do compile without generating warnings, right?






share|improve this answer





















  • Yes, I do compile without warnings. I come back to cpp after 4 month, I started learning JavaScript in the meanwhile, so when I was declearing that variable I just put const, than the compiler droped an error and I realize that I was writing cpp, so I added int and left It has It is... Sad story
    – DiDi
    Apr 27 at 21:07














up vote
2
down vote













a short tip: use Raw strings to avoid the nested escapes.



Use auto (almost everywhere).



const int steps = found_extension - found_name - 1;


and by using auto you won’t have this unsigned to signed implicit conversion cluttering up your warnings window. You do compile without generating warnings, right?






share|improve this answer





















  • Yes, I do compile without warnings. I come back to cpp after 4 month, I started learning JavaScript in the meanwhile, so when I was declearing that variable I just put const, than the compiler droped an error and I realize that I was writing cpp, so I added int and left It has It is... Sad story
    – DiDi
    Apr 27 at 21:07












up vote
2
down vote










up vote
2
down vote









a short tip: use Raw strings to avoid the nested escapes.



Use auto (almost everywhere).



const int steps = found_extension - found_name - 1;


and by using auto you won’t have this unsigned to signed implicit conversion cluttering up your warnings window. You do compile without generating warnings, right?






share|improve this answer













a short tip: use Raw strings to avoid the nested escapes.



Use auto (almost everywhere).



const int steps = found_extension - found_name - 1;


and by using auto you won’t have this unsigned to signed implicit conversion cluttering up your warnings window. You do compile without generating warnings, right?







share|improve this answer













share|improve this answer



share|improve this answer











answered Apr 27 at 21:00









JDługosz

5,047731




5,047731











  • Yes, I do compile without warnings. I come back to cpp after 4 month, I started learning JavaScript in the meanwhile, so when I was declearing that variable I just put const, than the compiler droped an error and I realize that I was writing cpp, so I added int and left It has It is... Sad story
    – DiDi
    Apr 27 at 21:07
















  • Yes, I do compile without warnings. I come back to cpp after 4 month, I started learning JavaScript in the meanwhile, so when I was declearing that variable I just put const, than the compiler droped an error and I realize that I was writing cpp, so I added int and left It has It is... Sad story
    – DiDi
    Apr 27 at 21:07















Yes, I do compile without warnings. I come back to cpp after 4 month, I started learning JavaScript in the meanwhile, so when I was declearing that variable I just put const, than the compiler droped an error and I realize that I was writing cpp, so I added int and left It has It is... Sad story
– DiDi
Apr 27 at 21:07




Yes, I do compile without warnings. I come back to cpp after 4 month, I started learning JavaScript in the meanwhile, so when I was declearing that variable I just put const, than the compiler droped an error and I realize that I was writing cpp, so I added int and left It has It is... Sad story
– DiDi
Apr 27 at 21:07












 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f193092%2fsimple-parser-with-regular-expression%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Chat program with C++ and SFML

Function to Return a JSON Like Objects Using VBA Collections and Arrays

Will my employers contract hold up in court?