Сапа
Здесь может быть ваша реклама
|

 Глава 3. Выражения и операторы

Глава 3. Выражения и операторы

В этой главе мы рассмотрим такие конструкции языка Object Pascal, как выражения и операторы. Вы узнаете об арифметических, логических и строковых выражениях языка Object Pascal. Кроме того, мы расскажем о простых и структурированных операторах, операторах условия, выбора и цикла.

Выражения
Выражения представляют собой конструкцию языка, которая содержит данные, операции и имеется строгий порядок выполнения операций.
В общем случае, в состав выражения входят:
операнды;
знаки операций;
скобки.
Операнды - это данные, над которыми производятся действия. Операндами могут быть переменные, константы, переменные массивов и другие элементы,
Знаки операций - это знаки, определяющие конкретные действия, которые должны быть произведены над операндами. Операции могут производиться над одним операндом и над несколькими операндами. Если операция производится над одним операндом, то знак операции ставится перед операндом, например -х. Если операция производится над двумя или несколькими операндами, знак операции ставится между операндами, например х*12.
Скобки - круглые скобки, которые служат для определения порядка выполнения операций, например, (х+у) /2.

Арифметические выражения
Арифметические операции выполняются над целыми и действительными числами. Результатом выполнения арифметического выражения является также целое или действительное число.
В языке Object Pascal определены арифметические операции над двумя операндами, которые приведены в табл. 3.1.

Таблица 3.1. Арифметические операции над двумя операндами

Знак операции ОперацияТипы операндовТип результатаПример
+
СложениеInteger, realInteger, realХ+У
-
ВычитаниеInteger, realInteger, realX-Y
*
УмножениеInteger, realInteger, realX*Y
/
ДелениеInteger, realRealX/10
div
Целочисленное деление IntegerIntegerX div Y
mod
Целочисленный остаток от деления IntegerIntegerX mod Y

Стоит сказать несколько слов по поводу операций div и mod. Результатом целочисленного деления х div Y будет результат деления X/Y, округленный в сторону нуля до ближайшего целого числа.
результатом операции mod будет остаток от целочисленного деления операнде. Таким образом, выражение х mod Y эквивалентно выражению х - (х div Y) *Y. Например, результатом выражения 4 div 2 будет о, а результатом выражения 9 div 4 будет 1.
В табл. 3.2 приведены операции, осуществляемые над одним операндом.

Таблица 3.2. Арифметические операции над одним операндом

Знак операцииОперацияТип операндаТип результатаПример
+
Сохранение знака числаInteger, realInteger, real
+7
-
Отрицание знака числаInteger, realInteger, real
-X

Приведем примеры использования арифметических операций с одним и двумя операндами (листинг 3.1).

Листинг 3.1 Примеры использования арифметических операций
var
a, b, с, d: Integer; // Объявляем четыре целочисленных переменных
begin
a:=7; b:= 5; c:= -10; // Присваиваем трем из них начальные значения
d:= a+b; // Результатом будет число 12
d:= -d; // Результатом будет число -12 .
d:= d+c; // Результатом будет число -22
d:= d div с; // Результатом будет число 2
d:= a mod b; // Результатом будет число 2
end;

Кроме вышеперечисленных операций, над целочисленными данными можно производить поразрядные операции, представленные в табл. 3.3. Особенностью этих арифметических операций является то, что они выполняются побитно над операндами, переведенными в двоичную форму. Результат выдается в десятичной системе счисления.

Знак операцииОперацияТипы операндовТип результатаПример
notПоразрядное отрицаниеIntegerIntegernot X
andПоразрядное умножениеIntegerIntegerX and Y
orПоразрядное сложениеIntegerIntegerX or Y
xorПоразрядное исключающее ИЛИIntegerIntegerX xor Y
shl Поразрядный сдвиг числа влево
IntegerIntegerX shl 2
shrПоразрядный сдвиг числа вправоIntegerIntegerX shr 1

Таблица 3.3. Поразрядные арифметические операции

В табл. 3.4 показаны результаты выполнения поразрядных арифметических операций.

Таблица 3.4. Результаты выполнения поразрядных арифметических операций

Знак операции
Операция
Бит1
Бит 2
Результирующий бит
not
Поразрядное отрицание
0
1
1
0
and
Поразрядное умножение
0
0
1
1
0
1
0
1
0
0
0
1
or
Поразрядное сложение
0
0
1
1
0
1
0
1
0
1
1
1
хоr
Поразрядное исключающее ИЛИ
0
0
1
1
0
1
0
1
0
1
1
0

Приведем примеры использования побитовых арифметических операций (листинг 3.2).

Листинг 3.2 Примеры использования побитовых операций
var
a,b,c: Integer; // Объявляем три целочисленные переменные begin
а:=175; Ь:=77; // Двум из них присваиваем начальные значения
c:=not а; // Результатом будет число -176
с:-a or b; // Результатом будет число 239
c:=a and b; // Результатом будет число 13
с:=а хог Ь; // Результатом будет число 226
с:=а shl 1; // Результатом будет число 350
c:=b shr 1; // Результатом будет число 38
end;

Число 175 в двоичной системе выглядит так: 10101111. А число 77 так: 1001101. Операции производятся поразрядно справа налево, затем результат переводится в десятичную систему счисления.
Сдвиг на один разряд влево равносилен умножению числа на 2. Сдвиг на один разряд вправо равносилен делению числа нацело на 2 с отбрасыванием дробной части.
Кроме всего рассмотренного выше, язык Object Pascal имеет достаточно большое количество функций для работы с числовыми данными. Эти функции можно также использовать в арифметических выражениях. Среди прочих наиболее часто используются следующие функции:
Abs(x) - абсолютное значение х. Вызов данной функции позволяет отбросить знак минус у числа, если он есть;
Cos (х) - косинус угла х. Угол задается в радианах; Ехр(х) - возведение числа е в степень х;
Ln(х) - натуральный логарифм числа х;
odd(x) - проверяет число х на четность. Если оно четное, то возвращает значение True, иначе - False;
sin (х) - синус угла х. Угол задается в радианах;
sqr (х) - возведение числа х в квадрат;
sqrt (х) - извлечение квадратного корня из числа х.
Аргументами данных функций могут быть не только числа, но и переменные, константы, выражения.
Приведем пример вычисления выражения, в котором присутствуют арифметические функции:

a:=sqr((152+b)/2*cos(3.14+b)+sqrt(23) ) ;

Логические выражения
Логические выражения это выражения, в которых содержатся:
логические константы True и False;
логические переменные и константы типа Boolean;
операции отношения;
логические операции;
скобки.
В результате выполнения логической операции получается логическое значение True или False. Логические операции, доступные в языке Object Pascal, представлены в табл. 3.5.

Таблица 3.5. Логические операции языка Object Pascal

Знак операцииОперация Типы операндовТип результата Пример
not
Отрицание
Boolean
Boolean
not (С in MySet)
and
Конъюнкция (логическое И)
Boolean
Boolean
A and В
or
Дизъюнкция (логическое ИЛИ)
Boolean
Boolean
A or В
хоr
Исключающая дизъюнкция (исключающее ИЛИ)
Boolean
Boolean
А хог В

Как видно из примеров табл. 3.5, логические операции and, or и xor являются операциями над двумя операндами, а операции not - над одним операндом. В следующей таблице (табл. 3.6) приведены результаты выполнения логических операций.

Таблица 3.6. Результаты выполнения логических операций

Знак операции
Операция
Операнд 1
Операнд 2
Результат
not
Отрицание
False
True
True
False
and
Конъюнкция (логическое И)
False
False
True
True
False
True
False
True
False
False
False
True
or
Дизъюнкция (логическое ИЛИ)
False
False
True
True
False
True
False
True
False
True
True
True
хоr
Исключающая дизъюнкция (исключающее ИЛИ)
False
False
True
True
False
True
False
True
False
True
True
False

Для установки отношений между двумя значениями вы можете использовать операции отношения или сравнения. В языке Object Pascal имеется шесть операций отношения:
= - равенство;
< - меньше;
> - больше;
<= - меньше или равно;
>= - больше или равно;
<> - не равно.
Если операция отношения истинна, то результатом ее выполнения является значение True, например истинным является выражение 4 < 10; в противном случае - результат False, например 12 <> 12.
Рассмотрим теперь такой немаловажный вопрос: в каком порядке выполняются те или иные операции? Если в сложном выражении записаны несколько операций подряд, то последовательность их выполнения определяется старшинством. Для того чтобы был четкий порядок выполнения операции, в языке Object Pascal существует такое понятие, как приоритет.
Приоритет определяет старшинство операций и служит для установления порядка выполнения операций. Операции с более высоким уровнем приоритета выполняются раньше остальных.
По приоритету все операции делятся на четыре уровня:
первый (наивысший) уровень приоритета. К нему относятся операции @ и not;
второй уровень приоритета - операции *, /, div, mod, and, shi, shr и as;
третий уровень приоритета - операции +, -, or и xor;
четвертый (самый низкий) уровень приоритета - операции =, <>, <, >, <=, >=, in И is.
Если подряд идут несколько операций с одинаковым приоритетом, то операции выполняются слева направо.

