Home > Software engineering >  C how to split string with alphabets and numbers
C how to split string with alphabets and numbers

Time:02-21

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

CodePudding user response:

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

CodePudding user response:

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;

CodePudding user response:

You could indeed use regular expressions for this:

  • The pattern would be ([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.
  • Should you need to relax the regular expression, e.g. allowing white spaces before, after, or in the middle of the input string, you could do it easily just changing the pattern: \s*([A-Z] )\s*([0-9] )\s*.

[Demo]

#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'
  • Related