How to extract whole numbers not adjacent to letters <8408<f16f15>9387541<47g28<829o... in C++

2 Answers

0 votes
/*
========================================================
Title: Extract Whole Numbers Not Adjacent to Letters
========================================================
 
Definition:
 
A whole number is a maximal sequence of digits that is
NOT directly adjacent to an alphabetic character.
 
Examples:
 
    <8408<f16f15>9387541<47g28<829oiew0>>2i7>3<y5>8cas>616>9>
 
Output:
 
    8408
    9387541
    3
    616
    9
 
Why this approach?
 
    * Fast (single pass)
    * No regex overhead
    * Easy to understand
    * Production-friendly
*/
 
#include <cctype>
#include <iostream>
#include <string>
 
int main()
{
    const std::string text =
        "<8408<f16f15>9387541<47g28<829oiew0>>2i7>3<y5>8cas>616>9>";
 
    std::size_t i = 0;
 
    while (i < text.size())
    {
        if (!std::isdigit(static_cast<unsigned char>(text[i]))) {
            ++i;
            continue;
        }
 
        const std::size_t start = i;
 
        while (i < text.size() &&
               std::isdigit(static_cast<unsigned char>(text[i])))
        {
            ++i;
        }
 
        const std::size_t end = i;
 
        const bool left_is_letter =
            start > 0 &&
            std::isalpha(
                static_cast<unsigned char>(text[start - 1]));
 
        const bool right_is_letter =
            end < text.size() &&
            std::isalpha(
                static_cast<unsigned char>(text[end]));
 
        if (!left_is_letter && !right_is_letter) {
            std::cout
                << text.substr(start, end - start)
                << '\n';
        }
    }
}
 
 
 
/*
run:
 
8408
9387541
3
616
9
 
*/
 

 



answered Oct 10 by avibootz
0 votes
/*
========================================================
Title: Extract Whole Numbers From a String
========================================================

Definition:

A whole number is a consecutive sequence of digits that
is not immediately adjacent to an alphabetic character.

Example Input:
    <8408<f16f15>9387541<47g28<829oiew0>>2i7>3<y5>8cas>616>9>

Expected Output:
    8408
    9387541
    3
    616
    9

Best Practices Demonstrated:
    - Reusable function
    - Const correctness
    - No global variables
    - Safe use of std::isdigit/std::isalpha
    - Returns results instead of printing
*/

#include <cctype>
#include <iostream>
#include <string>
#include <vector>

/*
 * Extract all whole numbers from the input string.
 */
std::vector<std::string> extractWholeNumbers(const std::string& text)
{
    std::vector<std::string> numbers;

    std::size_t i = 0;

    while (i < text.size())
    {
        // Skip non-digits.
        if (!std::isdigit(static_cast<unsigned char>(text[i]))) {
            ++i;
            continue;
        }

        // Beginning of a digit sequence.
        const std::size_t start = i;

        while (i < text.size() &&
               std::isdigit(static_cast<unsigned char>(text[i])))
        {
            ++i;
        }

        const std::size_t end = i;

        // Check neighboring characters.
        const bool leftIsLetter =
            start > 0 &&
            std::isalpha(static_cast<unsigned char>(text[start - 1]));

        const bool rightIsLetter =
            end < text.size() &&
            std::isalpha(static_cast<unsigned char>(text[end]));

        // Keep only numbers not touching letters.
        if (!leftIsLetter && !rightIsLetter) {
            numbers.emplace_back(text.substr(start, end - start));
        }
    }

    return numbers;
}

int main()
{
    const std::string text =
        "<8408<f16f15>9387541<47g28<829oiew0>>2i7>3<y5>8cas>616>9>";

    const auto numbers = extractWholeNumbers(text);

    for (const auto& number : numbers) {
        std::cout << number << '\n';
    }
}



/*
run:

8408
9387541
3
616
9

*/

 



answered Oct 10 by avibootz
...