> Тут столкнулся с тривиальной задачей, нужно «пулять» > целочисленные значения по разным ветвям обработки, > тривиальный case в Паскале справился бы на-ура. А вот в > сях... switch - case какой-то слабоватый. Итак, пример на > Паскале ниже и вопрос в том, как это лучше всего > реализовать в С: > Case MyIntegerValue of > 0..15: DoSomthingCool(MyIntegerValue);
> 16, 18, 24: DoNextCoolThing(MyIntegerValue);
> 26..89, 90, 95, 101..170:
> VeryNiceAndCool(MyIntegerValue);
> End; ---
> Здесь паскальный Case во всей своей красе — выбор из > диапазона, из дискретных значений (что возможно и в сяшной > паре switch - case), и в последней строке выбора есть > диапазоны и дискретные значения. Неужели прийдётся строить > if - else?
Да, в С/С++ switch простой, без диапазонов, только на сравнение с константой. В любом случае сложный паскалевский case с диапазоном развернется в такую же проверку. Часто, кстати, используется вариант с поиском по предварительно заполненной таблице.
> Ну а теперь про множества. Это немного соотносится с case. > if MyChar in ['A'..'Z', 'a'..'z'] then DoSomthing — как это > сделать попроще? > Я понимаю, что можно так: > if (((MyChar >= "A") && (MyChar <= "Z"))|((MyChar > >= "a") && (MyChar <= "z"))) > DoSomething(); > но это как-то некрасиво.
Конкретно эта задача - проверка символа на попадание в диапазон a-zA-Z обычно решается с помощью функции isalpha, для чисел - isdigit, плюс еще несколько аналогичных функций, которые, насколько я помню, реализованы не как толпа if, а как поиск по таблице. Про множества в чистом виде - ниже.
> Ну и потяжелее пример с типом «множество»... > Type > TDigit = (zero, one, two, three, four, five, six, seven,
> eight, nine);
> TDigits = Set Of TDigit;
> Var Digits: TDigits;
> Begin
> Digits := [zero..two, four..six];
> Include(Digits, three);
> Digits := Digits + [seven..nine];
> // Ну и в таком духе — операции со множествами.
> End; ---
> Я понимаю, для процессора это всего-навсего возня с битами > в целочисленных значениях. Меня не испугает никакой язык, > если в нём есть операции or, and, xor и прочяя... Но > возможно, не надо изобретать колесо и есть уже что-то в > самом языке?
На уровне, совместимом с классическим С - это честная возня с битами. В С++ для этого есть класс из стандартной библиотеки std::bitset, реализован вполне эффективно.
> Теперь ещё. Была у меня раньше мечта — повозится в ядре > драйвером ;-) Delphi для этого не самый лучший инструмент, > посколько он для этого не предназначен и включает даже в > самую маленькую программу кучу инициализирующего дерьма с > вызовом функций из библиотек пользовательского режима. > Скажу даже, что за C я взялся, тайно движимый «ядерной» > мечтою ;-) Но, наверное, взялся не за тот компилер, а > именно за борландовсий С. И что я вижу — программа, которая > «ничего не делает» — а именно, входит в Main и выходит из > неё, без единого #include занимает 7 с лишним килобайт и > выполняет кучу дерьма пользовательского режима при старте. > С этим можно как-то побороться, или мне нужен другой > компилятор?
Ну, например, в VC всегда можно отрубить стандартную библиотеку, определить свою точку входа вместо стандартной. Скажем, в каких-то простых loader'ах я люблю определить свой WinMainCRTStartup, в итоге вполне функциональные программы получаются размером 2к, из которых большая часть приходится на заголовок, stub и т.п.
> Ещё в PE-заголовке драйверов выставляется флаг NATIVE > subsystem, это как делается?
У VC есть параметр линкера /SUBSYSTEM. И вообще, для таких задач VC, пожалуй, подходит больше, все-таки это родной компилятор, опять же, всякие примеры будут собираться сходу, без предварительного рихтования make-файлов (как это было раньше, по крайней мере).
|