LINUX.ORG.RU

C++ итераторы: признак конца последовательности


0

2

Пишу функцию, принимающую строковый итератор, в функции нужно пройтись по всем элементам начиная с указанного до конца. Как определить этот конец при условии, что сама последовательность в функции недоступна, а передавать дополнительный параметр string.end() - не хочется? Попробовал так - работает:

void foo(std::string::const_iterator i){
 for(i;*i!=0;i++)
  printf("%c",*i);
 printf("\n");}

Но я не уверен, есть ли гарантия, что std::string обязана хранить завершающий 0.

★★★★★

Почему бы не передавать строку?

r2d2
()

передавай c_str(). У std::string, насколько я знаю, нет такого понятия как завершающий 0.

anonymous
()
Ответ на: комментарий от anonymous

21.3.6

const charT * c_str () const ; Returns: A pointer to the initial element of an array of length size() + 1 whose first size() elements equal the corresponding elements of the string controlled by *this and whose last element is a null character specified by charT().

urykhy
()
Ответ на: комментарий от anonymous

передавай c_str()

Так и сделаю, если не найдется решения со строкой.

У std::string, насколько я знаю, нет такого понятия как завершающий 0.

Я перед тем как задать здесь вопрос, искал в документации. Гарантируется совместимость с С посредством c_str, но внутренняя реализация не оговаривается, теоретически нуля может не быть. Но мне непонятен сам факт того, что стандартной библиотеке нет обощенного iterator::end как константы например.

staseg ★★★★★
() автор топика
Ответ на: комментарий от anonymous

> У std::string, насколько я знаю, нет такого понятия как завершающий 0.

+1.

Насколько помню, даже нет гарантии, что в памяти все лежит одним куском (для вектора такая гарантия есть).

dave ★★★★★
()
Ответ на: комментарий от anonymous

Перестань позорится, клоун.

2ТС - просто проверяй на 0

anonymous
()
Ответ на: комментарий от anonymous

А-а, ты к тому, что std::string может не храниться одним куском в памяти.

Это не имеет значения, c_str все равно вернет правильную С-строку.

staseg ★★★★★
() автор топика
Ответ на: комментарий от staseg

Но не гарантируется, что итератор работает по тому же куску, на который указывает c_str. Хотя было бы странно найти, где не так реализовано.

dave ★★★★★
()

Не используй stl-итераторы там, где не нужно. Передавай c_str.

schizoid ★★★
()

А вообще, посмотри в сторону for_each.

using namespace std;

struct Printer {
    void operator()(char ch) {
        cout << ch;
    }
    ~Printer() { cout << endl; }
};

for_each(str.begin(), str.end(), Printer())

И Саттера почитай.

schizoid ★★★
()
Ответ на: комментарий от dave

Но не гарантируется, что итератор работает по тому же куску, на который указывает c_str. Хотя было бы странно найти, где не так реализовано.

Естественно. Поэтому и вопрос, можно ли сравнивать значение конечного итератора с нулем - даже если строка внутри раскидана по нескольким кускам, operator* для конечного итератора должен же что-то возвращать, всегда ли это будет 0.

staseg ★★★★★
() автор топика
Ответ на: комментарий от dave

Насколько помню, даже нет гарантии, что в памяти все лежит одним куском

А сложность O(1) vs O(N) для .c_str() оговорена?

Absurd ★★★
()
Ответ на: комментарий от namezys

а чем end не нравится?

Его надо передавать отдельным параметром в мою функцию, что конечно можно, но мне кажется неправильным :)

staseg ★★★★★
() автор топика
Ответ на: комментарий от staseg

а завтра захочешь, чтоб твой алгоритм работал не до end(), а до конкретного элемента

vvviperrr ★★★★★
()
Ответ на: комментарий от namezys

у тебя алгоритм должен либо работать от чего-то до чего-то, либо до встречи чего-то, либо от забора и до обеда

namezys ★★★★
()
Ответ на: комментарий от namezys

почему кажется не правильным?

Розовые очки.

передавай контейнер тогда

Не. Дробить придется. Лень объяснять.

ЗЫ. Тред не о том, как можно пройтись по последовательности, а про то, как конкретно с итератором определить, что итерируемая последовательность закончилась.

staseg ★★★★★
() автор топика
Ответ на: комментарий от staseg

ну так я сказал - делать до какого-то элемента. но string вообще не содержит маркера окончания строки в самой строке. Очень правильно это. Отвыкайте от глупости c string

namezys ★★★★
()
Ответ на: комментарий от staseg

Розовые очки.

Это через них не видно, что везде в STL передаются два итератора - начало и конец?

no-such-file ★★★★★
()
Ответ на: комментарий от staseg

Естественно. Поэтому и вопрос, можно ли сравнивать значение конечного итератора с нулем - даже если строка внутри раскидана по нескольким кускам, operator* для конечного итератора должен же что-то возвращать, всегда ли это будет 0.

По-моему закладываться на это нельзя. Теоретически разыменование по невалидному участку памяти может привести к UB. Почему бы просто не сравнивать значение итератора с end?

dave ★★★★★
()
Ответ на: комментарий от anonymous