Строковые выражения
Строковые выражения содержат строковые операции и функции. Для строк в Object Pascal определена одна операция - операция объединения строк (конкатенации строк). Знаком операции конкатенации является +. Операндами для этой операции могут быть строки, упакованные строки, а также символы. В то же время, если один из операндов имеет тип widechar, другой операнд должен быть длинной строкой. Результат операции объединения строк - строка символов. Этот результат совместим со всеми строковыми типами языка. В то же время, если количество символов после операции объединения строк превысит 255, то результатом станут первые 255 символов, а оставшиеся будут просто отброшены.
Для строк определены также следующие функции:
Concat(sl, s2, ..., sn) - возвращает строку, представляющую собой объединение строк si ... sn;
copy(S; index, Count) - возвращает строковое значение, являющееся подстрокой строки s, начиная с символа под номером index, и длиной count;
Length (s) - возвращает целое число, равное количеству символов в строке s;
символа, начиная с которого подстрока substr входит в строку s. Если такой подстроки в строке нет, то результатом будет 0;
Ttim(s) - возвращает строку, полученную в результате отбрасывания от строки s пробелов и управляющих символов в начале и конце строки;
TrimLeft(s) - возвращает строку, полученную в результате отбрасывания от строки s пробелов и управляющих символов в начале строки;
TrijnRight (s) - возвращает строку, полученную в результате отбрасывания от строки s пробелов и управляющих символов в конце строки.
Кроме перечисленных выше функций существует несколько дополнительное функций для преобразования одних типов данных в другие:
DateToStr(Date) - возвращает строку, полученную в результате преобразования значения даты Date в строку;
IrioatToStr(value) - возвращает строку, полученную в результате преобразования вещественного числа value в строку;
intTostr(value) - возвращает строку, полученную в результате преобразования целого числа value в строку;
LowerCasfe(s) - возвращает строку, полученную в результате преобразования строки s в строку символов нижнего регистра (прописные буквы);
strToDate(s) - возвращает значение типа "дата", полученное в результате преобразования строки s в значение даты;
strToDateTime(s) - возвращает значение типа "дата и время", полученное в результате преобразования строки s в значение даты и времени;
StrToFioat (s) - возвращает значение вещественного типа, полученное в результате преобразования строки s в вещественное число;
strToint(s) - возвращает целочисленное значение, полученное в результате преобразования строки s в целое число;
strToTime(s) - возвращает значение типа "время", полученное в результате преобразования строки s в значение времени;
TimeTostr(time) - возвращает строку, полученную в результате преобразования значения времени time в строку;
uppercase (s) -^ возвращает строку, полученную в результате преобразования строки s в строку символов верхнего регистра (заглавные буквы);
Приведем примеры строковых выражений:
S:='Мама'; // Результат в переменной S - слово Мама
S:=s + ' мыла'; // Результат - Мама мыла
S:=s + Uppercase(' раму1); // Результат - Мама мыла РАМУ

Простые операторы
Для выполнения каких-либо действий в программе на языке Object Pascal применяются операторы. Операторы - это команды компилятору языка на выполнение определенных действий. Как мы уже отмечали ранее, все операторы делятся на простые и структурированные.
Напомним, что простые операторы не влияют на ход выполнения программы, т. е. сохраняют линейность выполнения команд программы.
Кроме рассмотренных ранее арифметических логических и строковых операторов, к числу простых операторов относятся:
оператор присваивания; пустой оператор;
составной оператор; оператор доступа.

Оператор присваивания

Данный оператор является наиболее часто используемым в программах на языке Object Pascal. Оператор присваивания записывается с помощью знака :=. Данный оператор применяется для присваивания значения, записанного справа от знака присваивания переменной, которая записана слева от знака присваивания:

А: =10; // Переменной А присваивается значение 10

Если справа от знака присваивания стоит не конкретное значение, а выражение, оно будет вычислено и присвоено переменной слева от знака присваивания:

А:=12*754+123; // В переменную А будет помещен конечный
// результат вычисления

Переменная и выражение справа должны быть одного и того же или совместимого типа. Слева от оператора присваивания допустимо помещать не только переменную, но и элементы массивов, поля записей и другие объекты.

Пустой оператор
Пустой оператор мы уже рассматривали ранее. Он представляет собой точку с запятой и может быть расположен в любом месте программы, где допускается наличие операторов. Данный оператор не выполняет никаких действий, но бывает иногда необходим.

Составной оператор

Составной оператор - это группа операторов, которые заключены между операторными скобками begin и end и отделены друг от друга точкой с запятой.
Таким образом, составной оператор представляет собой следующую конструкцию:

begin
operator1; operator2;
operatorn;
end;

Такой оператор рассматривается как единое целое и может располагаться в любом месте программы, где допустимо наличие операторов.
Составные операторы могут быть вложены друг в друга. Например,

begin // Начало внешнего составного оператора
Operator1;
begin // Начало внутреннего составного оператора operator2_1;
Qperator2_2;
…;
operator2_k;
end; // Конец внутреннего оператора
…;
operatorn;
end; // Конец внешнего оператора

Количество вложений операторов друг в друга языком Object Pascal не ограничивается.

Оператор доступа
Оператор доступа предназначен для быстрого и удобного доступа к составным частям отдельных объектов. Например, удобно использовать оператор доступа при работе с полями записи. Если вы помните, для доступа к отдельному полю записи необходимо сначала указать имя этой записи и через точку - имя поля. Если нужно проделать несколько операций с разными полями записи, то оператор доступа использовать очень удобно.
Оператор доступа представлен следующим образом:
with объект do действие
Чтобы быстрее понять работу этого оператора, обратимся к листингу 3.3.

Листинг 3.3 Пример работы с оператором with
type TDate = record // Объявляем новый тип - запись с тремя полями
Day: Integer; // Поле День Month: Integer; // Поле Месяц
Year: Integer; // Поле Год end;
var OrderDate: TDate; // Объявляем запись OrderDate begin
with OrderDate do // Далее оперируем с записью OrderDate if Month =12 then begin
Month := 1;
Year := Year + 1;
end
else
Month := Month + 1;
end;

Таким образом, при обращении к полям записи нам не нужно указывать имя самой записи.
Кроме обращения к полям записи, при помощи оператора доступа можно повысить удобство работы с объектами Kylix, которые мы рассмотрим во второй части книги.

Структурированные операторы
Напомним, что структурированные операторы - это операторы, которые изменяют ход выполнения команд программы.
К числу структурированных операторов можно отнести:
оператор перехода;
оператор условия;
оператор выбора;
операторы цикла.
Рассмотрим эти операторы.

Оператор перехода
Оператор перехода позволяет перейти от текущего места выполнения программы к другому месту, которое не является следующим по порядку. Данный оператор нарушает нормальный ход выполнения программы.
Переход осуществляется при помощи так называемых меток. Метка - это идентификатор или целое число без знака в диапазоне от 0 до 9999, которое находится перед каким-либо оператором программы и отделено от него двоеточием. Все используемые в программе метки должны быть предварительно объявлены в разделе объявления меток, начинающемся словом label.
Оператор перехода выглядит так:
goto метка;

Приведем фрагмент программы, в которой используется метка:

Label 1; // Объявляем метку с именем 1
var
A:integer; begin
а:=10;
goto 1; // Переход на метку 1
a;"sqrt(a); // Этот оператор не будет выполняться никогда!
1:a:=a+a; //' Оператор, помеченный меткой 1
end;

Примечание
Использование меток и операторов перехода не является хорошим тоном программирования. Старайтесь по возможности не использовать этот оператор, Т.к. это затрудняет чтение текста программы.

Оператор условия
Оператор условия предназначен для выполнения или невыполнения каких-либо действий, зависящих от результата условия типа Boolean. Этот оператор применяют для разветвления выполнения программы. То есть, если данное условие истинно (и только в этом случае!), выполняется некоторая последовательность операторов, иначе - выполняются другие операторы. Вид оператора условия таков:

If условие then оператор1 else оператор2;

Оператор условия может быть записан и в упрощенной форме:

If условие then оператор;

Приведем примеры использования операторов условия:

If a>0 then b:=sqrt(a) else b:=a*2; // Оператор условия
If a=10 then b:=b+l; // Упрощенная форма

Для того чтобы организовать ветвление на несколько направлений (более двух), можно использовать несколько операторов условия, вложенных друг в друга. Вложение операторов условия происходит по тем же правилам, что и вложение составных операторов.

Примечание
Старайтесь не злоупотреблять чрезмерным вложением операторов условия друг в друга, т. к. это может привести к трудно выявляемым ошибкам.

Оператор выбора
Оператор выбора - это конструкция языка, позволяющая сделать выбор из произвольного числа вариантов и выполнить в соответствии с этим выбором if определенные действия. То есть оператор выбора позволяет обойтись без использования нескольких операторов if.
Оператор выбора имеет следующий вид:

case селектор of
Список1: Оператор1;
СписокN: OnepaтоpN;
else
Оператор;
end;

Таким образом, оператор выбора case состоит из селектора, списка вариантов и необязательной части else.
Выражение-селектор должно быть обязательно порядкового типа. Нельзя использовать в качестве селектора строковые типы.
Каждое значение списка вариантов представляет собой вариант значения, принимаемого селектором. Оно должно быть:
цифрой, объявленной константой или другим выражением, которое компилятор может определить без выполнения программы. Переменные и вызовы функций не могут быть значением списка вариантов;
совместимым по типу с селектором;
уникальным. Ни одно из значений списка не может быть продублировано.
Приведем пример использования оператора case (листинг 3,4).

Листинг 3.4 Пример использования оператора case
I of // В зависимости от значения переменной I
1..5: С := 'До пяти1; // Если оно от 1 до 5, то переменная С= 'До пяти'
6.. 9: С :== 'Выше пяти'; // Если оно от б до 9, то переменная С= 'Выше
// пяти'
0, 10.. 99: С := 'Вне области допустимых значений'; // Если оно равно 0 // или от 10 до 99, то С=' Вне области допустимых значений'
else
С := "; // Иначе, если ни одно из условий не выполняется,
//С равно пустой строке
end;

Таким образом, мы с помощью одного оператора case охватили множество значений. Более того, код программы читается довольно легко. Посмотрим, что было бы, если бы для той же самой задачи мы использовали оператор условия (листинг 3.5).

Листинг 3.5 Пример использования оператора условия

if I in [1..5] then
С := 'До пяти'
else if I in [6.. 10] then
С := 'Выше пяти'
else if (I = 0) or (I in [10..99]) then
С : = 'Вне области допустимых значений' else
С := ";

На листинге 3.5 получилась довольно тяжело читаемая конструкция.

Операторы цикла
Иногда необходимо, чтобы какая-либо часть программы выполнялась несколько раз. Для этого во всех языках программирования, в том числе и в Языке Object Pascal, используются циклы.
Цикл - это последовательность операторов, команд, которая выполняется более одного раза, т. е. повторяется. Такие операторы и команды называют телом цикла.
В языке Object Pascal имеются три вида операторов цикла:
цикл с параметром;
цикл с предусловием;
цикл с постусловием.
Каждый из этих видов циклов удобно применять в определенных случаях, хотя с помощью любого из них можно обходиться практически в любом случае.
В тело цикла допускается помещать оператор безусловного перехода goto. Кроме того, для досрочного прерывания выполнения цикла можно использовать специальную процедуру break. Вызов этой процедуры приводит к прекращению выполнения операторов тела цикла и переходу к выполнению операторов, расположенных сразу за циклом. Вы можете досрочно завершить выполнение данного повторения цикла при помощи вызова процедуры continue. Ее вызов приводит к передаче управления сразу в конец цикла, т. е. досрочному завершению данного повторения.
Операторы циклов допускают множественные вложения друг в друга. При вложении, сначала выполняются внутренние операторы цикла, а затем - внешние. Далее мы приведем примеры вложений операторов цикла друг в Друга.

Цикл с параметром

Цикл с параметром применяется в том случае, когда заранее известно, сколько раз он должен выполниться. Данный цикл выглядит следующим образом:

For параметр:=нач.значение to кон.значение do оператор;

ИЛИ

For параметр:=нач.значение downto кон.значение do оператор;

Параметр цикла - это переменная порядкового типа, которая объявлена в разделе объявления переменных.
Начальное значение - это значение, которое принимает параметр цикла. Естественно, что данное значение должно быть того же типа, что и переменная параметра цикла.
Конечное значение - это значение, которое может принимать параметр цикла;
Оператор - это одиночный или составной оператор, который и представляет собой тело цикла.

Внимание
Тело цикла не должно изменять параметр цикла, т. к. это может привести к непредсказуемым последствиям. В частности, к бесконечному циклу (зацикливанию программы).

И первый и второй варианты написания цикла изменяют параметр цикла на единицу. В первом случае (for ... to) происходит увеличение параметра на единицу при каждом проходе цикла, во втором случае (for ... downto) - уменьшение параметра цикла на единицу.
Итак, цикл с параметром выполняется несколько раз, постепенно увеличивая или уменьшая значение параметра: до тех пор, пока это значение не достигнет конечного значения.

Примечание

Цикл не выполняется ни разу, если для первого варианта цикла начальное значение параметра больше конечного, а для второго варианта - конечное значение больше начального.

Приведем несколько примеров циклов с параметрами (листинг 3.6).

Листинг 3.6 Примеры циклов с параметрами
ror i:=1 to 20 do // Начало цикла
begin // Начало составного оператора
s:=s+i; // Тело цикла
a;=a*i;
end; // Конец цикла. Значение i увеличивается на 1
for i:=1 to 10 do // Начало внешнего цикла
begin // Начало составного оператора
for j:=10 downto 1 do // Начало внутреннего цикла
begin
s:=s+j; // Тело внутреннего цикла
a:=s+a;
end; // Конец внутреннего цикла, i уменьшается на 1
a:=a*s;
end; // Конец внешнего цикла, i увеличивается на 1

Цикл с предусловием
Цикл с предусловием применяется в том случае, если число повторений заранее неизвестно и если при некоторых условиях тело цикла может не выполняться совсем. Данный цикл выглядит следующим образом:

while условие do оператор;

Условие представляет собой логическое выражение, которое может быть ложным или истинным.
Оператор - это тело цикла. Он может быть простым или составным.
[Данный цикл выполняется в том случае, когда условие имеет значение True. Как только условие примет значение False, цикл выполняться не будет.
Переменные, входящие в условие цикла, могут быть произвольными (не обязательно порядковыми).
Пример оператора цикла с предусловием представлен ниже (листинг 3.7).

Листинг 3.7 Пример цикла с предусловием
while I > 0 do // Начало цикла
begin // Начало составного оператора
S := S+I; // Тело цикла
I :=I -1; // Изменяем переменную i самостоятельно
end; // Конец цикла. Переменная i не изменяется

Примечание
В отличие от цикла с параметром, при использовании других видов циклов следите за тем, чтобы условие цикла когда-нибудь изменилось. Для этого нужно изменять переменные, входящие в условие цикла в теле цикла.

Данный цикл не выполняется совсем, если при первоначальной проверке 'условия оно имеет значение False.

Цикл с постусловием
Цикл с постусловием используется в случае, когда желательно, чтобы тело цикла выполнилось хотя бы один раз, а общее количество повторений цикла заранее неизвестно.
Данный цикл имеет следующий вид:
repeat
оператор1;
...
операторN;
unti1 условие;

Операторы, расположенные между словами repeat и собой тело цикла. Условие - это логическое выражение.
Операторы цикла выполняются, по крайней мере, один раз, а затем происходит проверка истинности условия. Если условие является ложным (False), то операторы цикла выполняются повторно. Цикл будет выполняться до тех пор, пока условие цикла не станет истинным (True).
Рассмотрим пример применения цикла с постусловием (листинг 3.8).

Листинг 3.8 Приме6р цикла с постусловием
repeat // Начало цикла
К := I mod J; // Тело цикла
I := J;
J := К;
unti1 J = 0; // Условие цикла

 
MKPortal©2003-2008 mkportal.it
MultiBoard ©2007-2009 RusMKPortal