Я пытаюсь удалить символы, которые не являются цифрами или буквами из строки, с помощью такого глупого метода, поскольку мне не удалось получить другие методы (я настоящий новичок, "просто пытаюсь")

Я знаю, что это неправильный способ, но мой вопрос в том, в чем проблема, в чем ошибка, поскольку он не работает: 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;
0
Basma 6 Мар 2015 в 16:14

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 стирает все те, которые были перемещены на задний план.

2
Angew is no longer proud of SO 6 Мар 2015 в 13:26

Общий подход для таких задач состоит в использовании стирания функции-члена вместе со стандартным алгоритмом 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

Для выполнения этой операции нет необходимости использовать дополнительную строку.

0
Vlad from Moscow 6 Мар 2015 в 13:41

Проблема в том, как вы пытаетесь расширить строку y. Индексирование может применяться только в домене строки (т.е. вы не можете индексировать за пределами длины строки)

Измените y[t++] = g[i] на y += g[i]

Кроме того, я хотел бы упомянуть, что вам не нужна ветка else. Когда выполнение достигает конца области цикла, оно будет "автоматически" continue, его не нужно выражать явно.

PS: Это классический C ++, а не C ++ 11, я бы принял ответ Captain Giraffe

2
Géza Török 6 Мар 2015 в 15:16

Это разумно выражено в стандартной библиотеке. Что-то вроде

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>. Энгью объясняет причину, по которой ваш не работает.

2
Captain Giraffe 6 Мар 2015 в 13:26