Reputation: 27608
I have a need to split the following string into their corresponding alpahbets and numbers
CH1000003
ABC000123
WXYZ10001
Results I want are
st1: CH
st2: 1000003
st1: ABC
st2: 000123
st1: WXYZ
st2: 10001
Now I do have a working code but the amount of code I have written seems a bit too much. There has to be an easy way. Perhaps somehow use regex in C++? Suggestions?
My code:
std::string idToCheckStr="CH1000003";
//find length of string
int strLength = idToCheckStr.length();
cout << "idToCheckStr: " << idToCheckStr <<endl;
cout << "strLength : " << strLength <<endl;
string::iterator it;
int index = 0;
for ( it = idToCheckStr.begin() ; it < idToCheckStr.end(); it++ ,index++)
{
//check where the numbers start in the string
if (std::isdigit(*it) != 0)
{
cout<< "FOUND NUMBER!" <<endl;
cout<< index << ": " << *it <<endl;
break;
}
cout<< index << ": " << *it <<endl;
}
std::string firstPartStr = idToCheckStr.substr (0,index);
cout << "firstPartStr: " << firstPartStr <<endl;
std::string secondPartStr = idToCheckStr.substr (index,strLength);
cout << "secondPartStr: " << secondPartStr <<endl;
OUTPUT:
idToCheckStr: CH1000003
strLength : 9
0: C
1: H
FOUND NUMBER!
2: 1
firstPartStr: CH
secondPartStr: 1000003
Upvotes: 0
Views: 928
Reputation: 8064
You could indeed use regular expressions for this:
([A-Z]+)([0-9]+)
, i.e. any combination of 1 or more uppercase letters followed by any combination of 1 or more numbers. The parentheses allow you to capture those 2 groups to be able to access them later on.std::regex_match(line, matches, pattern)
takes an input line
, and tries to match it against a pattern
. If it can, stores the matches in a std::smatch
array; where the first entry is always the whole match, and the successive ones are for each capturing group. If it can't, it just returns false
.\s*([A-Z]+)\s*([0-9]+)\s*
.#include <fmt/core.h>
#include <iostream> // cout
#include <regex> // regex_match, smatch
#include <string>
int main() {
std::string line{};
std::regex pattern{R"(([A-Z]+)([0-9]+))"};
while (std::getline(std::cin, line)) {
std::smatch matches{};
if (std::regex_match(line, matches, pattern)) {
std::cout << fmt::format("line = '{}', alphabets = '{}', numbers = '{}'\n",
matches[0].str(), matches[1].str(), matches[2].str());
}
}
}
// Outputs:
//
// line = 'CH1000003', alphabets = 'CH', numbers = '1000003'
// line = 'ABC000123', alphabets = 'ABC', numbers = '000123'
// line = 'WXYZ10001', alphabets = 'WXYZ', numbers = '10001'
Upvotes: 0
Reputation: 576
Here is one of the simple ways to handle your problem. I find this more understandable for you.
string s = "CH1000003";
// cin >> s; if you waant to read the input
string st1 = "", st2 = "";
for(auto ch : s) {
if(isdigit(ch)) st2 += ch;
else if(isalpha(ch)) st1 += ch;
else {} // if you want something else
}
cout << "st1: " << st1 << endl;
cout << "st2: " << st2 << endl;
Upvotes: 0
Reputation: 27608
Thanks to igor.
size_t first_digit = idToCheckStr.find_first_of("0123456789");
cout << "first_digit: " << first_digit <<endl;
std::string str1 = idToCheckStr.substr (0,first_digit);
cout << "str1: " << str1 <<endl;
std::string str2 = idToCheckStr.substr (first_digit,idToCheckStr.length());
cout << "str2: " << str2 <<endl;
OUTPUT:
first_digit: 2
str1: CH
str2: 1000003
Upvotes: 2