См. правило номер 78 «Стандартов программирования на Си++» (Саттер, Александреску).

dave ★★★★★
()

for(i;*i!=0;i++)

Быдлокод. 0 имеет право находиться в любом месте std::string (например, в середине)

передавать дополнительный параметр string.end() - не хочется

Выправляй свои хотения, поскольку сейчас они кривые. Передача двух итераторов - вполне в духе stl.

Manhunt ★★★★★
()
Ответ на: комментарий от Absurd

По-моему, для std::string вообще никакие асимптотики не заявлены.

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

Быдлокод. 0 имеет право находиться в любом месте std::string (например, в середине)

С таким же успехом как и внутри сишной строки. Если использовать строку по назначению, а не как byte array, нуля в середине не будет.

Выправляй свои хотения, поскольку сейчас они кривые. Передача двух итераторов - вполне в духе stl.

Да уже так и сделал. С stl раньше редко очень работал.

staseg ★★★★★
() автор топика
Ответ на: комментарий от namezys

Что такое строка для начала дай определение?

Последовательность символов. Я не знаю символа с кодом ноль.

staseg ★★★★★
() автор топика
Ответ на: комментарий от staseg

С таким же успехом как и внутри сишной строки.

Нет. Обычная си-шная строка - по определению null-terminated.

Если использовать строку по назначению, а не как byte array, нуля в середине не будет.

Назначение строки - хранить последовательность char-ов. Нули имеют право в таких последовательностях встречаться. Вот тебе, для примера, цитата из «man 7 unix»

an abstract socket address is distinguished by the fact that sun_path[0] is a null byte ('\0'). The socket's address in this namespace is given by the additional bytes in sun_path that are covered by the specified length of the address structure. (Null bytes in the name have no special significance.) The name has no connection with file system pathnames. When the address of an abstract socket is returned by getsockname(2), getpeername(2), and accept(2), the returned addrlen is greater than sizeof(sa_family_t) (i.e., greater than 2), and the name of the socket is contained in the first (addrlen - sizeof(sa_family_t)) bytes of sun_path. The abstract socket namespace is a nonportable Linux extension.

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

Нет. Обычная си-шная строка - по определению null-terminated.

terminated, это значит, что внутри нее не может быть нулей, первый же ноль становится концом, т.к. это единственный способ определить границы строки. Верно? Я не утверждаю, что std::string тоже null-terminated.

Вот тебе, для примера, цитата из «man 7 unix»

Это уже какие-то пляски на костылях, а не строка. Массив char-ов - да, но не строка (ни одна из функций для работы со строками с ней не справится).

staseg ★★★★★
() автор топика
Ответ на: комментарий от namezys

такого объекта в stl вообще нет, если что

Очень сложно общаться с человеком, который постоянно нудит, но не говорит по существу.

staseg ★★★★★
() автор топика
Ответ на: комментарий от staseg

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

namezys ★★★★
()

Кстати, а наличие нулевых символов в середине std::string стрингов допускается или нет? А как std::string::length() будет работать ?

Absurd ★★★
()
Ответ на: комментарий от Absurd

А как std::string::length() будет работать ?

Строка хранит в себе свою длину. По этой причине плюсовые строки иногда бывают быстрее сишных.

staseg ★★★★★
() автор топика
Ответ на: комментарий от staseg

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

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

Это уже какие-то пляски на костылях, а не строка.

Это имя. Начинающееся с нулевого байта. Плюсовые строки позволяют хранить в себе такие имена.

ни одна из функций для работы со строками с ней не справится

Все методы std::string спокойно с ней справляются.

Manhunt ★★★★★
()
Ответ на: комментарий от staseg

Строка хранит в себе свою длину. По этой причине плюсовые строки иногда бывают быстрее сишных.

То есть если в середине нолик то строка становится непреобразуемой в сишную?

Absurd ★★★
()
Ответ на: комментарий от Manhunt

Все методы std::string спокойно с ней справляются.

Просто пример был из man 7 unix, там сишные строки. Теперь я понял твою мысль.

Все методы std::string спокойно с ней справляются.

Ясно. У меня в функции обработка текста, из файла в общем случае значит тоже может ноль прилететь.

staseg ★★★★★
() автор топика
Ответ на: комментарий от staseg

Это уже какие-то пляски на костылях, а не строка.

Крайне скользкий вопрос. Почему бы не считать костылём обязательный ноль в конце Си-шной строки? Почему бы не считать костылём особую управляющую роль нулевого байта в Си-шных строках?

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

Крайне скользкий вопрос.

Это уже зависит от точки зрения. Если мы в си/++ пытаемся засунуть в char[] ноль в середину - это пляска. Если смотреть более широко, я с тобой согласен. Твой копипаст был о внешних данных, я только что понял, да :)

staseg ★★★★★
() автор топика

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

Absurd ★★★
()

а передавать дополнительный параметр string.end() - не хочется?

Однако, нужно.

Но я не уверен, есть ли гарантия, что std::string обязана хранить завершающий 0.

Есть, однако нет гарантии, что в середине строки нет символов с кодом 0.

Reset ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.