Reputation: 57
I would like to extract several sets of numbers from a string and paste them into another string accordingly.
Let's say there is a dialog and we get the WndCaption as String A (input string).
String A: Voltage: 2.0V, Current:0.4A, Resistance: 5.0Ω, Power: 1.5W.
String A is a dynamic input, it depends on the WndCaption of the dialog. For example, String A also can be The apple is inside column: 12, row: 3, box: 5.
String B (input reference string) is exactly the same as String A except the numbers are replaced by delimiter. It is used to extract the numbers from String A.
String B: Voltage: %fV, Current:%fA, Resistance: %fΩ, Power: %fW.
Then this is String C (output reference string),
String C: The answers are %fV; %fA; %fΩ; %fW.
String B and String C are paired together that get from a database (.txt file) using std::vector<>::data
.
Question is: how can I extract that 4 sets of number and paste them into String C and get the final output as The answers are 2.0V; 0.4A; 5.0Ω; 1.5W.
?
I tried to implement the split and merge method but it seems not possible for this situation. Any idea?
Upvotes: 1
Views: 383
Reputation: 1306
You should definitely use regex to perform that task. They're more flexible and can parse almost anything.
In case the format is very limited, and will never ever change, you might get away by using sscanf
. Here's an example program :
#include <iostream>
#include <string>
int main()
{
char input[100];
int param1, param2, param3;
char output[100];
sprintf( input, "%s", "AA123BBB45CCCCC6789DDDD" ); // your input
sscanf( input, "AA%dBBB%dCCCCC%dDDDD", ¶m1, ¶m2, ¶m3); // parse the parameters
sprintf(output, "E%dFF%dGGG%dHHHH", param1, param2, param3); // print in output with your new format
printf("%s", output);
return(0);
}
Post-edit :
That answer doesn't make any sense anymore, but I'll leave it like that.
My advice remains : use regexes.
Upvotes: 1
Reputation: 16747
I've impelemented code below as an example what can be done.
I didn't understand what exact steps to achieve your task, but I understood that you need two things - first finding and extracting matches of some substring inside input string using regular expressions or something, second compose new string by putting inside some substrings found on first stage.
In my code below I implemented both stages - first extracting substrings using regular expression, second composing new string.
I used functions and objects from standard C++ module std::regex. Also I coded a special helper function string_format(format, args...)
to be able to do formatting of composed result, formatting is achieved through described here formatting specifiers.
You may achieve your goal by repeating next code few times by first extracting necessary substring and the composing result formatted string.
Next code can be also run online here! or here!
#include <regex>
#include <string>
#include <regex>
#include <iostream>
#include <stdexcept>
#include <memory>
using namespace std;
// Possible formatting arguments are described here https://en.cppreference.com/w/cpp/io/c/fprintf
template<typename ... Args>
std::string string_format( const std::string& format, Args ... args )
{
size_t size = snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0'
if( size <= 0 ){ throw std::runtime_error( "Error during formatting." ); }
std::unique_ptr<char[]> buf( new char[ size ] );
snprintf( buf.get(), size, format.c_str(), args ... );
return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
}
int main() {
try {
string str = "abc12345DEF xyz12ABcd";
cout << "Input string [" << str << "]." << endl;
string sre0 = "\\d+[A-Z]+";
// https://en.cppreference.com/w/cpp/header/regex
std::regex re0(sre0);
vector<string> elems;
std::sregex_token_iterator iter(str.begin(), str.end(), re0, 0);
std::sregex_token_iterator end;
while (iter != end) {
elems.push_back(*iter);
++iter;
cout << "matched [" << elems.back() << "] " << endl;
}
string fmt = "New String part0 \"%s\" and part1 \"%s\" and some number %d.";
string formatted = string_format(fmt.c_str(), elems.at(0).c_str(), elems.at(1).c_str(), 987);
cout << "Formatted [" << formatted << "]." << endl;
return 0;
} catch (exception const & ex) {
cout << "Exception: " << ex.what() << endl;
return -1;
}
}
Code output:
Input string [abc12345DEF xyz12ABcd].
matched [12345DEF]
matched [12AB]
Formatted [New String part0 "12345DEF" and part1 "12AB" and some number 987.].
Upvotes: 1