1

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?

  • 1
    There is [regex](https://en.cppreference.com/w/cpp/header/regex) module in C++, there is regex_match to find positions of substrings by needed criteria. Then by obtained positions you may extract substring through [substr](http://www.cplusplus.com/reference/string/string/substr/). – Arty Sep 30 '20 at 15:01

2 Answers2

1

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",  &param1, &param2, &param3); // 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.

MartinVeronneau
  • 1,296
  • 7
  • 24
  • The output of `sscanf` example is exactly what I needed. But the numbers of parameter will not be a fix. So the idea is, it should be able to know how many parameters have to extract from String A based on taking String B as the reference. Btw, still trying to implement regex! – Joshua_0101 Oct 05 '20 at 10:21
  • You should edit your question to make this obvious, because that information would have change my answer. Try to be as explicit as possible : why are the parameters dynamix, what controls the number of parameters, etc... – MartinVeronneau Oct 05 '20 at 13:00
  • Thanks for the advice. I had updated the question to make it more details. Hope it explain well. – Joshua_0101 Oct 06 '20 at 02:29
1

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.].
Arty
  • 14,883
  • 6
  • 36
  • 69
  • Hi Arty. The exact steps to achieve the goals are: – Joshua_0101 Oct 05 '20 at 10:23
  • 1. Get String A and compare it with String B. 2. The characters will be the same, the only difference between String A and B is the numbers and delimiters (etc: %d). 3. After comparison, we should get the 3 sets of number only. 4. Saved the 3 sets of number as array. (possible?) 5. Paste the 3 sets of number into String C and replace the delimiters respectively. Also, thanks for the example about the `regex'! – Joshua_0101 Oct 05 '20 at 10:32