- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
void bvnr(char *text)
{
for(int f=0; f<=strlen(text); f++)
{
switch(text[f])
{
case 'Q' : text[f] = 'q' ; break;
case 'W' : text[f] = 'w' ; break;
case 'E' : text[f] = 'e' ; break;
case 'R' : text[f] = 'r' ; break;
case 'T' : text[f] = 't' ; break;
case 'Y' : text[f] = 'y' ; break;
case 'U' : text[f] = 'u' ; break;
case 'I' : text[f] = 'i' ; break;
case 'O' : text[f] = 'o' ; break;
case 'P' : text[f] = 'p' ; break;
case 'A' : text[f] = 'a' ; break;
case 'S' : text[f] = 's' ; break;
case 'D' : text[f] = 'd' ; break;
case 'F' : text[f] = 'f' ; break;
case 'G' : text[f] = 'g' ; break;
case 'H' : text[f] = 'h' ; break;
case 'J' : text[f] = 'j' ; break;
case 'K' : text[f] = 'k' ; break;
case 'L' : text[f] = 'l' ; break;
case 'Z' : text[f] = 'z' ; break;
case 'X' : text[f] = 'x' ; break;
case 'C' : text[f] = 'c' ; break;
case 'V' : text[f] = 'v' ; break;
case 'B' : text[f] = 'b' ; break;
case 'N' : text[f] = 'n' ; break;
case 'M' : text[f] = 'm' ; break;
)
}
}
Перевод текста в нижний регистр. Можно пугать детей на ночь))
Забавно ещё, что не по алфавиту, а по клавиатурной раскладке ;)
Ну, и конечно, баг в условии выхода из цикла. Не говоря уже о вызове strlen() каждую итерацию.
я думаю, компилятор тут соптимизирует и вывед вызов за цикл. или для этого нужно иметь const char* text наверное?
Если я правильно вас понял, и вы именно из-за этого называете тут всех "пониёбами" и "говнокодерами", то вы - убожество.
Если пишешь программы, то не надо расчитывать на портируемость на столь экзотические архитекторы, т.к. такой подход сильно ухудшит ваш код не принеся тем самым никакой пользы, в то время как. на тех самых архитектурах никогда использоваться не будет. Например были компьютеры, где байт был равен 6 битам, дак что теперь, расчитывать на то, что если используется char, то он в положительную сторону больше 31 не отсчитывает? Портируемой на столь экзотические архитектуры надо писать только в том случае, если программа предназначается для того, чтобы там работать. И если уж на то пошло, если пишешь портируемой на такие архитектуры, было бы неплохо ещё проверить (отладить) как-нибудь образом, насколько работоспособен твой код на таком компьютере, что в свою очередь повлечёт исправление таких функций, за которые вы тут всех пониёбами называете.
Вам люди говорят про стандартные случаи, т.к. тут нигде не указано, что программа писана под какой-нибудь там TMS320VC31.
Менее экзотическим случаем, как тут уже говорили, является не ansi кодирока.
Так что хватит придумывать отговорки, тут выносят вердикт говнокод или нет. Все костыли, имитирующие то что есть в стандартных либах - говнокод.
И не надо отмазываться, типа экзотика и т.п. Если бы turdman добавил, условия при которых его код работает, то можно было бы поспорить.
Попробую ответить по тому, что я мутно понял из вашего поста:
1.) Каким именно стандартам и в каком месте какой именно код не соотвествует?
2.) Вообще не понял про какие отговорки речь. Отговорки я вижу с вашей стороны. Обосрали всех и вся вокруг, а потом придумываете какие-то нелепые "отговорки" чтобы как-то доказать, что это было обоснованно.
3.) Лично я хожу на данный ресурс не для того, чтобы выносить вердикт "говнокод или нет", а чтобы во-первых развлечься прочитав код на основной странице, а во-вторых если повезёт, то узнать что-то новое для себя в коммертариях.
4.) По поводу велосипедов (или как вы их назвали "костыли"). Я вот ради эксперимента переписывал помню bcmp(), дак в моих задачах моя реализация работала раза в 3-4 быстрее, чем стандартная. А ведь в некоторых из них сравнение строк у меня составляло ощутимый процент общей нагрузки приложения. Я вообще не считаю априори, что велосипеды - говнокод. Я считаю, что если они вносят какую-то пользу, то они вполне могут быть обоснованы, тут уже стоит вопрос в том, как расставлял приоритеты в стиле программирования.
5.) Я не отмазываюсь, я действительно считаю системы, где байт не равен октету крайне редкой экзотикой, поддерживать которую при написании программ для x86/amd64/sparc/sparc64/etc абсолютно невыгодно.
5.) Про какие условия в коде turdman-а речь? И прошу заметить, что у него описан кусок кода, а не функция целиком, но тем ни менее мне интересно узнать, что конкретно в данном коде с вашей точки зрения не так.
Читали рассуждения Гегеля "Кто мыслит абстрактно?". Если не читали, очень советую прочесть (там всего 2-3 странички). Дак вот вы говорите какие-то абсолютно абстрактные вещи. Другими словами, прошу высказавать хоть какие-нибудь конкретные факты в подобных диалогах.
В посте turdman предполагается, что char в кодирвке, в которой финт "|= 0x20" прокатывает.
Я против использования таких костылей, что не понятно?
Или для управляющего протокола FTP, там тоже совместимая кодировка... Да и почти в каком-либо угодно другом демоне тоже кодировка совместима. Не понимаю проблему.
Я дак занимаюсь сетевыми задачами и вижу намного больше задач, где никаких проблем нет, нежели наоборот.
Хотя, конечно, при особом желании можно извратнутся и ускорить процесс для длинных строк и делать OR сразу по 0x20202020, а уже хвост по 0x20. Но это уже для какой задачи как выгоднее и у кого какой стиль программирования
Вот например процерка на чётность "(i/2)*2 == i" - это говнокод. Т.к. существует возможность получить абсолютно эквивалентный результат намного более оптимальным и наглядным способом. А тот способ upcase-а - пока не обосновано что говнокод, т.к. никто пока не доказал, что нет такой сферы применения данного кода, где он является приемлемым.
Типа назовите системы где это не заработает.. Потом появились в широком распространении x64, всем кто использовал тот говнокод(и соответственно, нужны были большие объёмы памяти), начали дружно искать места где нужно менять на size_t и т.п., а где по формату нельзя просто заменить на size_t, так как в формате файла жёсткие int'ы.
Если на данный момент нет ни одной(широкораспрастранённой) системы, где этот говнокод не будет работать, это не значит, что они не появится в ближайшем будущем.
Вот чем, предложенный ранее ctype::tolower плох? почему вас тянет на говнецо?
2.) С массивами абсолютно другая ситуация, т.к. объёмы используемой памяти всё-таки меняются.
3.) Чего это вы на личности так грубовато переходите. Я ниразу не сказал, что это приемлемый код.
4.) По поводу ctype::tolower, как показывает грубый опыт:
Время выполнения с ctype::tolower
Время выполнения с кодом от turdman:
К тому же, хоть это мало меняет, но я, честно сказать, забыл, что мы обсуждаем c++ вариант, поэтому ожидал Сишный код.
Если требуется, чтобы данный код работал супер быстро, нужно оптимизировать под конкретное железо, оси и т.п. В этом случае я допускаю применение варианта turdman, но только в том случае, если есть увереность что он работает правильно.
Мы ведь здесь не про оптимизацию говорим? Зачем переводить тему в более выгодное для вашей позиции русло?
Кстате, интересно посмотреть, что в g++(в либах) делается.
Посмотрев в вариант от MSVC 2008, у меня есть догадка почему вариант turdman быстрее, смотрим:
1027583F cmp dword ptr [c],41h
10275843 jl tolower+26h (10275856h)
10275845 cmp dword ptr [c],5Ah
10275849 jg tolower+26h (10275856h)
1027584B mov eax,dword ptr [c]
1027584E add eax,20h
Ясно?
Я допускаю что вариант turdman может непосредственно использоваться в либах - но либы то знают(часто) для какой они платформы.
if (__locale_changed == 0)
{
return __ascii_towlower(c);
}
else
{
return _tolower_l(c, NULL);
}
Однако:
1.) Да, я прекрасно знаю, от чего зависит скорость выполнения. ;)
2.) Я не перевожу диалог в другое русло. Я просто ответил, чем может быть плох "ctype::tolower".
3.) По поводу "знают для какой они платформы". Я уже кажется писал про свой эксперимент с bcmp(). То было проведено на linux, где "стандартная библиотека" ещё достаточно шустрая. А вот на FreeBSD разница составила в 7 раз, если я правильно помню.
Я понимаю вашу позицию. Я с ней согласен в особенности, если говорить о коммерческих проектах (где очень важна скорость разработки). Однако я считаю, что программист вполне имеет право (если он достаточно дотошный) делать любой велосипед, если это имеет какое-то обоснование (например значительный прирост производительности).
И я, например, писал код, где я расчитывал как будут работать на велосипеды для 4 архитектур. И считаю, что получилось вполне неплохо, тем более что, при компиляции идёт проверка этих функций, и если видно, что они хуже стандартных или соизмеримы, то выбираются стандартные функции (ну и естественно, их можно флагами отрубить вручную при компиляции). Из-за чего я это делал? Из-за того, что моей целью было сделать хорошо быстродействующий вариант программы.
А по поводу того, как это делается в g++, если хотите, могу дать ssh-доступ к машине с g++ и objdump (для дизассембляции) ;)
Я понимаю вашу позицию. Повторюсь, если turdman сделал бы небольшую сноску, о том где это будет работать, у меня небыло бы никаких вопросов/возражений. Конечно, я понимаю что большинство здесь просто стебается, но всё же было бы неплохой традицией, в спорах находить лучшие варианты, а не просто обсирать сабжи.
Я за использование стандартных(тут я допускаю использование нормальных либ, которые идут на разных платформах типа QT) либ.
Помню недавно пришлось исправлять/дополнять один известный open-source проект, чтобы он нормально заработал в windows, после того как один из разработчиков использовал функции которые были только у g++, в общем не очень приятно возится с таким калом.
По поводу дизассембляции, это просто очень удобный способ посмотреть "что за хрень натворил компилятор" :)
P.S.: Кстати, основной мой грех пожалуй в том, что я пишу не под c89 или какой-то чисто сишный стандарт, а под gnu89. Т.е. я привык использовать GNU-расширения :(
Я этим тоже занимаюсь, был приятно удивлён, когда MSVC сам развернул цикл(сделал достаточно длинной итерацию) и использовал sse. Причём порядок операций на первый взгляд был случайным, а оказалось, очень даже оптимизирован под конвееры процессора.
http://www.opennet.ru/man.shtml?topic=tolower&category=3
Предложите вариант использования.
А по поводу ctype::tolower я написал в посте выше.
Я на 90% уверен, что использую стандартные функции ещё можем получить бонус - например если локаль русская, автоматом перевод русских заглавных букв(не проверял, может это не так)
А по поводу tolower, вы его в цикле собираетесь запускать или как? Хотя я так понял, вы C++-ник, поэтому вряд ли вам будет интересно писать вариант кода для PureC. Однако, к сожелению, tolower надо использовать в цикле. :(
(дальше, не в тему)
В чём преимущество использования C? Разве что, для какой-нибудь железки нет компилятора C++.
Аргумент быстрее, не очень состоятельный, ведь на C++ не обязательно использовать ООП, виртуальные функции и т.п. То есть я имею ввиду, какие сейчас аргументы в пользу использования чистого C(действительно интересно, может изучу его для разностороннего взгляда)?
Может сейчас скажу холиварные слова, но разве у C сильно синтаксис отличается? Да, понятно классы, шаблоны и т.п. Но ведь всё-таки процентов 60 кода это именно алгоритмы, а не ООП и т.п.
Я использую Си из двух религиозных соображений:
1.) Ради дополнительной близости к низкоуровневым языкам (люблю красивый код "с точки зрения компьютера");
2.) Мне крайне противно как используют ООП современные C++ "программисты", поэтому в знак протеста я пытаюсь стоять со стороны лагеря PureC.
Я сам придерживаюсь той же позиции, что C++ - более качественный язык, чем PureC, однако тот же lowcase строки используя ctype::tolower соотвествуя парадигме c++ работает ощутимо медленее, чем подход PureC. Да и вообще я привык думать, что плюсойды любят стрелять по мухам из базуки. И просто чтобы не заразиться той же болезнью я пишу на Си :).
К тому же, C++ сложнее, программы его компилятся порядком дольше и отлаживать лично мне ООП код сложнее [склад ума у меня такой :(, похоже]
Однако по поводу данного поста прошу заметить две вещи, я сейчас не очень адекватен и я ни коем образом не пытаюсь разжигать холивар, просто хочу дать понять, почему я остался на таком динозавре как C89
Если писать на си в объектном стиле, то ничуть не сложнее.
PS. Это другой комментарий.
ООП это парадигма, а не синтаксис. Поэтому вопрос "ООПить руками" имеет мало смысла с вашей стороны.
хотелось бы увидеть в новом стандарте С, перегрузку функций и шаблоны как в С++, это еще сильнее увеличит сферическое N...
щито?!
> к каждой функции нужно дописать имя объекта, что сделает имена функций очень длинными..
и что? ты программист или вебкилл? именна нихрена не длинные, нисколько не мешает. Stream_Close(obj) vs. obj->Close() тут разницу увидит только розовый дельфятник какой-нибудь, кому только рюшечки подавай.
> если нужно присвоить объект вызывается memcpy
это не присваивание, а копирование. при присваивании в объектом си тупо присваивается ссылка + рефкаунт. копирование в большинстве случаев нах не нужно.
это сделает более удобным добавление функционала при проектировании сверху вниз...
> Stream_Close(obj) vs. obj->Close()
слишком простые примеры...
с перегрузкой было бы симпатичнеее
Close( Stream* stream );
Close( Other* other );
> копирование в большинстве случаев нах не нужно.
да, но остается меньшинство случаев в котором это нужно...
Close( Stream* stream );
Close( Other* other );
перегрузка в большинстве случаев - лишний сахар чтобы сократить код на два слова...
в обж-с используют CloseWithStream - и никто не умер - тем более - становится более очевидным, что именно вызывается (а в говно-с++-подобном ООП бывает много неоднозначных случаев, связанных с выведенеием нужной сигнатуры (нап. при наследовании) > вызовом не того перегруженного метода).
обж-с говно чуть более чем полностью, к айфонам и макоси сильно притянуто за уши...
ну и как бы по соглашению обж-с первый параметр не может быть именован, поэтому имя первого параметра входит в имя метода для наглядности...
все неоднозначные случаи в С++ это error (или warning) на этапе компиляции...
ну а ты говнокодер чуть более чем полностью, и что теперь?
Си поддерживает модульную парадигму, и она там как-бы дэфакто.
Вместо класса у Вас модуль, вместо объекта -- хендлеры ага
> Си поддерживает модульную парадигму, и она там как-бы дэфакто.
ну почитай, что такой семантика и что такое синтаксис. ну да, на си в объектном стиле писать сложнее, чем на с++, но не насктолько, насколько хотят товарищи типа пушкова это представить. гном например сделан на "объектном си", правда, это не лучшая реализация
как я уже сказал, раии с++ с постоянным копированием туда-обратно я бы не советовал совать во все щели... в объектном си присваивание это: obj1 = obj2; REF(obj1); Всё.
> хочешь создать - вызови функцию инициализации
new Object() vs. Object_Create(). Ой бида, бида.
> хочешь удалить - вызови функцию закрытия
delete obj; vs. Object_Delete(obj);
ой бида, бида.
> иначе от такого стиля нет профита...
ну правлиьно, "самый-самый ООП" нужен только когда нужны обобщения (в с++ это зовётся виртуальными функциями). за остальным у "ООПа" нет особого профита. и ведь всё это не так часто нужно, поэтому и внимательным нужно быть совсем не всюду.
int main()
{
Object object;
Object_Init(&object);
....
if ( some == some_other)
{
Object_Close( & object );
return 0;
}
if (some_other)
{
Object_Close(&object);
return 0;
}
Object_Close( &object );
return 0;
}
большей части этой функции не будет в С++.
насчет присваивания - указатель катит не везде, иногда всетаки нужно создать копию... если ты делал динамические строки в С, то должен был столкнуться...
у меня оно будет так:
кто тебе это сказал? у тебя с++ головного мозга. на деле программисту языка высокого уровня как бы должно быть без разницы, где хранится объект. хоть в регистре, блядь.
это всё хорошо, но к обсуждаемой теме - ООП - это не имеет никакого отношения.
ты щас какую-то бессвязную херь спорол.
Про деструктор слышали ? А про то, что он вызывается автоматически при выходе из области видимости ? Не надо путать объекты, время жизни которых управляется руками с объектами на стеке.
с++ крут, в стеке он при выходе за область видимости деструктится, а в куче - нет
молодец!
для кучи есть auto_ptr, или любой другой объект который в конструкторе примет указатель, а в деструкторе удалит его...
Конечно объективное ценнее, но хоть так..
Холивар конечно начинать не хочется.
всё от конкретной задачи зависит.
Лучше назови хотя бы один стандарт Си, где sizeof(char) больше единицы.
Мой.
http://vik100.boom.ru/progulka.html
Я бы даже сказал, нетрадиционный.
А теперь перечитай ту срань которую спросил
Если вдруг не хотите верить моим документациям, то давайте воспользуемся внешним источником. Например, прошу ознакомиться с:
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
Страница 92. "in bytes"...
И я то прекрасно знаю, что я написал, вы лучше перепрочтите из-за чего я это написал.
"The sizeof operator yields the size (in bytes) of its operand"
Дальше, ты идёшь и протираешь глаза:
"When applied to an operand that has type char, unsigned char, or signed char,
(or a qualified version thereof) the result is 1"
ок, прочитал, и что ты теперь думаешь? что char это восемь бит?
дальше делаешь промывку глаз ещё раз, ибо в том же документе:
"byte
addressable unit of data storage large enough to hold any member of the basic character
set of the execution environment
NOTE 2 A byte is composed of a contiguous sequence of bits, the number of which is implementationdefined.
The least significant bit is called the low-order bit; the most significant bit is called the high-order
bit."
Всё твой мир рухнул..
Итак, твой вопрос: "Лучше назови хотя бы один стандарт Си, где sizeof(char) больше единицы."
Ещё раз читаешь, и понимаешь что ляпнул тупость:
"When applied to an operand that has type char, unsigned char, or signed char,
(or a qualified version thereof) the result is 1"
1.) Я никогда не говорил, что sizeof(char) будет когда-либо отличаться от "1". Более того, я как раз доказываю, что он всегда равен единице в стандартах C/C++. Поэтому от человека, который хотел сказать обратное, я потребовал показать хотя бы один стандарт. Другими словами, начало вашего поста вообще не в тему.
2.) Я выше писал, что байт может быть 6-битным к примеру. Но так же знаю и другие системы - 9 бит, 32 бита и т.п. Если вы и это не прочли и опять пытаетесь мне что-то доказать, что в определение байта не входит "8 бит", то вы опять немножно не в тему.
3.) Вы хоть раз сформулируйте прямо про какую глупость вы говорите. А то всё ходите вокруг да около, а пока что выясняется что вы просто не внимательно читали что я писал.
Просто возьмите и почитайте что я написал и перестанье пороть всякую лабуду.
Где я пытался сказать обратное?
Я поясню причину своей критики кода turdman. Как одну из целей данного сайта(может это расходится с мнением его создателей), я вижу высмеиванием жутко костыльного кода(как один из вариантов) и выяснения в ходе обсуждения, какой код является более приемлемым, так сказать профит для всех читающих(и посмеяться, и немного опыта/знаний: что хорошо, а что плохо).
Если кто-то предлагает код, который ещё более костыльный(пусть даже в специфических случаях) чем сабжевый, то его(код, саму идею) надо тоже высмеивать и карать, чтобы неопытные программисты потом не использовали эти костыли в реальных программах .
Зачем вообще было это спрашивать? Весело заявить, что sizeof(char) везде 1, в том случае если бы я сказал что-то неправильно - поэтому и срань, подосрань, подъебон и т.п.? Это вообще к теме мало относится, по-этому ещё раз - срань.
" И, кстати, здравых и конкретных аргументов с доказательством против кода turdman-а я тоже не увидел."
В этом случае перечитайте вы всё.
Может вам разжевать? Где в стандарте написано, что 'A'^'a'==0x20. Понятное дело что есть реализации, где это справедливо, пусть даже такая ситуация в большинстве реализаций. Но раз нет в стандарте - говнокод.
1.) Про "sizeof(char)" я заговорил из-за "нет, ты просто говнокодер. Кто тебе сказал, что char это один байт?"
2.) По поводу "'A'^'a'" я вам уже ответил за 10 минут до вашего поста.
Извиняюсь, конечно, за эту манеру :)
Ресурс должен знать своих героев!
Компилятор, коем я пользуюсь поддерживает:
и
выполнит функцию beep();.
Тем ни менее, во-первых, лично мой компилятор не понимает что такое "short char" и "long char" и, AFAIK, не должен:
во-вторых как "sizeof(!a)" относится к нашему диалогу?
wchar_t a;
может скинуться в деревенский туалет.
#define true false
#define int char
или что-нибудь в этом роде, а потом скажите, что половина кода в мире - говнокод, т.к. не расчитано на такой случай. ;)
char a;
printf("sizeof=%d",sizeof(!a));
а вот это, да:
char a;
printf("sizeof=%d",sizeof(~a));
Курим RTTI:
char a;
printf("%s",typeid(a).name());
output - char
и
char a;
printf("%s",typeid(!a).name());
output - bool (у чувак может bool не как один char по размеру)
и наконец
char a;
printf("%s",typeid(~a).name());
output - int
, короче, тот крендель у которого beep, пусть выведет
char a;
printf("%s",typeid(!a).name());
Короче, высеркодер, а ну ка бипни этим
char a;
if(sizeof(a)>1)
beep();
или этим
char a;
a=!a;
if(sizeof(a)>1)
beep();
Лично я вообще не понял к чему был тот "прикол" с beep().
output - int
Оооо. Я не знал. Вы мне открыли Америку.
А есть ещё операции, что "портят" тип, кроме ~ ?
Побитовый сдвиг например.
В данных случаях происходит продвижение целочисленного типа.
с++ - язык взаимоисключающих параграфов: не достаточно низкоуровневый, не достаточно высокоуровневый. ни то, ни сё.
Я думаю, что любой более ли менее квалифицированный программист хорошо знает что есть "Си", "C++" и "ассемблер" и вряд ли нужно писать что хорошо, а что плохо.... А последние хрен знает сколько лет, меня эти диалоги успели ну настолько осточертеть, что не смотря на свою настройчивость я из принципа пытаюсь не отвечать на холиварные посты. А вы всё строчите и строчите... строчите и строчите... :(
Это относится к множеству веток, а не только к этой.
ну ты больше всех нас тут воспринимаешь всё близко сердцу, я посмотрю. флудишь-то больше всех ты )
У них открылось общество религиозных фанатиков - кидаются на неверных.. скоро будут шахидов с говнобомбами пускать
Школота, а не пора ли в летний лагерь собираться?
for(int f=0; f<=strlen(text); f++);
А вот в Сях... Absolut уже сказал.
и потому строка статическая, ограниченная
а в сях -- сами знаете
в дельфях длиной строки не сделать, потому на нем и не пишут серьезного софта
AnsiString, also called a long string, represents a dynamically allocated string whose maximum length is limited only by available memory.
A long-string variable is a pointer occupying four bytes of memory. When the variable is empty--that is, when it contains a zero-length string--the pointer is nil and the string uses no additional storage. When the variable is nonempty, it points a dynamically allocated block of memory that contains the string value. The eight bytes before the location contain a 32-bit length indicator and a 32-bit reference count. This memory is allocated on the heap, but its management is entirely automatic and requires no user code.
Because long-string variables are pointers, two or more of them can reference the same value without consuming additional memory. The compiler exploits this to conserve resources and execute assignments faster. Whenever a long-string variable is destroyed or assigned a new value, the reference count of the old string (the variable's previous value) is decremented and the reference count of the new value (if there is one) is incremented; if the reference count of a string reaches zero, its memory is deallocated. This process is called reference-counting. When indexing is used to change the value of a single character in a string, a copy of the string is made if--but only if--its reference count is greater than one. This is called copy-on-write semantics.
© Delphi 7 Help