C# изборна дисциплина


Оператори за преход break, continue и goto



страница3/5
Дата27.09.2016
Размер0.88 Mb.
#10986
1   2   3   4   5
8. Оператори за преход break, continue и goto
Използването на оператора break дава възможност за принудително и незабавно излизане от цикъла без да се изпълни останалата част от тялото му и без да се провери условието в цикъла, т.е. когато оператора break; се срещне в тялото на цикъл, то цикълът завършва своята работа и управлението се предава на оператора след цикъла.

Ще съставим програма за намиране на простите числа в интервала от 1 до 100:

using System;
class Prime

{

public static void Main()



{

int i, j;

bool isprime;

for (i = 1; i <= 100; i++)

{

isprime = true;



for (j = 2; j <= i / 2; j++)

{

if (i % j == 0)



{

isprime = false;

break;

}

}



if (isprime == true)

{

Console.WriteLine("{0} е просто число", i);



}

}

}



}

Операторът break може да се използва за прекъсване на безкраен цикъл. Ето

char ch;

for (; ; )

{

ch = (char)Console.Read();



if (ch == 'q') break;

}

Ако операторът break; се използва във вложени цикли, то той прекратява изпълнението само на най-вътрешния цикъл. Пример:



using System;
class Prime

{

public static void Main()



{

int count = 0;

for (int i = 0; i < 3; i++)

{

count++;



Console.WriteLine("count=" + count);

int t = 1;

while (t < 100)

{

if (t == 11)



break;

Console.Write(t+" ");

t++;

}

Console.WriteLine();



}

}

}



При изпълнение на continue; се извършва незабавно предаване на управлението на следващата итерация на цикъла, т.е. на следващото изпълнение на тялото на цикъла, без да се изпълни останалата част от тялото на цикъла.

Пример - оператор continue; се използва за извеждане на екрана на четните числа в диапазона от 1 до 100:

using System;
class ContDemo

{

public static void Main()



{

int i;


Console.WriteLine("Четни числа от 0 до 100: ");

for (i = 0; i <= 100; i++)

{

if (i % 2 != 0)



continue;

Console.Write(i + " ");

}

Console.WriteLine();



}

}

В циклите while и do while използването на оператора continue води до предаване на управлението непосредствено на условния израз, след което изпълнението на цикъла продължава. В цикъла for отначало се пресмята итерационния израз3 на цикъла, след това се оценява условния израз2 и вече след това продължава изпълнението на тялото на цикъла.



В С# gotо е оператор за безусловен преход. Ако той се срещне в кода, управлението в изпълнението на програмата се предава на това място, което е указано в goto. Много програмисти избягват да го използват, понеже той води до създаване на лошо структурирани и с объркана логика програми. Операторът goto има следния общ вид:

goto етикет;

Като „етикет” е идентификатор. Пред операторите може да има етикет. Т.е.

етикет:оператор

Предаване на управлението с goto може да стане само в рамките на един и същи метод. Например:

int x;


x = 1;

loop1:


x++;

if (x < 100)

goto loop1;

Console.WriteLine(x);

Операторът goto може ефективно да се използва за излизане от дълбоко вложени цикли. Пример:

using System;


class gotoDemo

{

public static void Main()



{

int i = 0, j = 0, k = 0;

for (i = 0; i < 10; i++)

{

for (j = 0; j < 10; j++)



{

for (k = 0; k < 10; k++)

{

Console.WriteLine("ijk:" + i + ' ' + j + ' ' + k);



if (k == 3)

goto stop;

}

}

}



stop:

Console.WriteLine("Завършва изпълнението на цикъла! i, j, k: {0}, {1}, {2}", i, j, k);

}

}

Ако тук не използвахме goto, би трябвало да използваме if и break. В този пример използването на goto е оправдано. В С# операторите break, continue и goto са същите както в С/С++, а в Java няма goto.




9. Класове и обекти
Класът е фундамент, на който е построен целия език С#. В класа се определят данните и кода, който обработва тези данни. Обектите са екземпляри на класа. Непосредствената инициализация на променливите в обекта се извършва в конструктор. В класа могат да бъдат определени няколко конструктора.

