IkaR49
@IkaR49

Можно ли так работать с указателями в C++?

Необходимо из потока считать массив символов, количество которых я не узнаю, пока не завершу считывание.
Я сделал такой финт ушами:
unsigned short int size = -1;
char mark = '#';

char *str = new char [0];

stream.getline(str, size, mark);

В данный момент этот код работает правильно, однако я не уверен, будет ли он всегда так работать? Или это всё-таки неопределённое поведение? Если так делать нельзя, то как стоит поступить в данной ситуации?

Создавать массив размером size не хочется: такое число выбрано просто, как нечто большое.

Ещё один вариант решения, который я вижу: считать сначала все символы без сохранения, получить stream.gcount(), сбросить итератор, объявить массив нужного размера и повторить считывание. Но мне этот способ не нравится, так как символов может быть прочитано действительно много, и в качестве входного потока будет файл на жёстком диске.
  • Вопрос задан
  • 316 просмотров
Решения вопроса 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
new[0] - ведёт к неопределённому поведению указателя при разыменовании.
А если используете new[(unsigned short)-1], то где гарантия, что поток будет короче 65536 символов?
Если работаете с потоком - ищите по возможности алгоритмы потоковой обработки, позволяющие считывать данные посимвольно или фиксированными блоками.
Если будете работать с файлами, то можно предварительно запросить длину файла.
Ответ написан
RiseOfDeath
@RiseOfDeath
Диванный эксперт.
Под линуксом вы гарантированно словите сегфолт. На винде почему-то выход за границы массива не очень беспокоит систему (наверное по тому, что задеть другие программы он не может, а работоспособность конкретной программы личная проблема разработчика), зато вы запросто можете попортить данные своей же программмы, если вдруг случайно ваш "несуществующий" массив "наложится" на какие-нибудь переменные в вашей программе.

Вообще в вашем случае надо читать порционно по N символов в буфер размером не меньше чем N, а потом скидывать их в какой-нибудь std::array
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
kozura
@kozura
финт ушами
в топку!

Вообще, при грамотной реализации, размер данных принято передавать вместе с их получением.
Классический пример:
bool GetData(char* data, int* size);

Длину указателя на строку можно узнать через strlen();

Если чтение из файла, то при загрузке размер файла определяется стандартными методами.
Как пример.

...считать сначала все символы без сохранения..
Не нужно.
Ответ написан
Комментировать
@MiiNiPaa
Можете выделять буфер, скажем в 100 символов. Заполняется, выделяете ещё один и читаете в него, и так далее. В конце высчитываете длину строки, выделяете под ней память, собираете строку из кусочков, освобождаете буферы.

Альтернатива — метод стандартных контейнеров: выделяете немного памяти. Если кончилась, выделяете в 1.5-2 раза больше, копируете уже считанные данные, освобождаете уже ненужную память, продолжаете читать. При необходимости повторить. Или сразу читайте в std::string.
Ответ написан
@monah_tuk
В том варианте, что в посте - строчите из пулемёта в себе в ноги.

В STL есть два способа получить нужное поведение:
ать: www.cplusplus.com/reference/string/string/getline
два: www.cplusplus.com/reference/istream/istream/getline

Оба прекрасно работают со стримами, но первый хочет std:string.

Второй вариант (он же вариант из твоего поста) обычно используется с буфферами фиксированной длинны + чтение в цикле чанками.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы