2011-09-03 13 views
7

Jestem teraz na przerwie od zajęć i postanowiłem spędzić czas na nauce Perla. Pracuję z Beginning Perl (http://www.perl.org/books/beginning-perl/) i kończę ćwiczenia na końcu trzeciego rozdziału.Szukam wyjaśnienia na temat chomp

Jedno z ćwiczeń zadawało mi pytanie "Zapisuję twoje ważne numery telefonów w haśle. Napisz program, aby wyszukać numery według nazwiska osoby".

W każdym razie, ja wymyślił to:

#!/usr/bin/perl 
use warnings; 
use strict; 

my %name_number= 
(
Me => "XXX XXX XXXX", 
Home => "YYY YYY YYYY", 
Emergency => "ZZZ ZZZ ZZZZ", 
Lookup => "411" 
); 

print "Enter the name of who you want to call (Me, Home, Emergency, Lookup)", "\n"; 
my $input = <STDIN>; 
print "$input can be reached at $name_number{$input}\n"; 

A to po prostu nie będzie działać. Ciągle otrzymuję ten komunikat o błędzie: (.) ​​

wykorzystanie wartości niezainicjowanych w konkatenacji lub ciąg w hello.plx linii 17, wiersz 1

Próbowałem odtwarzanie z kodem nieco więcej, ale każde "rozwiązanie" wyglądało na bardziej złożone niż "rozwiązanie", które było przed nim. W końcu postanowiłem sprawdzić odpowiedzi.

Jedyną różnicą między moim kodem a odpowiedzią była obecność chomp ($input); po <STDIN>;.

Teraz autor użył wcześniejszego przykładu chomp, ale tak naprawdę nie wiedział, co robi chomp. Tak, znalazłem to odpowiedź na www.perlmeme.org:

Funkcja chomp() usunie (zazwyczaj) dowolny znak nowej linii z końcu łańcucha. Powodem mówimy zazwyczaj jest to, że faktycznie usuwa dowolny znak, który odpowiada aktualnej wartości $/ (rekord separatora wejście ) i $/ domyślne do nowej linii ..


W każdym razie, moje pytania są :

  1. Jakie nowe linie są usuwane? Czy Perl automatycznie dołącza "\n" do wejścia z <STDIN>? Jestem trochę niejasna, ponieważ kiedy przeczytałem "to faktycznie usuwa jakąkolwiek postać, która pasuje do aktualnej wartości $/", nie mogę pomóc, ale myślę "nie pamiętam umieszczania $/ w moim kodzie."

  2. Chciałbym opracować najlepsze praktyki tak szybko, jak to możliwe - czy najlepiej jest zawsze dodawać chomp po <STDIN> lub czy istnieją scenariusze, w których nie jest to konieczne?

+2

'perldoc -f chomp' lub [perlfunc] (http://perldoc.perl.org/perlfunc.html) –

+0

Ok, więc wejście chomp w Perlmeme w FAQ (http: //www.perlmeme.org/faqs/manipulating_text/chomp.html) odpowiada na większość mojego pierwszego pytania. Oznacza to, że najczęściej zadawane pytania pozwalają mi sądzić, że Perl automatycznie tworzy nowy znak (niekoniecznie w "\ n", ale znak nowej linii jest taki sam). Ale czy rozumiem to poprawnie? – krebshack

+0

Kontynuacja z linkiem z perlfunc: [chomp] (http://perldoc.perl.org/functions/chomp.html), który opisuje użycie separatora. –

Odpowiedz

9

<STDIN> czyta do końca ciągu wejściowego, który zawiera znak nowej linii, jeśli naciśniesz powrót do niego wejść, które prawdopodobnie nie.

chomp usuwa znak nowej linii na końcu łańcucha. $/ jest zmienną (jak można znaleźć, domyślną do nowej linii), która prawdopodobnie nie musisz się martwić; po prostu informuje perla, co to jest "separator rekordów wejściowych", co zakładam, że definiuje, jak daleko sięga <FILEHANDLE>. Na razie można o tym zapomnieć, wydaje się, że jest to zaawansowany temat.Po prostu udawaj, że chomp chomps z końcowego znaku nowej linii. Szczerze mówiąc, nigdy wcześniej nie słyszałem o $/.

Co do drugiego pytania, ogólnie rzecz biorąc czystsze jest zawsze, aby zawsze wyszukiwać zmienne i dodawać nowe wiersze w razie potrzeby później, ponieważ nie zawsze wiadomo, czy zmienna ma znak nowej linii; za pomocą zawsze chomping zmiennych zawsze masz takie samo zachowanie. Istnieją sytuacje, w których nie jest to konieczne, ale jeśli nie masz pewności, że nie zaszkodzi to chomp.

Mam nadzieję, że to pomoże!

+1

" odczytuje koniec łańcucha wejściowego, który zawiera znak nowej linii, jeśli naciśniesz klawisz Return, aby go wprowadzić, co prawdopodobnie." To dużo wyjaśnia. Nie pamiętam, aby autor wspomniał, że naciśnięcie klawisza Return po wprowadzeniu mojego wejścia do automatycznie zawiera znak nowej linii. Chociaż to tłumaczy, dlaczego tworzono znak nowej linii, mimo że nie napisałem (świadomie) kodu do kodu. Dzięki za pomoc. – krebshack

+1

@kreb - to nie jest tak naprawdę specyficzne dla Perla - zachowanie linii nowej jest specyficzne dla systemu operacyjnego (i większość systemów operacyjnych to zrobi, chociaż różne systemy operacyjne mają różne znaki nowej linii - właśnie tam pojawia się '$ /'. Nowa linia linii Windows/DOS różni się od nowej linii Unix Na szczęście dla ciebie, Perl po prostu działa - mianowicie, Windows Perl ustawi '$ /' na newline z Windows Zobacz wspaniałą odpowiedź shawnhcorey poniżej – DVK

0

myślę najlepszą praktyką jest, aby napisać:

chomp(my $input = <STDIN>); 

Oto krótki przykład jak chomp function ($/ znaczenie jest tam wyjaśnione) działa usuwając tylko jeden spływu nowej linii (jeśli występują):

chomp (my $input = "Me\n"); # OK 
chomp ($input = "Me"); # OK (nothing done) 
chomp ($input = "Me\n\n"); # $input now is "Me\n"; 
chomp ($input); # finally "Me" 

print "$input can be reached at $name_number{$input}\n"; 

BTW: To zabawne, że uczę się również Perla i dotarłem do haszów pięć minut temu.

+0

Och, to jest zabawne.Jakie zasoby wykorzystujesz? Uważam, że pomocny jest dostęp do wiele tutoriali/książek/stron internetowych, kiedy mogę się czegoś nauczyć – krebshack

+0

@krebshack: Używam głównie [Perl uczący] (http://oreilly.com/catalog/0636920018452?green=c142e8ee-fefc-4f4d- 80d1-fb6d1f20e787 & cmp = af-mybuy-0636920018452.IP) (z [Safari Books] (http://my.safaribooksonline.com/)), a czasami [perldoc] (http://perldoc.perl.org/). –

+0

Będę musiał to sprawdzić, kiedy przyjdzie kolejna wypłata. Nie miałem nic oprócz pozytywnego expe rary z O'Reilly's. – krebshack

3

OK, od 1), perl nie dodaje żadnego \n na wejściu. To Ty uderzyłeś Wpisz po zakończeniu wprowadzania numeru. Jeśli nie podasz parametru $/, zostanie ustawione domyślne ustawienie \n (przynajmniej w systemie UNIX).

Od 2), chomp będzie potrzebny, ilekroć dane wejściowe pochodzą od użytkownika, lub kiedy chcesz usunąć znak końca linii (np. Odczyt z pliku).

Wreszcie, błąd, który otrzymujesz, może pochodzić od perla, który nie rozumie twojej zmiennej w podwójnych cudzysłowach ostatniego print, ponieważ ma znak _. Spróbuj napisać ciąg w następujący sposób:

print "$input can be reached at ${name_number{$input}}\n"; 

(zanotować {} wokół ostatniej zmiennej).

+0

Nie jestem pewien. Próbowałem zastąpić ciąg "print" $ input ... "z" with print "" wejście $ można uzyskać na $ {name_number {$ input}} \ n ";" i powrócił te same wyniki, gdy po nastąpił chomp. Zwrócił również ten sam komunikat o błędzie, gdy nie było śledzone przez chomp. Ale czy pisanie sznurków powinno być takim nawykiem, do którego powinienem się wtrącać? – krebshack

+0

Dlaczego double * double * cytuje? Jeśli chodzi o zmienne, to tak, zmienne ze znakami specjalnymi, takie jak '_', powinny być otoczone przez' {} 'jeśli są w podwójnych cudzysłowach. –

+0

Dobra, dobrze wiedzieć. Usuwam podwójne podwójne cudzysłowy. To literówka. – krebshack

0

Chociaż może być oczywiste, nadal warto wspomnieć o , dlaczego potrzebne jest tutajchomp.

Haszysz stworzony zawiera 4 klawisze odnośników: "Me", "Home", "Emergency" i "Lookup"

Kiedy $input jest określona z <STDIN>, będzie ona zawierać "Me\n", "Me\r\n" lub jakiś inny wariant kończących wiersz w zależności od systemu operacyjnego używane.

Błąd niezainicjowanej wartości pojawia się, ponieważ klucz "Me\n" nie istnieje w haszdzie. A to dlatego chomp jest potrzebne:

my $input = <STDIN>; # "Me\n" --> Key DNE, $name_number{$input} not defined 
chomp $input;  # "Me" --> Key exists, $name_number{$input} defined 
2

<STDIN> jest notacja short-cut dla readline(*STDIN);. Funkcja readline() odczytuje uchwyt pliku, dopóki nie napotka treści $/(aka $ INPUT_RECORD_SEPARATOR) i zwróci wszystko, co przeczytał, łącznie z zawartością $ /. To, co robi chomp(), usuwa ostatnią zawartość $ /, jeśli jest obecna.

Zawartość jest często nazywana znakiem nowej linii, ale może składać się z więcej niż jednego znaku. W systemie Linux zawiera znak LF, ale w systemie Windows zawiera CR-LF.

Patrz:

perldoc -f readline 
perldoc -f chomp 
perldoc perlvar and search for /\$INPUT_RECORD_SEPARATOR/ 
Powiązane problemy