Класът е логическа абстракция докато не бъде създаден обект и не се появи физическа реализация на този обекат в паметта на компютъра. Методите и променливите, съставящи класа, се наричат членове на класа. Данните се съдържат в променливите на обекта, които са определени в класа, а кода се съдържа в методите. Общ вид на дефиницията на класа, съдържащ само променливи на екземпляра и методи:

class име_на_класа

{

достъп тип променлива1;



достъп тип променлива2;

...


достъп тип променливаN;

достъп тип метод1(параметри)

{

//тяло;


}

достъп тип метод2(параметри)

{

//тяло;


}

...


достъп тип методN(параметри)

{

//тяло;



}
}

Обърнете внимание, че дефинирането на всяка променлива или метод започва с задавне на достъп. Достъпът може да бъде private или public. Модификаторът private указва, че съответния член на класа е достъпен само за членовете на този клас. Модификатортът public указва, че съответния член на класа е достъпен и за кода, определен извън границите на дадения клас. Ако достъпът не е зададен се приема по подразбиране private. Методър Main() е необходим само в класа, от който трябва да започне изпълнението на програмата.

using System;

class Vehicle

{

public int passengers;



public int fuelcap;

public int mpg;

}

Синтаксиса за дефиниране на променлива на екземпляра е аналогичен на този, на дефиниране на вътрешни (локални) променливи, само че дефиницията започва със задаване на спецификатора за достъп. С дефинирането на класа се описва нов тип данни:



class VehicleDemo

{

public static void Main()



{

Vehicle minivan = new Vehicle();

Vehicle sportscar = new Vehicle();

//Тук се създават 2 обекта с помощта на операцията new:

int range1, range2;

/*При създаване на екземпляр на класа се създава обект => всеки екземпляр съдържа свои собствени копия на променливите си. За достъп до тях се ползва операцията ‘.’. Тази операция свързва името на обекта с името на члена на класа. Операцията ‘.’ може да се използва за достъп както до променливите на екземпляра, така и до методите.*/

minivan.passengers = 7;

minivan.fuelcap = 16;

minivan.mpg = 21;

sportscar.passengers = 2;

sportscar.fuelcap = 14;

sportscar.mpg = 12;

/*Пресмятане на максималното растояние, което може да измине всеки от автомобилите ако има пълен резервоар.*/

range1 = minivan.fuelcap * minivan.mpg;

range2 = sportscar.fuelcap * sportscar.mpg;

Console.WriteLine("Микробусът може да превози " + minivan.passengers + " пътници на растояние " + range1 + " мили");

Console.WriteLine("Спортният автомобил може да превози " + sportscar.passengers + " пътници на растояния " + range2 + " мили");

}

}



В този пример, класовете Vehicle и VehicleDemo са различни самостоятелни класове. Единствената връзка между тях е, че в единия клас се създава екземпляр на другия клас. Макар че те са самостоятелни, кодът във VehicleDemo може да има достъп до членовете на Vehicle, тъй като те са public. В редa “Vehicle minivan = new Vehicle();” се извършват две действия:

  1. дефинира се променлива с име minivan от тип Vehicle, тази променлива не е непосредствено обект а съдържа адрес на обект;

  2. при изпълнението на new се създава обект чиито адрес се присвоява на minivan.

След изпълнението на кода от реда minivan ще бъде псевдоним на указател към обект от тип Vehicle. Операцията new динамично разпределя памет за обекта и връща адреса на тази област от паметта, който по-късно се съхранява в променлива т.е. за всички стойности в C# се заделя памет динамично. Двете стъпки за по нагледно могат да се запишат отделно:

Vehicle minivan;

minivan = new Vehicle();

Непосредствено след дефинирането на minivan, тя съдържа стойност null, което означава, че тя няма връзка с определен обект. Когато й се присвои адрес на даден обект, тогава тя има връзка с този обект. Тъй като достъпът до елементите на класа става чрез указател (reference), то класът е от reference-тип (указателен тип). Променлива от обикновен тип непосредствено съхранява стойността си, а променлива от указателен тип съхранява адрес на обект.

Фрагмент от програма:

Vehicle car1 = new Vehicle();

Vehicle car2 = car1;

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



Vehicle car3 = new Vehicle();

car2 = car3;

Сега car2 и car3 ще сочат към един и същи обект. Обектът към който сочи car1 не се променя.




10. Методи
Методите са подпрограми, които обработват данните дефинирани в класа.

Обикновено другите части на програмата взаимодействат с класа чрез методи. В добре написани програми всеки метод изпълнява само една задача. Общ вид на метод:



достъп тип_на_резултат име(списък_от_параметри)

{тяло_на_метода}

Името на метода е идентификатор, различен от метод с име Main, с който започва изпълнението на програмата. Достъпът е модификатор, който определя кои части от програмата имат видимост на метода. Ако достъпът се пропусне, то се подразбира private. Обикновено методите са public, т.е. те могат да бъдат извикани от всяко място на програмата. Типът на връщания резултат може да бъде вграден или дефиниран от потребителя. Ако метода не връща резултат, то той трябва да има тип “void”. Името на метода не трябва да съвпада с имената на други методи от класа, т.е. от същата област на видимост. Параметърът е от <тип> <идентификатор>. Ако методът няма параметри, то списъкът е празен.

Модификация на Vehicle, с добавен метод Range:

class Vehicle

{

public int passengers;



public int fuelcap;

public int mpg;

//дефиниране на Range

public void Range()

{

Console.WriteLine("Този автомобил може да измине с пълен резервоар " + fuelcap * mpg + " мили.");



}

}

Променливи fuelcap и mpg се използват непосредствено без да се използва оператора “.”. Методът с име “Range” няма параметри, не връща резултат, тъй като е тип void. Може да се извиква отвсякъде в програмата тъй като има достъп public.



class AddMeth

{

public static void Main()



{

Vehicle minivan = new Vehicle();

Vehicle sportscar = new Vehicle();

minivan.passengers = 7;

minivan.fuelcap = 16;

minivan.mpg = 21;

sportscar.passengers = 2;

sportscar.fuelcap = 14;

sportscar.mpg = 12;

Console.WriteLine("Микробусът може да превози " + minivan.passengers + " пътници.");

minivan.Range();

Console.WriteLine("Спортният автомобил може да превози " + sportscar.passengers + " пътници.");

sportscar.Range();

/*При извикване на Range() управлението се предава на този метод, след края му се връща на реда след него. Всеки път при извикване на метода Range, той ползва данните на обекта указан отляво на операцията*/

}

}

Методът приключва изпълнението си или когато се срещне затваряща фигурна скоба в края на тялото на метода, или когато се изпълни оператора return. Съществуват две форми на оператора return – първата се среща в методи имащи void тип, а втората – в методи, които връщат стойност. Първата форма на return:



public void myMeth()

{

int i;



for (i = 0; i < 10; i++)

{

if (i == 5)



return;

Console.WriteLine();

}

}

В един метод може да има няколко return;. Втората форма на return има следния общ вид:



return израз;

„Израз” е връщания резултат от метода. Стойността му се определя от типа на функцията.

Метода Range, пресмятащ стойността на максималното разстояние и го връща с return:

public int Range()

{

return fuelcap * mpg;



}

Методът Range може да бъде използван по следния начин:

class RetMeth

{

public static void Main()



{

Vehicle minivan = new Vehicle();

Vehicle sportscar = new Vehicle();

minivan.passengers = 7;

minivan.fuelcap = 16;

minivan.mpg = 21;

sportscar.passengers = 2;

sportscar.fuelcap = 14;

sportscar.mpg = 12;

int range1 = minivan.Range();

int range2 = sportscar.Range();

Console.WriteLine("Микробусът може да превози " + minivan.passengers + " пътници на растояние " + range1 + " мили");

Console.WriteLine("Спортният автомобил може да превози " + sportscar.passengers + " пътници на растояние " + range2 + " мили");

}

}



Тази програма може да се напише по-ефективно като вместо range1 и range2 направо да се извикат съответно minivan.Range() и sportscar.Range() в метода Console.WriteLine(). Освен това метода Range може да бъде извикан в произволно място на програмата, където е необходимо да се знае стойността на разстоянието:

if( v1.Range()>v2.Range() )

{

оператори

}

Ако компилаторът на C# открие в даден метод определен код, който не може да се изпълни, то той извиква предупреждение:

public void test()

{

char a, b;



...

if (a == b)

{

Console.WriteLine("Равни");



return;

}

else



{

Console.WriteLine("Различни");

return;

}

Оператор1



}

С „Оператор1” се извиква предупреждение.

Параметрите се дефинират в кръгли скобки, които са след името на метода. Синтаксисът за дефиниране на параметри е аналогичен на същия за дефиниране на променливи. Параметърът се намира в областта на видимост на своя метод. При изпълнение на метода, параметърът приема стойността на съответния си аргумент и като цяло се използва като всяка друга вътрешна или локална променлива. Стойността на аргумента се предава на метода при неговото извикване. Ще разгледаме един пример:

using System;

class ChkNum

{

public bool isEven(int x)



{

if (x % 2 == 0)

return true;

else


return true;

}

class ParDemo



{

public static void Main()

{

ChkNum e = new ChkNum();



if (e.isEven(10))

Console.WriteLine("Числото 10 е четно");

if (e.isEven(9))

Console.WriteLine("Числото 9 е четно");

}

};

}



Методът може да има няколко параметъра. Пример:

using System;

class Factor

{

public bool isFactor(int a, int b)



{

if (b % a == 0)

return true;

else


return false;

}

};



class isFact

{

public static void Main()



{

Factor x= new Factor();

if (x.isFactor(2, 20))

Console.WriteLine("2 е делител на 20");

if (x.isFactor(3, 20))

Console.WriteLine("3 е делител на 20");

}

}

Параметрите могат да бъдат от различни типове. Например:



int myMath(int a, double b, float c)

{

//...



}

Усъвършенстване на класът за Vehicle:

using System;
class Vehicle

{

public int passengers;



public int fuelcap; //капацитет на резервоара в галони

public int mpg; //miles per gallon

public int range()

{

return mpg * fuelcap;



}

public double fuelneeded(int miles)

{

return (double)miles / mpg;



}

};

class CompFuel



{

public static void Main()

{

Vehicle minivan=new Vehicle();



Vehicle sportcar=new Vehicle();

double gallons;

int dist=252;

minivan.passengers=7;

minivan.fuelcap=16;

minivan.mpg=21;

sportcar.passengers=2;

sportcar.fuelcap=14;

sportcar.mpg=12;

gallons=minivan.fuelneeded(dist);

Console.WriteLine("За да измине {0} мили, на микробуса са му нижни {1} галона гориво", dist, gallons);

gallons = sportcar.fuelneeded(dist);

Console.WriteLine("За да измине {0} мили, на спортната кола са й нужни {1} галона гориво", dist, gallons);

}

};




11. Конструктори и деструктори. Ключова дума this
В предишните примери променливите в обект от клас Vehicle бяха инициализирани ръчно със следната последователност от оператори:

minivan.passengers=7;

minivan.fuelcap=16;

minivan.mpg=21;

sportcar.passengers=2;

sportcar.fuelcap=14;

sportcar.mpg=12;

Такъв начин никога не се използва в професионално написани програми на C#. Тъй като, първо, при ръчно въвеждане винаги съществува вероятност от случайни грешки. Например да се забрави да се присвои стойност на някоя от променливите. И, второ, в С# е предвиден по-ефективен начин за решаване на тази задача, а именно използване на конструктор. Конструкторът на класа инициализира обекта при неговото създаване. Той има същото име като на класа и синтактично прилича на метод, но в конструкторите не се задава явно тип на връщания резултат. Той има следния общ вид:



Име_на_класа(списък_от_параметри)

{

тяло_на_конструктора;

}

Като правило, конструкторите се използват за присвояване на начални стойности на променливите в обект на класа и за изпълнение на всякакви други действия по инициализация, необходими за създаване на напълно сформиран обект. Всички класове имат конструктори, независимо от това дали те са дефинирани или не. По подразбиране в С# е предвидено наличието на конструктор, който присвоява нулеви начални стойности на всички променливи от обикновен тип в обекта и стойност null, за променливи от указателен тип. Ако в класа явно е дефиниран конструктор, то конструкторът по подразбиране не се използва. Да разгледаме един пример:

using System;
class MyClass

{

public int x;



public MyClass()

{

x = 10;



}

};

Конструкторът е дефиниран като public, тъй като се извиква от програмата извън границите на класа.



using System;
class MyClass

{

public int x;



public MyClass()

{

x = 10;



}

};
class ConstrDemo

{

public static void Main()



{

MyClass t1 = new MyClass();

MyClass t2 = new MyClass();

Console.WriteLine(t1.x + " " + t2.x);

}

};

