Нужно ли использовать begin чтобы сработало else?
Если действие после then одно, то можно и без begin .. end его записать.
begin .. end в условиях, обычно используется для предотвращения ошибок в логике и формирования правильной структуры нескольких условий. Например:
// Неправильное форматирование и структуру не так просто заметить if (x <> 1001) then writeln(x); if x <> 1002 then writeln(x) else writeln('-1'); // этот else относится ко второму if, а не к первому! // А вот так, все наглядно if (x <> 1001) then begin writeln(x); if x <> 1002 then writeln(x) end else writeln('-1');
Отслеживать
ответ дан 29 июн 2020 в 3:47
13.7k 12 12 золотых знаков 43 43 серебряных знака 75 75 бронзовых знаков
Да, можно так написать это не считается неправильным
Begin . End
используют для объединения нескольких команд в единый блок, но нет запрета на использования блока для одной команды как в вашем случае. Но есть рекомендации использовать begin end нежели опускать, по причине если в дальнейшей разработки вы добавите еще одну команду то в else есть вероятность что вы можете упустить добавить блок и ваша новая команда будет выполняться всегда.
else firstcommand(); . else onecommand(); secondcommand();
else begin firstcommand(); end . else begin onecommand(); secondcommand(); end;
Конструкция ветвления if then else
Оператор if then позволяет выполнять условное ветвление хода программы на основании результата логической операции.
Пример использования оператора:
if a > b then write('a > b'); b тогда вывести('a > b'); >
Процедура write выполниться только в случае, когда переменная a больше b.
Конструкцию можно дополнить словом else(иначе).
if a > b then write('a > b') else write('a < b'); b тогда вывести('a > b') иначе вывести('a
Перед ключевым словом else точка с запятой не указывается.
Напишем программу на языке Pascal для сравнения двух целых чисел. Будем использовать полное ветвление.
program CompareNums; var numOne, numTwo : integer; begin write('Введите первое число '); readln(numOne); write('Введите второе число '); readln(numTwo); if numOne = numTwo then writeln(numOne, ' = ', numTwo) else if numOne < numTwo then writeln(numOne, ' < ', numTwo) else writeln(numOne, ' > ', numTwo); writeln('Для выхода из программы нажмите клавишу Enter'); readln; end.
Из примера мы видим что конструкции ветвления можно комбинировать, создавая вложенные.
В теле if then может содержаться только один оператор, если требуется выполнить несколько операций, то вы можете использовать операторные скобки — begin end;
Если нужно проверить несколько условий, можно использовать условные выражения.
Программа на Паскаль в IDE Lazarus, которая попробует угадать, чем занимается пользователь исходя из его возраста.
program CheckUserAge; var age : integer; begin write('Сколько вам лет '); readln(age); if age < 1 then writeln('Значение не может быть меньше 4') else begin write('Скорее всего Вы '); if age < 6 then writeln('ходите в садик'); if (age >= 6) and (age < 18) then writeln('учитесь в школе'); if (age >=18) and (age 21) then writeln('студент'); if age > 21 then writeln('работаете'); end; writeln('Для выхода из программы нажмите клавишу Enter'); readln; end.
Конструкция ветвления if then else
Оператор if then позволяет выполнять условное ветвление хода программы на основании результата логической операции.
Пример использования оператора:
if a > b then write('a > b'); b тогда вывести('a > b'); >
Процедура write выполниться только в случае, когда переменная a больше b.
Конструкцию можно дополнить словом else(иначе).
if a > b then write('a > b') else write('a < b'); b тогда вывести('a > b') иначе вывести('a
Перед ключевым словом else точка с запятой не указывается.
Напишем программу на языке Pascal для сравнения двух целых чисел. Будем использовать полное ветвление.
program CompareNums; var numOne, numTwo : integer; begin write('Введите первое число '); readln(numOne); write('Введите второе число '); readln(numTwo); if numOne = numTwo then writeln(numOne, ' = ', numTwo) else if numOne < numTwo then writeln(numOne, ' < ', numTwo) else writeln(numOne, ' > ', numTwo); writeln('Для выхода из программы нажмите клавишу Enter'); readln; end.
Из примера мы видим что конструкции ветвления можно комбинировать, создавая вложенные.
В теле if then может содержаться только один оператор, если требуется выполнить несколько операций, то вы можете использовать операторные скобки — begin end;
Если нужно проверить несколько условий, можно использовать условные выражения.
Программа на Паскаль в IDE Lazarus, которая попробует угадать, чем занимается пользователь исходя из его возраста.
program CheckUserAge; var age : integer; begin write('Сколько вам лет '); readln(age); if age < 1 then writeln('Значение не может быть меньше 4') else begin write('Скорее всего Вы '); if age < 6 then writeln('ходите в садик'); if (age >= 6) and (age < 18) then writeln('учитесь в школе'); if (age >=18) and (age 21) then writeln('студент'); if age > 21 then writeln('работаете'); end; writeln('Для выхода из программы нажмите клавишу Enter'); readln; end.
Создание и использование динамических библиотек, написанных на различных языках (C/C++, Pascal)
Передо мной возникла задача написать загрузчик библиотек, имеющий возможность предоставить какие-то интерфейсные функции внешней динамической библиотеке. Решение должно быть максимально кроссплатформенно (как минимум, работать на Linux и Windows). Загружаться должны библиотеки, написанные на различных языках программирования, поддерживающих создание динамических библиотек. В качестве примера были выбраны языки C и Pascal.
Решение
Основной загрузчик библиотек написан на языке C. Для того, чтобы загружаемые библиотеки имели возможность использовать функции основной программы, основная программа разделена на 2 части: на основной и подгружаемый модули. Основной модуль нужен просто для запуска программы, подгружаемый модуль — это также динамическая библиотека, связываемая с основным модулем во время его запуска. В качестве компиляторов были выбраны gcc (MinGW для Windows) и fpc.
Здесь будет приведён упрощённый пример программы, позволяющий разобраться в данном вопросе и учить первокурсников писать модули к своей программе (в школе часто преподают именно Pascal).
Загрузчик библиотек
Главный файл загрузчика библиотек выглядит очень просто:
main.c
#include "loader.h" #ifdef __cplusplus extern "C" < #endif int main(int argc, char *argv[]) < if (argc >1) < loadRun(argv[1]); >return 0; > #ifdef __cplusplus > #endif
А это модуль, отвечающий за загрузку динамических библиотек, который сам вынесен в динамическую библиотеку для того, чтобы подгружаемые библиотеки имели возможность использовать предоставляемые им функции:
loader.c
#include "loader.h" #include "functions.h" #include #ifndef WIN32 #include #else #include #endif #ifdef __cplusplus extern "C" < #endif void printString(const char * const s) < printf("String from library: %s\n", s); >void loadRun(const char * const s) < void * lib; void (*fun)(void); #ifndef WIN32 lib = dlopen(s, RTLD_LAZY); #else lib = LoadLibrary(s); #endif if (!lib) < printf("cannot open library '%s'\n", s); return; >#ifndef WIN32 fun = (void (*)(void))dlsym(lib, "run"); #else fun = (void (*)(void))GetProcAddress((HINSTANCE)lib, "run"); #endif if (fun == NULL) < printf("cannot load function run\n"); >else < fun(); >#ifndef WIN32 dlclose(lib); #else FreeLibrary((HINSTANCE)lib); #endif > #ifdef __cplusplus > #endif
Заголовочные файлы
Это всё была реализация, а теперь заголовочные файлы.
Вот интерфейс модуля, загружающего динамические библиотеки, для основного модуля:
loader.h
#ifndef LOADER_H #define LOADER_H #ifdef __cplusplus extern "C" < #endif extern void loadRun(const char * const s); #ifdef __cplusplus >#endif #endif
Вот интерфейс загрузчика для загружаемых им динамических библиотек (перечень функций, которые динамические библиотеки могут использовать в основной программе):
functions.h
#ifndef FUNCTIONS_H #define FUNCTIONS_H #ifdef __cplusplus extern "C" < #endif extern void printString(const char * const s); #ifdef __cplusplus >#endif #endif
Как видно, здесь всего одна функция printString для примера.
Компиляция загрузчика
Пример недистрибутивной компиляции (в случае Windows в опции компилятора просто нужно добавить -DWIN32):
$ gcc -Wall -c main.c $ gcc -Wall -fPIC -c loader.c $ gcc -shared -o libloader.so loader.o -ldl $ gcc main.o -ldl -o run -L. -lloader -Wl,-rpath,.
Дистрибутивная компиляция от недистрибутивной отличается тем, что в дистрибутивном случае динамические библиотеки ищутся в /usr/lib и имеют вид lib$(NAME).so.$(VERSION), в случае недистрибутивной компиляции они называются lib$(NAME).so, а ищутся в каталоге запуска программы.
Теперь посмотрим, что у нас получилось после компиляции:
$ nm run | tail -n 2 U loadRun 08048504 T main $ nm libloader.so| tail -n 4 000005da T loadRun 000005ac T printString U printf@@GLIBC_2.0 U puts@@GLIBC_2.0
Тут видим, что функции, отмечаемые как U ищутся во внешних динамических библиотеках, а функции, отмечаемые как T предоставляются модулем. Это бинарный интерфейс программы (ABI).
Динамические библиотеки
Теперь приступим к описанию самих динамических библиотек.
Библиотека на языке C
Вот пример простейшей библиотеки на языке C:
lib.c
#include "functions.h" #ifdef __cplusplus extern "C" < #endif void run(void) < printString("Hello, world!"); >#ifdef __cplusplus > #endif
Здесь везде окружение extern «C» <> нужно для того, чтобы нашу программу можно было компилировать при помощи C++-компилятора, такого, как g++. Просто в C++ можно объявлять функции с одним и тем же именем, но с разной сигнатурой, соответственно в этом случае используется так называемая декорация имён функций, то есть сигнатура функций записывается в ABI. Окружение extern «C» <> нужно для того, чтобы не использовалась эта декорация (тем более, что эта декорация зависит от используемого компилятора).
Компиляция
$ gcc -Wall -fPIC -c lib.c $ gcc -shared -o lib.so lib.o
$ nm lib.so | tail -n 2 U printString 0000043c T run
$ ./run lib.so String from library: Hello, world!
Если мы уберём в нашем модуле окружение extern «C» <> и скомпилируем при помощи g++ вместо gcc, то увидим следующее:
$ nm lib.so | grep run 0000045c T _Z3runv
То есть, как и ожидалось, ABI библиотеки изменился, теперь наш загрузчик не сможет увидеть функцию run в этой библиотеке:
$ ./run lib.so cannot load function run
Библиотека на языке Pascal
Как мы увидели выше, для того, чтобы наш загрузчик видел функции в динамических библиотеках, созданных компилятором C++, пришлось дополнять наш код вставками extern «C» <>, это притом, что C/C++-компиляторы и языки родственные. Что уж говорить про компилятор FreePascal совершенно другого языка — Pascal? Естественно, что и тут без дополнительных телодвижений не обойтись.
Для начала нам нужно научиться использовать экспортированные в C функции для динамических библиотек. Вот пример аналогичного C/C++ заголовочного файла на языке Pascal:
func.pas
unit func; interface procedure printString(const s:string); stdcall; external name 'printString'; implementation end.
Вот пример самого модуля на языке Pascal:
modul.pas
library modul; uses func; procedure run; stdcall; begin printString('Hello from module!'); end; exports run; begin end.
Компиляция
$ fpc -Cg modul.pas Компилятор Free Pascal версии 2.5.1 [2011/02/21] для i386 Copyright (c) 1993-2010 by Florian Klaempfl Целевая ОС: Linux for i386 Компиляция modul.pas Компоновка libmodul.so /usr/bin/ld: warning: link.res contains output sections; did you forget -T? /usr/bin/ld: warning: creating a DT_TEXTREL in a shared object. 13 строк скомпилиpовано, 6.6 сек
Смотрим ABI получившейся библиотеки:
$ nm libmodul.so U printString 000050c0 T run
Как видим, ничего лишнего, однако настораживает предупреждение ld во время компиляции. Находим в гугле возможную причину предупреждения, это связано с компиляцией без PIC (Position Independent Code — код не привязан к физическому адресу), однако в man fpc находим, что наша опция -Cg должна генерировать PIC-код, что само по себе странно, видимо fpc не выполняет своих обещаний, либо я делаю что-то не так.
Теперь попробуем убрать в нашем заголовочном файле кусок name ‘printString’ и посмотрим, что выдаст компилятор теперь:
$ nm libmodul.so U FUNC_PRINTSTRING$SHORTSTRING 000050d0 T run
Как видно, декорация в FreePascal совсем другого рода, чем в g++ и тоже присутствует.
При запуске с этим модулем получаем:
$ ./run libmodul.so ./run: symbol lookup error: ./libmodul.so: undefined symbol: FUNC_PRINTSTRING$SHORTSTRING
А с правильным модулем получаем:
$ ./run libmodul.so String from library: Hello from module!
Вот и всё, своей задачи — использование динамических библиотек, написанных на различных языках — мы достигли, и наш код работает как под Linux, так и под Windows (у самого Mac’а нет, поэтому не смотрел, как там с этим). Кроме того, загруженные библиотеки имеют возможность использовать предоставляемые в основной программе функции для взаимодействия с ней (то есть являются плагинами основной программы).
Сам загрузчик может выполняться в отдельном процессе, чтобы эти плагины не смогли сделать ничего лишнего с основной программой. Соответственно, основная программа может быть написана на любом другом удобном языке программирования (например, на Java или на том же C++).
Литература
- Загрузка DLL в C++.
- Linux первые шаги.
- Создание модуля Apache на языке Pascal.
