Как перебрать строку, состоящую из цифр и букв, и добавить в вектор только числа?
Например, если ввод:
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;
}
Ваш опубликованный код не работает? Если да, то каким образом? Пожалуйста отредактируйте этот вопрос, чтобы добавить эту информацию. Такие заявления, как «это не работает» , не являются достаточным описанием проблемы.
Добавляйте цифры к строке так же, как вы это делаете сейчас. Но добавьте случай, когда вы получаете нецифровой символ, чтобы вставить строку в ваш вектор и сбросить строку.
С другой стороны, int sm;
, а затем sm += ...
? Помните, что неинициализированные переменные на самом деле являются неинициализированными с неопределенным значением. Любое использование неопределенных значений приводит к неопределенному поведению.
Будет ли это работать для вас?
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 я не использовал, так как просто не знал об этой функции :)
Еще один подход, в котором больше используются стандартные библиотечные функции. Живая демонстрация здесь: 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;
}
Просто в качестве примечания: Почему я не должен #include <bits/stdc++.h>?