Конструкторът се извиква от операцията new при създаване на обект. Тук той се извиква при създаване на обекта t1 и при създаване на обекта t2.



По-често се дефинира конструктор с параметри, които се използват както в метод. Да модифицираме нашия пример като за инициализиране на променливата х се използва конструктор с един параметър:

using System;


class MyClass

{

public int x;



public MyClass(int i)

{

x = i;



}

};
class ParamConstrDemo

{

public static void Main()



{

MyClass t1 = new MyClass(5);

MyClass t2 = new MyClass(10);

Console.WriteLine(t1.x + " " + t2.x);

}

};

Сега да добавим конструктор към класа Vehicle, който при създаване на обект автоматично да инициализира променливите passengers, fuelcap и mpg:



using System;
class Vehicle

{

public int passengers;



public int fuelcap; //капацитет на резервоара в галони

public int mpg; //miles per gallon

public Vehicle(int p, int f, int m)

{

passengers = p;



fuelcap = f;

mpg = m;


}

public int range()

{

return mpg * fuelcap;



}

public double fuelneeded(int miles)

{

return (double)miles / mpg;



}

};

class CompFuel



{

public static void Main()

{

Vehicle minivan = new Vehicle(7, 17, 21);



Vehicle sportcar = new Vehicle(2, 14, 21);

double gallons;

int dist = 252;

gallons = minivan.fuelneeded(dist);

Console.WriteLine("За да измине {0} мили, на микробуса са му нижни {1} галона гориво", dist, gallons);

gallons = sportcar.fuelneeded(dist);

Console.WriteLine("За да измине {0} мили, на спортната кола са й нужни {1} галона гориво", dist, gallons);

}

};



Операцията new има следния общ вид:

клас променлива=new клас(списък_от_аргументи);

Операцията new отделя динамично памет, т.е. по време на изпълнение на програмата за обект от зададения клас и връща адреса на разпределената памет, който се присвоява на променливата, която е от указателен тип. Също така, new извиква конструктора на класа, който използва списъка от аргументи за инициализация на създадения обект на класа. Ако няма достатъчно памет възниква изключителна ситуация при изпълнение на програмата.

Една от ключовите компоненти на схемата за динамично разпределение на паметта е механизмът за освобождаване на паметта, заемана от вече неизползвани обекти, за да може да се разпредели за отново създавани обекти. В много езици за програмиране освобождаването за динамично разпределена памет става ръчно. Например в С++ за освобождаване на памет се използва операцията delete. За тази цел С# разполага с по-ефективен механизъм, наречен „събиране на боклук” (garbage collector). Когато в програмата на С# отсъстват обръщения към обект, то той се разглежда като „неизползващ се повече” и системата автоматично, без участието на програмист, освобождава заеманата от него памет, която по-нататък може да бъде разпределена за други обекти. Събирането на боклука се извършва периодично, като за началото на тази операция трябва да са изпълнени две условия. Първо, наличие на обекти, които могат да бъдат махнати от паметта и, второ, да има необходимост от такава операция. Тъй като процесът на събиране на боклука заема определено време, то изпълнителната система осъществява операцията само в случай на необходимост, като програмиста не може да определи точно момента, в който това ще стане.

В С# е предвидена възможност да се създаде метод, който се извиква непосредствено преди отстраняването на обекта от паметта с помощта на операцията „събиране на боклука”. Този метод се нарича деструктор и може да се използва за гарантиране на коректното отстраняване на обекта от паметта. Например с помощта на деструктора може да се гарантира, че файлът, към който е имало обръщение от дадения обект ще бъде затворен. Деструкторът има следния общ вид:



~име_на_класа()

{

//тяло

}

Деструкторът се обявява по същия начин, както и конструктор, но с тази разлика, че пред името на класа се използва символа ~ (тилда) . Ще отбележим, че при дефиниране на деструктора не се задава тип на връщания резултат. Деструкторът е обикновен член на класа. Тялото на деструктора се дефинира като тяло на обикновен метод на класа. Деструктора се извиква винаги, когато обект на неговия клас трябва да бъде отстранен от паметта, непосредствено преди изпълнение на операцията „събиране на боклука”. По това деструктора в С# се отличава от същия в С++, където той се извиква, когато управлението излиза извън границите на областта на видимост, в която е бил създаден обекта. Това означава, че в С# е невъзможно да се определи точно кога ще се изпълни деструктора. Освен това, програмата може да завърши своята работа преди началото на операцията „събиране на боклука” и в този случай деструкторът въобще няма да бъде извикан. Ще разгледаме пример, в който се демонстрира използването на деструктор:

using System;
class Destruct

{

public int x;



public Destruct(int i)

{

x = i;



}

~Destruct()

{

Console.WriteLine("Отстраняване на обекта от паметта" + x);



}

public void generator(int i) //създава се обект, който веднага ще бъде

{ // унищожен, но не и веднага отстранен

Destruct o = new Destruct(i);

}

};

class DemoDestructor



{

public static void Main()

{

Destruct ob = new Destruct(0);



int count;

for (count = 1; count < 100000; count++)

ob.generator(count);
}

};

Отначало, в този клас се създава обекта ob от тип Destruct. След това с помощта на този обект и извикването на generator() се създават 100 000 обекта. На определен етап от изпълнението, обектите ще започнат не само да се създават, но и унищожават, като на различни етапи ще се изпълняват операциите „събиране на боклука”. Колко често и кога именно ще става това, зависи от няколко фактора, а именно начален обем на свободната памет, тип на ОС и т.н. Но от определен момент на екрана ще започне да се появява съобщение, генерирано от деструктора. Ако такива съобщения не се извеждат трябва да се увеличи броя на създаваните обекти, чрез увеличаване стойността на променливата count.



При извикване на метод на него автоматично се предава неявен аргумент, който е псевдоним на указател към обекта, за който е извикан метода. Този псевдоним на указател се нарича this. За да илюстрираме използването му, ще разгледаме пример, в който се изчислява повдигане на число в цяла степен.

using System;


class Pwr

{

public double b;



public int e;

public double val;

public Pwr(double num, int exp)

{

b = num; //this.b



e = exp; //this.e

val = 1;


if (exp == 0)

return;


for (; exp > 0; exp--)

val *= b; //this.val=this.val*this.b

}

public double getPwr()



{

return val; // this.val

}

};

class DemoPwr



{

public static void Main()

{

Pwr x = new Pwr(4.0, 2);



Pwr y = new Pwr(2.5, 1);

Pwr z = new Pwr(5.7, 0);

Console.WriteLine(x.b + " на степен " + x.e + " = " + x.getPwr());

Console.WriteLine(y.b + " на степен " + y.e + " = " + y.getPwr());

Console.WriteLine(z.b + " на степен " + z.e + " = " + z.getPwr());

}

};



Тук this сочи към обект, за който е бил извикан метода getPwr(). Например, ако методът е извикан за обекта х, то this ще сочи към х. Може да се каже, че записване на оператора, без използване на ключовата дума this е съкратена форма на записване, която винаги се използва от опитните програмисти.

В някои случаи, указателят this може да бъде полезен. Например, синтаксиса на С# позволява да се използват еднакви имена за параметрите или локалните променливи и за променливите на обекта. Когато това се случва, локалната променлива и параметъра скриват променливата на обекта и достъп до нея може да се получи като се използва this. Например, да разгледаме конструктор на класа Pwr, който е коректен, но такъв стил на програмиране не се препоръчва:

public Pwr(double b, int e)

{

this.b = b;



this.e = e;

val = 1;


if (e == 0)

return;


for (; e > 0; e--)

val *= b;

}

В тази версия на конструктора, имената на параметрите и имената на променливите на екземпляра са еднакви. Затова се налага използването на ключовата дума this.



Каталог: files -> lekcii
files -> Рецептура на лекарствените форми рецептурни бланки и тяхната валидност
files -> Прогностични възможности на тестовете, използвани за подбор на млади футболисти
files -> Правила за реда за ползване, стопаниване и управление на стадион "христо ботев" благоевград глава първа общи положения
lekcii -> Е п и с к о п к о н с т а н т и н п р е с л а в с к и
lekcii -> Лекции на IV курс, уктц правец Съдържание Подпрограми в паскал 3 Дефиниране на подпрограми 3
lekcii -> C# изборна дисциплина


Сподели с приятели:
1   2   3   4   5




©obuch.info 2024
отнасят до администрацията

    Начална страница