Ошибка сегментации в программе C ++, обнаруживающей появление символа в повторяющейся строке - PullRequest
0 голосов
/ 20 апреля 2020

Следующий код подсчитывает общее вхождение символа, 'a' в строке, s повторяется до n символов:

#include<iostream>
using namespace std;

long repeatedString(string s, long n) 
{
    long count=0,i;
    char *s1{ new char[n]{} };
    int j=0;
    for(i=0;i<n;i++)
    {
        s1[i]=s[j++];
        if(j==s.size())
            j=0;
    }

    for(i=0;i<n;i++)
    {
        if(s1[i]=='a')
            count++;
    }
    return count;

}

int main()
{
   string s = "abaca";
   long n = 12;
   cout<<repeatedString(s,n);
   return 0;
}

Работает нормально при следующем вводе:

Например. Здесь s равно "abaca", s1 будет "abacaabacaab", поэтому n рассчитывается до 7.

Но если s равно "a" и n is 1000000000000, он прерывается из-за bad_allo c

Может кто-нибудь помочь мне решить эту проблему?

Заранее спасибо!

Ответы [ 2 ]

4 голосов
/ 20 апреля 2020

Мы начинаем с s1.size() == 0 и для строки s1[i] недопустимо для любого значения i больше или равно s1.size(). В этом случае оно всегда недействительно.

Измените s1[i]=s[j++]; на s1 +=s [j++];

1 голос
/ 20 апреля 2020

Объект s1 типа std :: string пуст

string s1="";

Поэтому вы не можете использовать оператор индекса для его изменения

    s1[i]=s[j++];

Вы можете объявить объект как

string s1( n, ' ' );

В этом случае он содержит n элементов, которые можно изменить с помощью оператора индекса.

Другой подход заключается в использовании оператора + =. Например,

string s1;
s1.reserve( n );

//...

s1 + = s [j ++];

Обратите внимание на то, что значение 1000000000000 параметра n может быть слишком большим, и система не сможет выделить такой string.

В этом случае вам необходимо проверить, может ли система выделить достаточно элементов для объекта.

Например,

string s1;

if ( not ( n < s1.max_size() ) ) n = s1.max_size();
s1.reserve( n );

, а затем

s1 + = s [j ++];

Обратите внимание, что тип возвращаемого значения функции должен быть не менее size_t, но будет еще лучше использовать std::string::size_type.

Вот демонстрационная программа

#include <iostream>
#include <string>

std::string::size_type repeatedString( const std::string &s, std::string::size_type n ) 
{
    std::string s1;

    if ( not( n < s1.max_size() ) ) n = s1.max_size();

    s1.reserve( n );

    for ( std::string::size_type i = 0, j = 0; i < n; i++ )
    {
        s1 += s[j++];

        if ( j == s.size() ) j = 0;
    }

    std::string::size_type count = 0;

    for ( const auto &c : s1 )
    {
        if ( c == 'a' ) ++count;
    }

    return count;
}

int main() 
{
    std::string s( "abaca" );

    std::string::size_type n = 12;

    std::cout << repeatedString( s, n ) << '\n';

    return 0;
}

Ее вывод

7

Вместо основанного на диапазоне значения для l oop в функции

    for ( const auto &c : s1 )
    {
        if ( c == 'a' ) ++count;
    }

вы можете использовать стандартный алгоритм std::count, объявленный в заголовке <algorithm>.

Если система не может выделить строку заданного размера, она выдает исключение типа std::bad_alloc. Вы можете перехватить исключение.

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

#include <iostream>
#include <string>

std::string::size_type repeatedString( const std::string &s, 
                                       std::string::size_type n ) throw( std::bad_alloc ) 
{
    std::string s1;

    if ( not( n < s1.max_size() - 1 ) ) n = s1.max_size() - 1;

    s1.reserve( n );

    return n;

    for ( std::string::size_type i = 0, j = 0; i < n; i++ )
    {
        s1 += s[j++];

        if ( j == s.size() ) j = 0;
    }

    std::string::size_type count = 0;

    for ( const auto &c : s1 )
    {
        if ( c == 'a' ) ++count;
    }

    return count;
}

int main() 
{
    std::string s( "a" );

    std::string::size_type n = 1000000000000;

    try
    {
        std::cout << repeatedString( s, n ) << '\n';
    }
    catch ( const std::bad_alloc & )
    {
        std::cout << n << " is too big value.\n";
    }

    return 0;
}

Вывод программы может выглядеть как

1000000000000 is too big value.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...