Не сте регистриран! Регистрирайте се БЕЗПЛАТНО, за да използвате услугите на сайта!

   Рубрики
 
 
 
 

 Форуми
» SEO и оптимизация
» Всичко за PHP и Perl
» Всичко за C, C++ и .NET
» Всичко за Java и JSP
» Всичко за SQL и MySQL
» Всичко за XHTML и CSS
» Презентация на сайтове
 Въвеждане на данни и Масиви
  1. Въвеждане на данни и Масиви
     
Автор  eminem (05.02.2005 12:22)  съобщение до автора
Погледнат  2685 пъти  добави към любими
Оценка  добави коментар
Гласове  1  изпрати на приятел
Коментари  (0)  абонирай се за Perl
    Страница 1 / 1

 



Въвеждане на данни

STDIN, filehandles

Понякога Вие трябва да контактувате с потребителя за да получите информация и да вършите действие с нея. Пробвайте това:
CODE
1
2
3
print "Please tell me your name: ";
$name=<STDIN>;
print "Thanks for making me happy, $name !n";

Има нови елементи, които трябва да научите тук. Първо <STDIN> . STDIN е filehandle. Filehandles са неща, които служат за да се взаймодейства с обектите като файлове, сокети, входни данни и др. Може да се каже, че STDIN е стандартната функция за вход. В този случай STDIN чете от клавиатурата (входните данни въведени от потребителя). Този тип скоби - <> чете данни от filehandle. И така ние прочитаме въведените данни от STDIN. Зададената стойност се установява на провенливата $name и принтирани. Някаква идея защо има още един ред. Като натиснете Enter, Вие включвате нов ред във вашите данни. Лесния начин да премахнете новия ред е чрез CODE
1
2
3
4
5
6
chop:
chop
print
"Please tell me your name: ";
$name=<STDIN>;
chop $name
print "Thanks for making me happy, $name !n"
и този код пропада поради синтактична грешка. Можете ли да познаете защо? Погледнете изведената информация, вижте номера на реда, където е открита грешката и вижте къде в синтаксиса сте сбъркали. Отговорът е в липсващите точка и запетая ( ; ) в края на последните два реда. Ако Вие добавите ; в края на трети ред, но не и на последния ред, тогава програматаще работи както трябва. Това е така защото Perl не се нуждае от ; на последния ред от блок. Препоръчвам винаги да се слага, най-малкото, защото е едно натискане на клавиш, а и след дадения код винаги може да добавите нещо без, ако сте пропуснали ; да търсите къде има синтактична грешка. Функцията chop премахва последния символ от всичко каквото и е дадено. В този случай премахва символа за нов ред. Кодът може да се съкрати, ето как:
CODE
1
2
3
print "Please tell me your name: ";
chop ($name=<STDIN>);
print "Thanks for making me happy, $name !";
Скобите ( ) принуждават chop да действа на резултата от това което е вътре в скобите. И така $name=<STDIN> се изпълнява първо, после резултата от това, който е $name със зададена стойност, после от тази стойност се премахва последния символ. Пробвайте без него. Може да прочетете от STDIN колкото пъти поискате. Вижте този код.
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
print "Please tell me your name: ";
chop ($name=<STDIN>);

print "Please tell me your nationality: ";
chop ($nation=<STDIN>);

if ($nation eq "British" or $nation eq "New Zealand") {
print "Hallo $name, pleased to meet you!n";

} elsif ($nation eq "Dutch" or $nation eq "Flemish") {
print "Hoi $name, hoe gaat het met u vandaag?!n";

} else {
print "HELLO!!! SPEAKEEE ENGLIEESH???n";
}

Премахването е опасно, в период когато най-важното нещо е сигурността при програмирането.
Безопасно премахване чрез chomp
Ние искаме да премахваме само символа за нов ред, а не безогледно, които и да е последен символ. Това може да стане с chomp - който премахва последния символ само, ако той е за нов ред.
chomp ($name=<STDIN>);
И тук Perl гурутата извикват "Открих грешка!". Е добре, chomp не винаги премахва последния символ, ако той е за нов ред, но ако не го премахне, Вие имате специалната променлива, наречена $/ .Като зададете нов символ на тази променлива, тази стойност става символа за нов ред, на която стойността по подразбиране е n.



Масиви
Какво са масивите?
В Perl има два типа масиви, асоциативни масиви (хешове) и масиви. И двата масива са списъци. Списъкът с сбор от променливи. Може да мислити за списъците в Perl като за стадо от животни. Списъка се обръща към цялото стадо, а скалара се обръща само към едно животно (Много МУУУУУУ стана,А?). Списъкът е стадо от променливи. Не е задължително променливите да бъдат от един и същи тип. Може да имате три скалара, два масива и три хеша в един масив. Всеки тип от списък си има свое име в Perl. Масивите представляват списък от стойности. Дефиницията на масив в другите езици е: съвкупност от еднотипни елементи (с еднаква големина). В Perl обаче всеки елемент може да е различен и с произволна дължина, следователно масивът е съставен от разнородни по състав елементи. За това често масивът е наричан списък. Масивите се означават с @ - която наподобява "a"(Аrray-масив).
Основи на работата с масиви
За пример, масива е списък от стойности. Списъка може да се обръща към целия списък или към отделни елементи от него. Скрипта по долу задава масива наречен @names . Зададени са 5 стойности в масива.
CODE
1
2
3
4
5
6
7
8
9
10
11
12
@names=("Muriel","Gavin","Susanne","Sarah","Anna");

print "The elements of @names are @namesn";
print "The first element is $names[0] n";
print "The third element is $names[2] n";
print 'There are ',scalar(@names)," elements in the arrayn";
Първо, забележете как се декларира масива -
@names . Всяка стойност е заградена в кавички "",а запетайката е подразбиращия се разделител за стойности в масива. След това забележете как се извежда. Първо се обръща към себе си като цяло в контекста на списък. Това означава , че се обръща към повече от една стойност. Вижте следващия код
@names=("Muriel","Gavin","Susanne","Sarah","Anna","Paul","Trish","Simon");

print @names;
print "n";
print "@names";
Когато списъка е между "" стойностите в него се извеждат с интервал между тях. Ако искаме да се обърнем към повече от една стойност от масива използваме @ . Когато се обръщате към повече от една стойност от масива, но не към целия масив, това се нарича дял, резен (slice) . Аналогията с кекс е подходяща. Парче от кекс е подходящо сравнение за дял.
Елементите на масива
Масивите не са много полезно нещо ако не можем да се обръщаме към стойностите в него. Първо ако извикваме единичен елемент от масив не трябва да използваме префикса @ който се използва за обръщение към няколко стойности. Ако ни трябва единична стойност, то това ще е скалар, а префикса за скалар е $ . Второ ние трябва да укажем, кой точно елемент искаме. Това е лесно - $array[0] за първия елемент, $array[1] за втория и т.н.. Индексът на списъците започва от 0, докато не направите нещо което да промени това (нещо, което е твърде нежелателно и противопоказно за добро и пълноценно програмиране). И последно, използвахме масива в скаларен контекст за да видим колко елемента има, чрез scalar(@names) в по-горния пример.

Как да се обръщаме към елементите на масив
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$myvar="scalar variable";
@myvar=("one","element","of","an","array","called","myvar");

print $myvar; # обръща се към скалар с името myvar
print $myvar[1]; # обръща се към втория елемент на масива myvar
print @myvar; # обръща се към всички елементи на масива myvar
Двете променливи нямат нищо общо помежду си. Ако се върнем към аналогията с животните, това е като да си имаш куче с име
'Myvar' и златна рибка 'Myvar'. Вие никога няма да ги сбъркате, нали?
Номерът на елемента от масив, който извикваме може да бъде променлива.
print "Enter a number :";
chomp ($x=<STDIN>);

@names=("Muriel","Gavin","Susanne","Sarah","Anna");

print "You requested element $x who is $names[$x]n";

print "The index number of the last element is $#names n";
Забележете последния ред на примера. Връща индекса на последния елемент на масива. Същото може да го направите и с $last=scalar(@names)-1; но това не е толкова ефективно. Има по-лесен начин да получите последния елемент на масива, както ще видите:
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
print "Enter the number of the element you wish to view :";
chomp ($x=<STDIN>);

@names=("Muriel","Gavin","Susanne","Sarah","Anna","Paul","Trish","Simon");

print "The first two elements are @names[0,1]n";
print "The first three elements are @names[0..2]n";
print "You requested element $x who is $names[$x-1]n"; # започва от 0
print "The elements before and after are : @names[$x-2,$x]n";
print "The first, second, third and fifth elements are @names[0..2,4]n";

print "a) The last element is $names[$#names]n"; # първи начин
print "b) The last element is @names[-1]n"; # втори начин
Забележете, че имате две стойности разделени от многоточие. Това дава всички стойности от първата до последната между двете числа.
[0..3] означава 0, 1, 2, 3 .Когато за индекс се използва отрицателно число, стойностите на масива се взимат отзад напред, -1 е за последната стойност, -2 за предпоследната и т.н.
За циклите
Всичко дотук е добре, но как ние да изведем всички елементи на масив един след друг? Решението е в следващия пример:
@names=("Muriel","Gavin","Susanne","Sarah","Anna","Paul","Trish","Simon");

for ($x=0; $x <= $#names; $x++) {
print "$names[$x]n";
}

което задава на $x стойност 0, прави един цикъл, прибавя единица към $x , проверява дали е по-малка или равна на $#names , и т.н.. Това е пример за цикъл. За да бъде по-детайлно, цикъла има три части:
•    Инициализация
•    Проверка на условието
•    Модификация
В този случай, променливата $x е инициализирана на 0. След това веднага е проверена дали е по-малка или равна на $#names . Ако е истина, блокът се изпълнява веднъж. Ако условието не е изпълнено и блока не се изпълнява.
Един път след като блока се изпълни, променливата се модифицира. Това е $x++ . След това теста за изпълнение на условието се изпълнява и т.н..
За циклите с .. - оператор за поредица
Има и друг начин за написването на по-горния код:
CODE
1
2
3
for $x (0 .. $#names) {
print "$names[$x]n";
}

който използва оператора за поредица .. (две точки една до друга). Това просто задава на $x стойност 0, после увеличава $x с 1 докато стане равно на $#names . През цялото това време изпълнява блока по веднъж на всяко увеличаване с единица.
CODE
1
2
3
4
5
foreach
За по-добър код използваите
foreach .
foreach $person (@names) {
print "$person";
}

Цикъла минава през всеки елемент ('многократно повторение', друго техническо описание на процеса) на масива @names , и всеки елемент се връща като стойност на променливата $person . След това може да извършвате всякакви действия с променливата. Вие може да използвате и:
CODE
1
2
3
for $person (@names) {
print "$person";
}
ако искате. Няма разлика като цяло, но кода изглежда малко по-неясен.
Невероятното $_
За да намалим кода , ще Ви преставя $_ , които е входа по подразбиране и шаблонна променлива.
CODE
1
2
3
foreach (@names) {
print "$_";
}

Ако Вие не зададете променлива в която да се присвояват като стойности, елементите на масива , $_ се използва по подразбиране за тази и много, много други операции в Perl. Още един пример с функцията print:
CODE
1
2
3
foreach (@names) {
print ;
}

Ние не определяме кой елемент да се принтира, затова $_ се изпозва по подразбиране. По дефиниция ако на print не е зададена променлива, тя използва стойността, която се намира в специалната променлива $_.
Преждевременен край на повторения
Процесът на повторенията завършва при постигането на някакво условие зададено първоначално или въобще не завършва. Следващия скрипт е пример за непрекъсваем процес, защото 1 е истина и условието е винаги истана.
CODE
1
2
3
4
while (1) {
$x++;
print "$x: Знаете ли че може чрез натискане на CTRL-C да прекъснете изпълнението на perl скрипт? n";
}

Друг начин да излезете от процеса е, ако при изреждането на елементите на масива намерим този, който ни трябва и продължаването на процеса се обезмисля.
CODE
1
2
3
4
5
6
@names=('Mrs Smith','Mr Jones','Ms Samuel','Dr Jansen','Sir Philip');

foreach $person (@names) {
print "$personn";
last if $person=~/Dr /;
}

Оператора last изпълнява функцията прекъсване на процеса и излизане от цикъла. Не се тревожете за /Dr / това е регулярен израз, който ще бъде обяснен по-късно. Всичко, което трябва да знаете засега е, че връща истина ако намери съвпадение между това в скобите и подадената променлива. В случая когато открие съвпадение подава истина и функцията last се изпълнява. Контрол върху функцията last се извършва чрез етикети.
Засега е просто, но почакайте! Ние се нуждаем от лекар, който го има и в списъка с имена, не просто само лекар. Следващия пример е за това:
CODE
1
2
3
4
5
6
7
8
9
10
11
12
@names =('Mrs Smith','Mr Jones','Ms Samuel','Dr Jansen','Sir Philip');
@medics =('Dr Black','Dr Waymour','Dr Jansen','Dr Pettle');

foreach $person (@names) {
print "$personn";
if ($person=~/Dr /) {
foreach $doc (@medics) {
print "t$docn";
last if $doc eq $person;
}
}
}

Първо се взима първия елемент на масива @names, изписва се на екрана, и след това се проверява за съвпадение с Dr, ако се открие съвпадение се изпълнява следващия блок. В него се изреждат всички елементи на масива @medics, и ако се открие, че съдържанието на променливата $doc съвпада със съдържанието на променливата $person се прекъсва изпълнението на този блок и се преминава към външния цикъл с нова променлива $person.

Но има малък проблем, ние искаме при намиране на съвпадение да прекъснем изцяло цикъла, а не само изпълнението на вътрешния цикъл. Трябва да укажем на функцията last, кое точно искаме да прекъснем. Това става чрез етикети, като във следващия пример:
CODE
1
2
3
4
5
6
7
8
9
10
11
12
@names =('Mrs Smith','Mr Jones','Ms Samuel','Dr Jansen','Sir Philip');
@medics =('Dr Black','Dr Waymour','Dr Jansen','Dr Pettle');

LBL: foreach $person (@names) {
print "$personn";
if ($person=~/Dr /) {
foreach $doc (@medics) {
print "t$docn";
last LBL if $doc eq $person;
}
}
}

Има само две промени тук. Дефинирали сме етикет с името LBL. Когато укажем на last даден етикет, той прекъсва функцията, на която е зададен първоначално този етикет.

Има още две функции за работа с цикли redo и goto. Redo връща на току-що изпълнилото се $_. Goto изпраща към друг цикъл, подпрограма или израз за изчисляване. Не се препоръчва използването му.
Промяна на елементите на масив
И така имаме масива @names. Искаме да го променим. Пробвайте следващия код:
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
print "Enter a name :";
chomp ($x=<STDIN>);

@names=("Muriel","Gavin","Susanne","Sarah");

print "@namesn";

push (@names, $x);

print "@namesn";
Push функцията прибавя нова стойност към края на масива. Разбира се може да не е само една стойност:
print "Enter a name :";
chop ($x=<STDIN>);

@names=("Muriel","Gavin","Susanne","Sarah");
@cities=("Brussels","Hamburg","London","Breda");

print "@namesn";

push (@names, $x, 10, @cities[1..3]);

print "@namesn";
Нови функции за работа с масив:

@names=("Muriel","Gavin","Susanne","Sarah");
@cities=("Brussels","Hamburg","London","Breda");

&
look;

$last=pop(@names);
unshift (@cities, $last);

&
look;

sub look {
print "Names : @namesn";
print "Cities: @citiesn";
}

Сега имаме два масива. pop функцията премахва последния елемент на масив и го връща, което означава че може да извършите някакви действия с върнатата стойност. Функцията unshift прибавя стойност в началото на масив. В таблицата по долу са изборени функциите, които се използват за работа с масив.
push    Прибавя стойност към края на масив.
pop    Премахва и връща последната стойност на масив.
shift    Премахва и връща първата стойност на масив.
unshift    Прибавя стойност към началото на масива.


Сега за достъпа до другите елементи на масива. Ще Ви представя функцията splice.
CODE
1
2
3
4
5
6
7
8
9
10
11
12
@names=("Muriel","Sarah","Susanne","Gavin");

&
look;

@middle=splice (@names, 1, 2);

&
look;

sub look {
print "Names : @namesn";
print "The Splice Girls are: @middlen";
}

Първия аргумент на функцията splice е масив. Втората стойност е индекс (число) показващо, коя стойност от списъка (масива) да се използва за начало. В този случай тя е 1 (ще се започне от втория елемент). После идва елемента, който показва колко елементи да се премахнат от масива и да се прибавят към втория.
Ако използвате резултата от splice като скалар:
CODE
1
2
3
4
5
6
7
8
9
10
11
12
@names=("Muriel","Sarah","Susanne","Gavin");

&
look;

$middle=splice (@names, 1, 2);

&
look;

sub look {
print "Names : @namesn";
print "The Splice Girls are: $middlen";
}

тогава скалара взема като стойност последната му подадена стойност. Функцията splice се използва и за триене на елементи от масив.
Триене на променливи от масив
Искаме да изтрием Hamburg от масива. Как да го направим? Може би ето така:
CODE
1
2
3
4
5
6
7
8
9
10
11
@cities=("Brussels","Hamburg","London","Breda");

&
look;

$cities[1]="";

&
look;

sub look {
print "Cities: ",scalar(@cities), ": @citiesn";
}

Разбира се Hamburg е премахнат, но забележете, броят на елементите остана един и същ. Все още има 4 елемента в масива. Резултата от горния код е, че $cities[1], съществува но няма стойност. И така ние трябва да използваме splice функцията за да премахнем елемента изцяло.
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
splice (@cities, 1, 1);
Сега нека пробваме друго:
$car ="Porsche 911";
$aircraft="G-BBNX";

&
look;

$car="";

&
look;

sub look {
print "Car :$car: Aircraft:$aircraft:n";
print "Aircraft exists !n" if $aircraft;
print "Car exists !n" if $car;
}
Изглежда че сме изтрили променливата $car. Но не точно. Ние сме изтрили стойността, която тя има, но не и самата променлива. В момента тя има стойност null и затова теста с if пропада. Само ако нещо дава като отговор грешка, то това не означава, че не съществува. Перуката е фалшива коса, но перуката съществува. Вашата променлива е все още там. Perl има функция, която да тества дали нещо съществува. Съществувам, в превод на Perl означава дефиниран (defined):
print "Car is defined !n" if defined $car;
Този код ще върне истина. Примерите дотук поставят въпроса, всъщност как да премахнем невъзвратимо една променлива. Много просто, ето как:
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$car ="Porsche 911";
$aircraft="G-BBNX";

&
look;

undef $car;

&
look;

sub look {
print "Car :$car: Aircraft:$aircraft:n";
print "Aircraft exists !n" if $aircraft;
print "Car exists !n" if $car;
}

Променливата $car е унищожена, тя липсва.
Флагове
Вие знаете, че може да пуснете режима с повече предупреждения и обяснения при грешки с -w от командния ред. Всяка опция на perl, която може да се зададе от командния ред, може да се зададе и в кода на скрипта.
perl script.pl hello
за да изпълни този код:
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!perl -w

@input=@ARGV;

$outfile='outfile.txt';
open OUT, ">$outfile" or die "Can't open $outfile for write:$!n";

$input2++;
$delay=2 if $input[0] eq 'sleep';

sleep $delay;

print "The first element of @input is $input[0]n";
print OUY "Slept $delay!n";
който ще се стартира по-същия начин , ако го стартирате така:
perl -w script.pl hello
Много по-удобно е да се слагат флагове вътре в скриптовете. Не е задължително да е -w , може да е всеки аргумент който Perl поддържа. Стартирайте
perl -h
за пълния списък на аргументите.
use strict;
Какво е това строгост (strict) и как да я използваме? Модулът strict ограничава 'несигурните, опасните конструкции', съгласно perl документацията. Няма смисъл да се притеснявате за опасни конструкции, ако сте прекарали часове наред в дебъгване на кода си. Когато включите модула strict , има три неща които Perl държи да са зададени точно:
•    Променливите 'vars'
•    Референциите 'refs'
•    Подпрограмите 'subs'
При използването на този модул трябва променливите да се декларират преди използването им, като всяка променлива се дефинира с my . Това е пример за програма, която не използва стриктен режим:
perl script.pl "Alain James Smith";
където "" затваря стринга като единичен параметър, иначе той ще се разглежда като три параметъра.
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#use strict; # махнете '#' след като стартирате кода няколко пъти

$name=shift; # дава първия аргумент от масива @ARGV

print "The name is $namen";
$inis=&initials($name);

$luck=int(rand(10)) if $inis=~/^(?:[a-d]|[n-p]|[x-z])/i;

print "The initials are $inis, lucky number: $luckn";

sub initials {
my $name=shift;
$initials.=$1 while $name=~/(w)w+s?/g;
return $initials;
}
Вие вече трябва да разбирате какво върши по-горния код. Когато премахнете '#' пред use strict; и стартирате кода отново, Вие ще получите изход подобен на този:

Global symbol "$name" requires explicit package name at n1.pl line 3.
Global symbol "$inis" requires explicit package name at n1.pl line 6.
Global symbol "$luck" requires explicit package name at n1.pl line 8.
Global symbol "$initials" requires explicit package name at n1.pl line 14.
Execution of n1.pl aborted due to compilation errors.

Тези предупреждения означават, че на Perl не му е ясно какъв е обсега на действие на тези променливи. Това означава, че Вие трябва да декларирате всяка една от тях с my, за да ограничите изпълнението им в дадения блок, в който се използват, или да им се зададе референцията с тяхното пълно име. В долния пример се използват и двата метода:
use strict;

CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$MAIN::name=shift; # shifts @ARGV if no arguments supplied

print "The name is ",$MAIN::name,"n";
my $inis='';
my $luck='';

$inis=&initials($MAIN::name);

$luck=int(rand(10)) if $inis=~/^(?:[a-d]|[n-p]|[x-z])/i;

print "The initials are $inis, lucky number: $luckn";

sub initials {
my $name=shift;
my $initials;
$initials.=$1 while $name=~/(w)w+s?/g;
return $initials;
}
Използването на my в подпрограма не е нищо ново за вас, а my извън подпрограма вече е. Ако се замислите цялата програма е един блок, така че може да се зададе променливите да се виждат само в този блок. Друга интересна част от кода е $MAIN::name. Това както може би очаквате е пълното име на променливата. Първата част е името на пакета, в случая MAIN (главния, основния). Втората част е името на променливата.



   


Ключови думи: perl програмиране данни паскал въвеждане


Още уроци от тази рубрика


 
  • Подобни теми от myLinks
 

 1 посетител чете този урок (0 потребители и 1 гост)  
Активни потребители: ---
   
  

Еmail  
 

 

 
  • Интересно от Софтуер