Как извлечь все числа из строки, где числа перемежаются буквами?

Как перебрать строку, состоящую из цифр и букв, и добавить в вектор только числа?

Например, если ввод:

e385p336J434Y26C2Z6X5Z2

Я хочу получить вектор int следующим образом:

число = {385, 336, 434, 26, 2, 6, 5, 2}


Лучшее, что я получил, это перебрать строку и добавить все цифры следующим образом:

#include <bits/stdc++.h>


int main(){
    string f = "e385p336J434Y26C2Z6X5Z2";
    vector<int> f_numb; 
    string sum; 
    for (int i = 0; i < f.size(); ++i){
         if (('0' <= f[i]) && (f[i] <= '9')){
            sum += (f[i]);
            
             
         }
    }
    //std::cout << sum << std::endl; 
    vector<int> m_numb; 
    for (int i = 0; i < sum.size(); ++i){
        m_numb.push_back(sum[i] - '0'); 
    }
    int sm; 
    for (int i = 0; i < m_numb.size(); ++i){
        sm += m_numb[i]; 
        std::cout << m_numb[i] << " "; 
    }
    std::cout << std::endl; 
    
}

Просто в качестве примечания: Почему я не должен #include <bits/stdc++.h>?

Andreas Wenzel 19.02.2023 12:49

Добавляйте цифры к строке так же, как вы это делаете сейчас. Но добавьте случай, когда вы получаете нецифровой символ, чтобы вставить строку в ваш вектор и сбросить строку.

Some programmer dude 19.02.2023 12:50

С другой стороны, int sm;, а затем sm += ...? Помните, что неинициализированные переменные на самом деле являются неинициализированными с неопределенным значением. Любое использование неопределенных значений приводит к неопределенному поведению.

Some programmer dude 19.02.2023 12:53
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
93
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Будет ли это работать для вас?

std::string f = "e385p336J434Y26C2Z6X5Z2";
std::vector<int> f_numb; 
std::string sum; 

#define MAX_DIGITS 25
char aBuildNumber[MAX_DIGITS];
int aBuildCount=0;

std::vector<int> m_numb; 
for (int i = 0; i < f.size(); ++i)
{
    if (!isdigit(f[i]) || aBuildCount>=MAX_DIGITS-1) 
    {
        if (aBuildCount>0) m_numb.push_back(atoi(aBuildNumber)); 
        aBuildCount=0;
    }
    else {aBuildNumber[aBuildCount++]=f[i];aBuildNumber[aBuildCount]=0;}
}
if (aBuildCount>0) m_numb.push_back(atoi(aBuildNumber)); 

int sm=0; 
for (int i = 0; i < m_numb.size(); ++i)
{
    sm += m_numb[i]; 
    std::cout << m_numb[i] << " "; 
}
std::cout << std::endl; 
Ответ принят как подходящий

За исключением неустановленной причины, по которой вы не используете std::isdigit, вы можете/должны просто создавать каждое число по мере обработки его цифр. Обратите внимание, что приведенный ниже код НЕ проверяет и не заботится о беззнаковом переполнении и не пытается обрабатывать отрицательные числа.

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

int main()
{
    std::string f = "e385p336J434Y26C2Z6X5Z2";
    std::vector<unsigned int> f_numb;

    for (auto it = f.begin(); it != f.end();)
    {
        if ('0' <= *it && *it <= '9')
        {
            unsigned int sm = 0;
            for (;it != f.end() && '0' <= *it && *it <= '9'; ++it)
                sm = (sm * 10) + (*it - '0');

            f_numb.emplace_back(sm);
        }
        else
        {
            ++it;
        }
    }

    for (auto x : f_numb)
        std::cout << x << ' ';
    std::cout << '\n';
}

Выход

385 336 434 26 2 6 5 2 

Это, если я понимаю ваш вопрос по сравнению с вашим кодом, которые сильно различаются по своим очевидным целям.

Большое спасибо! это именно то, что я хотел. isdigit я не использовал, так как просто не знал об этой функции :)

Swagga 19.02.2023 15:54

Еще один подход, в котором больше используются стандартные библиотечные функции. Живая демонстрация здесь: https://onlinegdb.com/8eEgREuEN

Я предпочитаю создавать функции из подэтапов, чтобы тестировать их по отдельности.

#include <algorithm>
#include <iterator> // back_inserter
#include <string>
#include <vector>
#include <iostream>
#include <string_view>

// I like to make functions for substeps (they tend to be reusable)

std::vector<std::string> get_number_substrings(const std::string& input)
{
    static const std::string_view digits{ "0123456789" };
    std::vector<std::string> substrings;

    auto start_pos = input.find_first_of(digits, 0ul);
    auto end_pos = start_pos;
    auto max_length = input.length();

    while (start_pos < max_length)
    {
        end_pos = std::min(max_length, input.find_first_not_of(digits, start_pos));

        if (end_pos != start_pos)
        {
            substrings.emplace_back(&input[start_pos], end_pos - start_pos);
            start_pos = input.find_first_of(digits, end_pos);
        }
    }

    return substrings;
}

std::vector<int> get_numbers(const std::string& input)
{
    auto numbers = get_number_substrings(input);
    std::vector<int> output;

    // now transform the string to vector<int>
    // the back_inserter is needed because output doesn't have allocated memory yet
    // and that needs to be build up during the transform. 
    // https://en.cppreference.com/w/cpp/iterator/back_inserter
    // https://en.cppreference.com/w/cpp/algorithm/transform

    std::transform(numbers.begin(), numbers.end(), std::back_inserter(output), [](const std::string& string)
    {
        return std::stoi(string);
    });

    return output;
}

int main()
{
    std::string input{ "e385p336J434Y26C2Z6X5Z2" };

    auto output = get_numbers(input); // output will be a std::vector<int>

    // Use range based for loop
    // https://en.cppreference.com/w/cpp/language/range-for
    bool comma = false;
    for (const int value : output)
    {
        if (comma) std::cout << ", ";
        std::cout << value;
        comma = true;
    }

    return 0;
}

Другие вопросы по теме