Павел Китьян: >Ведь арифметика указателей работает правильно
Арифметика указателей зависит от типа самого указателя который указывается явно. Возьмите массив интов присвойте указатель на чар адрес нулевого элемента, прибавьте два и конвертируйте обратно в указатель на инт. Явно не адрес второго элемента получите (Получите UB но это тема другово разговора).
Если бы размер данных хранился где-нибудь, то приведения массива указателей на класс к массиву указателей на базовый класс не приводило бы к проблемам.
И что характерно, полностью безопасными программы это не сделало. Так как если ты знаешь максимальную длину своей строки, ты можешь поставить там ноль на всякий случай, что большинство программистов и делало.
Главное применение эти функции находят в случаях если строку нельзя изменять и для специфических задач вроде копирования первых 5 символов или всех доступных если их меньше.
Ещё есть *_s функции. У которых пользы нет вообще.
vilgeforce: Уж тогда IsBadStringPtr. Иначе замучаешься на каждый последовательный байт проверять можно ли к нему обращаться.
И это же виндовс онли. В Линуксе ЕМНИМ можно проверять результат write или напрямую смотреть какая память выделена процессу, на абстрактной железке таково способа нет.
Так что или пишем обвязку для каждой платформы документируя что для всех платформ кроме А Б и В проверка не производится или забиваем на это и либо заставляем программиста работать или пишем не кроссплатформенно.
Всё равно в общем случае эта проблема неразрешима.
Я считаю, если реализуешь функцию стандартной библиотеки, надо обеспечит такие же гарантии при таких же предусловиях. А функция из сишной библиотеки требует чтобы строка содержала завершающий ноль (иначе это не строка по определению). Потом можно подумать о большем.
Для доказательства хватает школьной математики:
1) Если число n делится нацело на k, оно также делится на m=n/k (Базовые свойства деления)
2) Из этого следует, что каждый делитель из множества чисел меньше некого числа x, такого, что x·x = n, имеет парный ему уникальный делитель из множества чисел больше x. И наоборот
2.1) Соответственно проверяя число 100 на простоту, 25 как делитель проверять не нужно: мы уже проверили 4 до этого и убедились что число не простое.
3) Число x — квадратный корень из n.
> Иначе вы затруднитесь обяснять преподавателю то, что написали.
Кстати да. Очень важно в таких случаях объяснять использование чего ожидается. А то получишь шаблонный код использующий С++11, а потом будешь удивляться почему TurboC++ его не прожёвывает.
P.S. Мне вот очень хочется решить вторую задачу используя паттерн Chain of Responsibility.
Если есть желание выделять её из потока _неконструктивной_ критики, то можно. Важно разбираться в том, какой совет дельный, какой вредный, а какой вызван неприязнью любого отличающегося стиля программирования.
В общем, как на большинстве форумов. Правда есть очень большой риск получить ушат помоев вместо критики. Так что постите на незнакомых бордах исключительно на свой риск.
Проходитесь по последовательности символов, разрешённые символы добавляете к строке-результату, остальные пропускаете. Нюансы зависят уже от выбранного ЯП.
Я и не предлагал использовать MD5. Хотя даже в этом случае пользы от нахождения коллизий злоумышленнику может быть только одна: не дать в будущем загрузить какой-то конкретный файл.
Длину я использовал для предварительной проверки файла на нахождение в базе, ещё до его фактической загрузки и вычисления хэша. В общем случае лучше это место потратить на более длинный хэш.
Не везде, переедете на другой компилятор или обновите его и всё.