Здравствуйте, Flamer, Вы писали:
F>Блин, только что проснулся, т.к. как раз понадобилась такая весчь для одной маленькой библиотечки, где, по условию задачи, 30 Кб CRT-runtime тащить низзя... Долго вкуривал в выделенные жирным строчки... И пришел к выводу — браво, маэстро!
Год спал, ещё год курил?
Ты ж сам задачу поставил, в августе 2002...
Не проверял, мог и напутать где-нить, со скобками например
Хотя с if-ами нагляднее конечно, только поставьте else, ибо условия взаимоисключающие, а оптимизациям компилера тут как-то не верят
Здравствуйте Flamer, Вы писали:
F>Итак, задача номер два (посложнее ;) ):
F>Условия:
F>3. Знак числа должен сохраняться.
Гекс со знаком — оу е!
F>4. Возвращаемое значение — либо 0 в случае ошибки, либо часть числа до момента встречи ошибки (например, если строка содержит значение "0xA0jFD", то возвращаемым значением будет число 160
Халява сэр
F>6. Переполнение учитывается (например, вызов hex_atoi("0xFFFFFFFF") выдаст число -1 ).
А "0x123456789" = 0x12345678 или 0x23456789 ?
F>7. Допускается опускание в строке указания системы счисления (то есть, строки "0xBF" и "BF" идентичны).
F>8. Запрещается использовать операторы continue и goto в цикле. F>10. Использование конструкции switch, а также цикла do...while (но не while - его можно) запрещается.
Любим усложнять жизнь?
int hexatoi(const char* str)
{
if(!str) return 0;
int v = 0; // аккумуляторbool n = false; // негативchar c = *(str++); // пригодится
// ожидаем пробелыwhile(c == ' ' || c == '\t') c = *(str++);
if(!c) return 0;
// ожидаем знак
// на мой взгляд, так эффективнее, чем громоздить n = (...) ? (...) : (...)if(c == '-') { n = true; c = *(str++); }
else if(c == '+') c = *(str++);
if(!c) return 0; // В принципе, эту проверку можно опустить. Но она быстрая, облегчит жизнь маломало
// ожидаем префикс
// а если это просто 0, то и бог с ним. Не жалкоif(
c == '0' &&
(((c = *(str++)) == 'x') || (c == 'X'))
) c = *(str++);
// ожидаем цифры
// кто не верит оптимизатору, пусть напишет 55 вместо 'A'-10...while(
(с >= '0' && c <= 'f') && // оптимизирующая проверка - для быстрого отсечения неправильных символов
( // повторные проверки c>='0',c<='f' оставлены "для наглядности" (или если убрать оптимизирующую)
(c >= '0' && c <= '9') && (v <<= 4, v += (c - '0' ), true) ||
(c >= 'A' && c <= 'F') && (v <<= 4, v += (c - ('A' - 10)), true) ||
(c >= 'a' && c <= 'f') && (v <<= 4, v += (c - ('a' - 10)), true)
)
) c = *(str++);
return n ? -v : v;
}
Здравствуйте, Кодт, Вы писали:
К>О! Новая задачка. Представьте себе, что для различения используется не префикс, а суффикс (b/inary,d/ecimal,h/ex).
а где ответы? тихо как-то...
можно я лишь алгоритм?
— конвертируем строку в число, используя максимально возможную базу (hex в данном случае) [база1]
— попутно отмечаем, цифры каких баз встретились (максимум)
— когда доходим до последнего символа [база2] — проверяем, все ли цифры, нам встретившиеся, соответствуют базе2
— теперь вместо строки разбираем число:
извлекаем цифру из временного результата с помощью базы1 [ digit = temp_result % base1 ]
добавляем цифру к результату с помощью базы2 [ result += digit * pow(base2, index) ]
мне просто интересно знать: правильные ли у мня мысли
SD>- конвертируем строку в число, используя максимально возможную базу (hex в данном случае) [база1] SD>- попутно отмечаем, цифры каких баз встретились (максимум) SD>- когда доходим до последнего символа [база2] — проверяем, все ли цифры, нам встретившиеся, соответствуют базе2 SD>- теперь вместо строки разбираем число: SD>
SD>извлекаем цифру из временного результата с помощью базы1 [ digit = temp_result % base1 ] SD>добавляем цифру к результату с помощью базы2 [ result += digit * pow(base2, index) ] SD>
Так на каком-нибудь длинном binary можно и переполнение получить. Надо ещё смотреть на длину пропарсенной строки, если она превосходит порог — понижать базу1, попутно пересчтывая число.
... << RSDN@Work 1.1.3 stable >>
Pink Floyd — Wearing The Inside Out
Standarts are great, everyone should have one!
Написать функцию, которая конвертирует строку (char*), содержащую число в шестнадцатеричном представлении (HEX) в число (int), то есть реализацию atoi для чисел в шестнадцатеричной системе счисления. Прототип функции:
int hex_atoi(const char* hex_string);
Условия:
0. Язык программирования — С/С++.
1. Запрещается пользоваться любыми библиотечными функциями (типа strlen и пр.), а также сторонними классами и иже с ними. В двух словах, задача должна решаться встроенными средствами языка С/С++.
2. Пробельные символы в начале строки (пробел и символ табуляции — \t) опускаются.
3. Знак числа должен сохраняться.
4. Возвращаемое значение — либо 0 в случае ошибки, либо часть числа до момента встречи ошибки (например, если строка содержит значение "0xA0jFD", то возвращаемым значением будет число 160
5. Передаваемая строка содержит числа в шестнадцатеричном формате.
6. Переполнение учитывается (например, вызов hex_atoi("0xFFFFFFFF") выдаст число -1 ).
7. Допускается опускание в строке указания системы счисления (то есть, строки "0xBF" и "BF" идентичны).
8. Запрещается использовать операторы continue и goto в цикле.
9. Количество вспомогательных переменных ограничено тремя.
10. Использование конструкции switch, а также цикла do...while (но не while - его можно) запрещается.
Здравствуйте Flamer, Вы писали:
F>Итак, задача номер два (посложнее ):
Вопросик можно А чем она посложнее ? Ну у числа другое основание и все тут.
Для Oct было бы не 16 или 10, а 8. И просто ограничения на символы от 0 до 7.
Здравствуйте Vampire, Вы писали:
V>Здравствуйте Flamer, Вы писали:
F>>Итак, задача номер два (посложнее ):
V>Вопросик можно А чем она посложнее ? Ну у числа другое основание и все тут. V>Для Oct было бы не 16 или 10, а 8. И просто ограничения на символы от 0 до 7. V>
Ну так посложнее же Пусть немножко, но все-же... Обороты надо набирать постепенно
Здравствуйте Flamer, Вы писали:
F>Здравствуйте Vampire, Вы писали:
V>>Здравствуйте Flamer, Вы писали:
F>>>Итак, задача номер два (посложнее ):
V>>Вопросик можно А чем она посложнее ? Ну у числа другое основание и все тут. V>>Для Oct было бы не 16 или 10, а 8. И просто ограничения на символы от 0 до 7. V>>
F>Ну так посложнее же Пусть немножко, но все-же... Обороты надо набирать постепенно
Ну тогда вот чисто мат. задачка.
Конвертор чисел по любому основанию.
Это значит не только 2 8 10 16, но и любое другое типа 12 и т.п.
Здравствуйте Flamer, Вы писали:
F>Итак, задача номер два (посложнее ):
F>Задача:
F>Написать функцию, которая конвертирует строку (char*), содержащую число в шестнадцатеричном представлении (HEX) в число (int), то есть реализацию atoi для чисел в шестнадцатеричной системе счисления. Прототип функции: F>Условия: F>0. Язык программирования — С/С++. F>1. Запрещается пользоваться любыми библиотечными функциями (типа strlen и пр.), а также сторонними классами и иже с ними. В двух словах, задача должна решаться встроенными средствами языка С/С++. F>2. Пробельные символы в начале строки (пробел и символ табуляции — \t) опускаются. F>3. Знак числа должен сохраняться. F>4. Возвращаемое значение — либо 0 в случае ошибки, либо часть числа до момента встречи ошибки (например, если строка содержит значение "0xA0jFD", то возвращаемым значением будет число 160 F>5. Передаваемая строка содержит числа в шестнадцатеричном формате. F>6. Переполнение учитывается (например, вызов hex_atoi("0xFFFFFFFF") выдаст число -1 ). F>7. Допускается опускание в строке указания системы счисления (то есть, строки "0xBF" и "BF" идентичны). F>8. Запрещается использовать операторы continue и goto в цикле. F>9. Количество вспомогательных переменных ограничено тремя. F>10. Использование конструкции switch, а также цикла do...while (но не while - его можно) запрещается.
почему бы не написать сразу универсальную функцию определяюшюю тип числа по началу записи
0x — HEX
0 — OCT
остальное DEC
соответственно проверяя коректность символов (т.е 0xa => 10, а 0a => 0, a => 0)
условия оставим теже, но немного довавим
1. сделать две функции
а. signed long sig_uni_atoi(const char *str);
учитывеет знак, знаковый бит. при переролнении возврашает 0, (т.е 2147483648 => 0)
б. unsigned long usig_uni_atoi(const char *str);
не учитывеет знак, знаковый бит.
(можно дополнить/исправить)
Блин, только что проснулся, т.к. как раз понадобилась такая весчь для одной маленькой библиотечки, где, по условию задачи, 30 Кб CRT-runtime тащить низзя... Долго вкуривал в выделенные жирным строчки... И пришел к выводу — браво, маэстро!
К>
[]
К> ( // повторные проверки c>='0',c<='f' оставлены "для наглядности"
// (или если убрать оптимизирующую)К> (c >= '0' && c <= '9') && (v <<= 4, v += (c - '0' ), true) ||
К> (c >= 'A' && c <= 'F') && (v <<= 4, v += (c - ('A' - 10)), true) ||
К> (c >= 'a' && c <= 'f') && (v <<= 4, v += (c - ('a' - 10)), true)
К> )
К> ) c = *(str++);
К> return n ? -v : v;
К>}
К>
Здравствуйте, Flamer, Вы писали:
F>Здравствуйте, Кодт, Вы писали:
F>[]
F>Блин, только что проснулся, т.к. как раз понадобилась такая весчь для одной маленькой библиотечки, где, по условию задачи, 30 Кб CRT-runtime тащить низзя... Долго вкуривал в выделенные жирным строчки... И пришел к выводу — браво, маэстро!
Здравствуйте, MaximE, Вы писали:
ME>Chez wrote:
ME>А чем strtol не устраивает?
Это не то 1) если префикса 0x нет — рассматривает число как десятичное
5. Передаваемая строка содержит числа в шестнадцатеричном формате.
2) возвращает другие результаты в случае ошибок, а надо:
4. Возвращаемое значение — либо 0 в случае ошибки, либо часть числа до момента встречи ошибки (например, если строка содержит значение "0xA0jFD", то возвращаемым значением будет число 160
3) но самое главное, что задание было поставлено просто как разминка для мозгов !
1. Запрещается пользоваться любыми библиотечными функциями (типа strlen и пр.), а также сторонними классами и иже с ними. В двух словах, задача должна решаться встроенными средствами языка С/С++.
...
8. Запрещается использовать операторы continue и goto в цикле.
9. Количество вспомогательных переменных ограничено тремя.
10. Использование конструкции switch, а также цикла do...while (но не while — его можно) запрещается.
Chez wrote:
> ME>А чем strtol не устраивает? > Это не то > 1) если префикса 0x нет — рассматривает число как десятичное
Представь, что число идет тебе из командной строки. Как ты различишь без префикса decimal от hex?
> 2) возвращает другие результаты в случае ошибок, а надо: >
> 4. Возвращаемое значение — либо 0 в случае ошибки, либо часть числа до момента встречи ошибки (например, если строка содержит значение "0xA0jFD", то возвращаемым значением будет число 160
> 1. Запрещается пользоваться любыми библиотечными функциями (типа strlen и пр.), а также сторонними классами и иже с ними. В двух словах, задача должна решаться встроенными средствами языка С/С++.
> ...
> 8. Запрещается использовать операторы continue и goto в цикле.
> 9. Количество вспомогательных переменных ограничено тремя.
> 10. Использование конструкции switch, а также цикла do...while (но не while — его можно) запрещается.
Здравствуйте, MaximE, Вы писали:
ME>Chez wrote:
>> ME>А чем strtol не устраивает? >> Это не то >> 1) если префикса 0x нет — рассматривает число как десятичное ME>Представь, что число идет тебе из командной строки. Как ты различишь без префикса decimal от hex?
Это понятно.
Но функция, которую я написал, принимает только hex, по условию. И если нет 0x — то рассматривает число как hex, в отличие от strtol.
>> 3) но самое главное, что задание было поставлено просто как разминка для мозгов ! >>
>> 1. Запрещается пользоваться любыми библиотечными функциями (типа strlen и пр.), а также сторонними классами и иже с ними. В двух словах, задача должна решаться встроенными средствами языка С/С++.
>> ...
>> 8. Запрещается использовать операторы continue и goto в цикле.
>> 9. Количество вспомогательных переменных ограничено тремя.
>> 10. Использование конструкции switch, а также цикла do...while (но не while — его можно) запрещается.
строчка "1bC", попав на вход этой функции породит ответ 1 + 11 + 12 = 24, а вовсе и не то, что надо
Всё-таки условия конкурса не совсем удачные. Я бы лучше читабельности и надёжности хотел, а не ребусов на C++
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, DK3981, Вы писали:
SD>>- конвертируем строку в число, используя максимально возможную базу (hex в данном случае) [база1] SD>>- попутно отмечаем, цифры каких баз встретились (максимум) SD>>- когда доходим до последнего символа [база2] — проверяем, все ли цифры, нам встретившиеся, соответствуют базе2 SD>>- теперь вместо строки разбираем число: SD>>
SD>>извлекаем цифру из временного результата с помощью базы1 [ digit = temp_result % base1 ] SD>>добавляем цифру к результату с помощью базы2 [ result += digit * pow(base2, index) ] SD>>
DK>Так на каком-нибудь длинном binary можно и переполнение получить. Надо ещё смотреть на длину пропарсенной строки, если она превосходит порог — понижать базу1, попутно пересчтывая число.
Можно и с другого конца начать. Изначально установить базу = 2. Каждый раз, встречая неожиданную цифру, повышать базу. Это произойдёт не более 2 раз, поскольку в условии говорилось про (2,10,16). Или не более 3, если добавить восьмеричную.
Ну а если уж на текущей маленькой базе получили переполнение, то с нерассмотренными ещё большими — тем более будет.