On-line: гостей 0. Всего: 0 [подробнее..]
Программисты всех стран, объединяйтесь!

АвторСообщение



ссылка на сообщение  Отправлено: 30.05.18 17:14. Заголовок: Предложение по включению в стандарт C++ итераторов c_str_iterator и const_c_str_iterator


Нередко приходится выполнять стандартные алгоритмы для C-строк.

Чтобы предоставить два итератора, начальный итератор и конечный итератор диапазона, то есть начало и конец строки, для алгоритма приходится вызывать стандартную C-функцию strlen, объявленную в заголовочном файле <cstring>. Например, вызов стандартного алгоритма std::adjacent_find, содержащего строку, может выглядеть следующим образом

 
size_t n = ::strlen( s );

char *p = std::adjacent_find( s, s + n );

if ( p != s + n ) std::cout << p << std::endl;


Как видно из примера, требуется вызывать стандартную C-функцию strlen, чтобы получить конечный итератор диапазона.

Однако все C-строки по определению имеют завершающий ноль-символ '\0', и по этому символу легко определить конец диапазона, если имеешь дело с последовательными итераторами. То есть предварительный вызов функции strlen является неэффективным и избыточным.

В связи с этим я предлагаю использовать итераторы, названные мною как const_c_str_iterator и c_str_iterator, которые позволяют применять стандартные алгоритмы к C-строкам без необходимости вызова стандартной C-функции strlen, чтобы задать диапазон итераторов.

Ниже приведена демонстрационная программа, в которой показано, как данные итераторы для C-строк могут быть определены.

 
#include <iostream>
#include <iterator>
#include <algorithm>

class const_c_str_iterator
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = char;
using difference_type = ptrdiff_t;
using pointer = const char *;
using reference = const char &;

// Constructors
const_c_str_iterator() = default;
explicit const_c_str_iterator( const char *s ) : s( s )
{
}
const_c_str_iterator( const const_c_str_iterator & ) = default;

// The copy assignment operator
const_c_str_iterator & operator =( const const_c_str_iterator &it )
{
this->s = it.s;

return *this;
}

// Conversion operator
operator pointer() const
{
return s;
}

// Increment operators
const_c_str_iterator & operator ++()
{
++this->s;

return *this;
}

const_c_str_iterator operator ++( int )
{
const_c_str_iterator it( this->s );
++this->s;

return it;
}

// Dereferencing operator
reference operator *() const
{
return *s;
}

friend bool operator ==( const const_c_str_iterator &it1, const const_c_str_iterator &it2 );
friend bool operator !=( const const_c_str_iterator &it1, const const_c_str_iterator &it2 );

protected:
const char *s = nullptr;
};

bool operator ==( const const_c_str_iterator &it1, const const_c_str_iterator &it2 )
{
return ( it1.s == it2.s ) || ( not it1.s && not *it2.s ) || ( not *it1.s && not it2.s );
}

bool operator !=( const const_c_str_iterator &it1, const const_c_str_iterator &it2 )
{
return not ( it1 == it2 );
}


class c_str_iterator
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = char;
using difference_type = ptrdiff_t;
using pointer = char *;
using reference = char &;

// Constructors
c_str_iterator() = default;
explicit c_str_iterator( char *s ) : s( s )
{
}
c_str_iterator( const c_str_iterator & ) = default;

// The copy assignment operator
c_str_iterator & operator =( const c_str_iterator &it )
{
this->s = it.s;

return *this;
}

// Conversion operators
operator pointer() const
{
return s;
}

operator const_c_str_iterator() const
{
return const_c_str_iterator( this->s );
}

// Increment operators
c_str_iterator & operator ++()
{
++this->s;

return *this;
}

c_str_iterator operator ++( int )
{
c_str_iterator it( this->s );
++this->s;

return it;
}

// Dereferencing operator
reference operator *() const
{
return *s;
}

friend bool operator ==( const c_str_iterator &it1, const c_str_iterator &it2 );
friend bool operator !=( const c_str_iterator &it1, const c_str_iterator &it2 );

protected:
char *s = nullptr;
};

bool operator ==( const c_str_iterator &it1, const c_str_iterator &it2 )
{
return ( it1.s == it2.s ) || ( not it1.s && not *it2.s ) || ( not *it1.s && not it2.s );
}

bool operator !=( const c_str_iterator &it1, const c_str_iterator &it2 )
{
return not ( it1 == it2 );
}

int main()
{
{
char s[] = "Aa Bb Cc Dd";
const char *t = "Cc";

auto it = std::adjacent_find( c_str_iterator( s ), {},
[=]( char c1, char c2 ) { return c1 == t[0] && c2 == t[1]; } );

if ( it != c_str_iterator() ) std::cout << it << std::endl;

}

{
const char *s = "Aa Bb Cc Dd";
const char *t = "Cc";

auto it = std::adjacent_find( const_c_str_iterator( s ), {},
[=]( char c1, char c2 ) { return c1 == t[0] && c2 == t[1]; } );

if ( it != const_c_str_iterator() ) std::cout << it << std::endl;
}
}


Вывод программы на консоль

 
Cc Dd
Cc Dd


Спасибо: 0 
ПрофильЦитата Ответить
Новых ответов нет


Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 5
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет