> Тут столкнулся с тривиальной задачей, нужно «пулять» > целочисленные значения по разным ветвям обработки, > тривиальный case в Паскале справился бы на-ура. А вот в > сях... switch - case какой-то слабоватый. Итак, пример на > Паскале ниже и вопрос в том, как это лучше всего > реализовать в С: > Case MyIntegerValue of > 0..15: DoSomthingCool(MyIntegerValue);
> 16, 18, 24: DoNextCoolThing(MyIntegerValue);
> 26..89, 90, 95, 101..170:
> VeryNiceAndCool(MyIntegerValue);
В сях case действует немного по другому - первый же встреченный case с совпадением приводит к тому, что все другие case как бы пропускаются (почему так - можно понять взглянув на код, который генерится для switch-case инструкции) - именно поэтому каждый case нужно заканчивать break-ом. Так вот, чтоб прикрутить к одной ветке исполнения несколько разных case-ов нужно просто все их указать:
switch(i) {
case 0: case 1: case 2: case 3:
do_my_stuff();
break;
case 10: case 11: case 12:
do_another_stuff();
break;
default:
do_default_stuff();
}
---
Но такой код встречается нечасто, обычно case-ы идут по предопределенным константам (кодам сообщений, ioctl-ов, чего-то еще). Если нужно например сделать что-то только для букв есть библиотечная функция:
if (isalpha(char))
do_something(char);
Другие типы символов можно глянуть в <ctype.h>
И кстати, case-ы с не очень большим разбросом реализуются в коде при помощи таблицы указателей на функции (в общем берем нужный case используем как индекс в некой таблице и получаем искомый результат). Кстати использование всевозможных таблиц с данными - очень часто используемый прием.
Если действительно жизнь не мила без множеств (set-ов) - можешь глянуть на C++ овский STL или нестандартные библиотеки типа MFC.
> End; ---
> Здесь паскальный Case во всей своей красе — выбор из > диапазона, из дискретных значений (что возможно и в сяшной > паре switch - case), и в последней строке выбора есть Сишный switch-case не умеет в одном case-е обрабатывать диапазоны - нет такого типа. Если нужен диапазон - нужно делать несколько case-ов.
> Ну а теперь про множества. Это немного соотносится с case. > if MyChar in ['A'..'Z', 'a'..'z'] then DoSomthing — как это > сделать попроще? Собственно, см выше. Напомню:
if (isalpha(MyChar)) do_something();
> Я понимаю, что можно так: > if (((MyChar >= "A") && (MyChar <= "Z"))|((MyChar > >= "a") && (MyChar <= "z"))) > DoSomething(); Так, кстати, будет работать не везде. Например в кодировке EBCDIC - символы от a до z идут не непрерывно, а C задумывался как высокопортабельный язык, при этом библиотечная функция использует не 4-е сравнения (как в вышеприведенном примере), а одно индексирование и одну логическую операцию (битовое И).
> Ну и потяжелее пример с типом «множество»... > 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; ---
Множеств в стандарте C нет. Есть математические библиотеки с реализациями и так далее. В стандарте C++ множества, как и многое другое есть, но не встроенные в язык, а реализованные в виде стандартной библиотеки. Это кстати соблюдается везде, где можно: все, что не нужно для самого языка выносится в библиотеку, например, в C (и C++) нет поддержки ввода/вывода на уровне языка (в отличие от паскаля, где read/write - операторы) - язык позволяет сделать это в библиотеке. Хотя может я и неточно выражаюсь, потому как эта самая библиотека стандартизирована: все реализации языка должны предоставлять то-то и то-то, а значит вроде как и тоже относятся к языку.
> Я понимаю, для процессора это всего-навсего возня с битами > в целочисленных значениях. Меня не испугает никакой язык, > если в нём есть операции or, and, xor и прочяя... Но > возможно, не надо изобретать колесо и есть уже что-то в > самом языке? См выше. Короче, если кровь из носа нужны множества и именно на C - можешь поискать в инете куча свободных математических библиотек.
> именно за борландовсий С. И что я вижу — программа, которая > «ничего не делает» — а именно, входит в Main и выходит из > неё, без единого #include занимает 7 с лишним килобайт и Маловато что-то :-)))
Вообще-то стандартное выравнивание секций для винды: 0x1000 (4 киловытеса). Именно для виндовозного PE, а не для какого-либо языка или компилятора. При этом выравниваются: заголовок, секция кода, секция данных и секция импортов. Так что минимум, чего можно добиться со стандартными установками - 16 кБ. Границу выравнивания можно уменьшить, но на фиг это никому не нужно. В сях тоже есть инициализация: как минимум проинициализировать некоторые глобальные и статические переменных (иногда не получается на этапе компиляции) и преобразовать строчку параметров строки в массив для вызова main(), вызов самого main-а и т.д.. Там не так много, но все-таки есть.
> выполняет кучу дерьма пользовательского режима при старте. > С этим можно как-то побороться, или мне нужен другой > компилятор? Если собираешься писать дривера, то нужен по-луюбому (см сабж).
> Ещё в PE-заголовке драйверов выставляется флаг NATIVE > subsystem, это как делается? Смотри опции линкера (для VC-шного это делается так: link /subsystem:native) вот только для драйверов нужно не это
> Заранее всем большое спасибо, надеюсь что не утомил. Не очень :-))) Наоборот, нашего полку прибыло :-)))
|