Я пытаюсь удалить символы, которые не являются цифрами или буквами из строки, с помощью такого глупого метода, поскольку мне не удалось получить другие методы (я настоящий новичок, "просто пытаюсь")
Я знаю, что это неправильный способ, но мой вопрос в том, в чем проблема, в чем ошибка, поскольку он не работает: S
string g = "9-=p98u;iu8y76";
string y;
int t = 0;
for (int i = 0; i < g.length(); i++)
{
if (isdigit(g[i]) || isalpha(g[i]))
{
y[t++] = g[i];
}
else
continue;
}
g = y;
cout << g;
4 ответа
Проблема в том, что размер y
равен 0, он пуст. Таким образом, доступ к его элементам (с использованием y[t++]
) достигает «после» строки - это переполнение буфера и неопределенное поведение.
Вам нужно продлить y
. Чтобы сделать это с минимальными изменениями в вашем коде, вы должны сделать это:
string g = "9-=p98u;iu8y76";
string y;
for (int i = 0; i < g.length(); i++)
{
if (isdigit(g[i]) || isalpha(g[i]))
{
y.push_back(g[i]);
}
else
continue;
}
g = y;
cout << g;
Конечно, есть и другие способы сделать это. Использование стандартных алгоритмов и идиомы «стереть-удалить» было бы более идиоматичным C ++. Весь код можно заменить на это:
auto shouldBeRemoved = [](char c) { !(isdigit(c) || isalpha(c)) };
g.erase(std::remove_if(g.begin(), g.end(), shouldBeRemoved), g.end());
cout << g;
std::remove_if
работает путем реорганизации диапазона таким образом, чтобы все элементы, соответствующие предикаты (т.е. те, которые должны быть удалены) перемещаются после всех элементов, которые должны остаться. Затем функция-член erase
стирает все те, которые были перемещены на задний план.
Общий подход для таких задач состоит в использовании стирания функции-члена вместе со стандартным алгоритмом std::remove_if
, объявленным в заголовке <algorithm>
.
Например
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main()
{
std::string s = "9-=p98u;iu8y76";
std::cout << s << std::endl;
s.erase( std::remove_if( s.begin(), s.end(),
[]( char c )
{
return !std::isalnum( ( unsigned char )c );
} ),
s.end() );
std::cout << s << std::endl;
return 0;
}
Вывод программы
9-=p98u;iu8y76
9p98uiu8y76
Что касается вашего кода, вы пытаетесь использовать оператор индекса
y[t++] = g[i];
Для пустой строки
string y;
Учтите, что вместо двух функций std::isalpha
и std::isdigit
вы можете использовать одну функцию std::isalnum
, как показано в моей демонстрационной программе.
Если вы хотите сами писать циклы, программа может выглядеть так:
#include <iostream>
#include <string>
#include <cctype>
int main()
{
std::string s = "9-=p98u;iu8y76";
std::cout << s << std::endl;
std::string::size_type i = 0;
while ( i < s.length() && std::isalnum( ( unsigned char )s[i] ) ) ++i;
std::string::size_type j = i;
while ( i++ < s.length() )
{
if ( std::isalnum( ( unsigned char )s[i] ) ) s[j++] = s[i];
}
s.erase( j );
std::cout << s << std::endl;
return 0;
}
Вывод программы такой же, как указано выше.
9-=p98u;iu8y76
9p98uiu8y76
Для выполнения этой операции нет необходимости использовать дополнительную строку.
Проблема в том, как вы пытаетесь расширить строку y
. Индексирование может применяться только в домене строки (т.е. вы не можете индексировать за пределами длины строки)
Измените y[t++] = g[i]
на y += g[i]
Кроме того, я хотел бы упомянуть, что вам не нужна ветка else
. Когда выполнение достигает конца области цикла, оно будет "автоматически" continue
, его не нужно выражать явно.
PS: Это классический C ++, а не C ++ 11, я бы принял ответ Captain Giraffe
Это разумно выражено в стандартной библиотеке. Что-то вроде
auto digit_or_alpha = [](char c){ return isdigit(c) || isalpha(c); };
std::copy_if(g.begin(), g.end(), std::back_inserter(y), digit_or_alpha );
Должно сработать. back_inserter находится в <iterator>
. Энгью объясняет причину, по которой ваш не работает.
Похожие вопросы
Новые вопросы
c++
C ++ - это язык программирования общего назначения. Первоначально он был разработан как расширение C и имеет аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде (который должен быть) скомпилирован с помощью компилятора C ++. Используйте тег для конкретной версии для вопросов, связанных с конкретной версией стандарта [C ++ 11], [C ++ 14], [C ++ 17], [C ++ 20] или [C ++ 23] и т. Д. .