📄 ch8.htm
字号:
<P>There is one more twist that I would like to show you using thisdata structure. Let's see how to dynamically add information.First, we'll look at adding an entire data record, and then we'lllook at adding new members to an existing data record. Listing8.7 shows you can use a standard hash assignment to dynamicallycreate a data record.<P><IMG SRC="pseudo.gif" BORDER=1 ALIGN=RIGHT><p><BLOCKQUOTE><I>Assign a refereNCe to a hash to the "MRD-300" keyin the </I><TT><I>%database </I></TT><I>associativearray.<BR>Assign the refereNCe to the hash associated with the key "MRD-300"to the </I><TT><I>$refCustomer</I></TT><I>variable.<BR>Print the value associated with the key "Name" insidehash refereNCed by </I><TT><I>$refCustomer</I></TT><I>.<BR>Print the value associated with the key "Address" insidehash refereNCed by </I><TT><I>$refCustomer</I></TT><I>.</I></BLOCKQUOTE><HR><BLOCKQUOTE><B>Listing 8.7 08LST07.PL-Creating a Record Using HashAssignment<BR></B></BLOCKQUOTE><BLOCKQUOTE><PRE>$database{"MRD-300"} = { "Name" => "Nathan Hale", "Address" => "999 Centennial Ave.", "Town" => "AnyTown", "State" => "AnyState", "Zip" => "12345-1234"};$refCustomer = $database{"MRD-300"};print(%{$refCustomer}->{"Name"} . "\n");print(%{$refCustomer}->{"Address"} . "\n");</PRE></BLOCKQUOTE><HR><P>This program displays:<BLOCKQUOTE><PRE>Nathan Hale999 Centennial Ave.</PRE></BLOCKQUOTE><P>Notice that by using a temporary variable (<TT>$refCustomer</TT>),the program code is more readable. The alternative would be this:<BLOCKQUOTE><PRE>print(%{$database{"MRD-300"}}->{"Name"} . "\n");</PRE></BLOCKQUOTE><P>Most programmers would agree that using the temporary variableaids in the understanding of the program.<P>Our last data structure example will show how to add members toan existing customer record. Listing 8.8 shows how to add twophone number members to customer record MRD-300.<P><IMG SRC="pseudo.gif" BORDER=1 ALIGN=RIGHT><p><BLOCKQUOTE><I>Assign a refereNCe to an anonymous fuNCtion to </I><TT><I>$codeRef</I></TT><I>.This fuNCtion will print the elements of the </I><TT><I>%database</I></TT><I>hash. Because each value in the </I><TT><I>%database</I></TT><I>hash is a refereNCe to another hash, the fuNCtion has an innerloop to derefereNCe the sub-hash.<BR>Assign a refereNCe to a hash to the "MRD-300" key inthe </I><TT><I>%database </I></TT><I>associativearray.<BR>Call the anonymous routine by derefereNCing </I><TT><I>$codeRefto print the contents of %database</I></TT><I>. This isdone by surrounding the code refereNCe variable with curly bracesand prefixing it with a </I><TT><I>&</I></TT><I>to indicate that it should be derefereNCed as a fuNCtion.<BR>Assign the refereNCe to the hash associated with the key "MRD-300"to the </I><TT><I>$refCustomer</I></TT><I>variable.<BR>Add "Home Phone" as a key to the hash associated withthe "MRD-300" key.<BR>Add "Business Phone" as a key to the hash associatedwith the "MRD-300" key.<BR>Call the anonymous routine by derefereNCing </I><TT><I>$codeRefto print the contents of %database</I></TT><I>.</I></BLOCKQUOTE><HR><BLOCKQUOTE><B>Listing 8.8 08LST08.PL-How to Dynamically Add Membersto a Data Structure<BR></B></BLOCKQUOTE><BLOCKQUOTE><PRE>$codeRef = sub { while (($key, $value) = each(%database)) { print("$key = {\n"); while (($innerKey, $innerValue) = each(%{$value})) { print("\t$innerKey => $innerValue\n"); } print("};\n\n"); }};$database{"MRD-300"} = { "Name" => "Nathan Hale", "Address" => "999 Centennial Ave.", "Town" => "AnyTown", "State" => "AnyState", "Zip" => "12345-1234"};# print database before dynamic changes.&{$codeRef};$refCustomer = $database{"MRD-300"};%{$refCustomer}->{"Home Phone"} = "(111) 511-1322";%{$refCustomer}->{"Business Phone"} = "(111) 513-4556";# print database after dynamic changes.&{$codeRef};</PRE></BLOCKQUOTE><HR><P>This program displays:<BLOCKQUOTE><PRE>MRD-300 = { Town => AnyTown State => AnyState Name => Nathan Hale Zip => 12345-1234 Address => 999 Centennial Ave.};MRD-300 = { Town => AnyTown State => AnyState Name => Nathan Hale Home Phone => (111) 511-1322 Zip => 12345-1234 Business Phone => (111) 513-4556 Address => 999 Centennial Ave.};</PRE></BLOCKQUOTE><P>This example does two new things. The first thing is that it usesan anonymous fuNCtion refereNCed by <TT>$codeRef</TT>.This is done for illustration purposes. There is no reason touse an anonymous fuNCtion. There are actually good reasons foryou not to do so in normal programs. I think that anonymous fuNCtionsmake programs much harder to understand.<BR><p><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR><TD><B>Note</B></TD></TR><TR><TD><BLOCKQUOTE>When helper fuNCtions are small and easily understood, I like to place them at the beginning of code files. This helps me to quickly refresh my memory when coming back to view program code after time spent doing other things.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><P>The second thing is that a regular hash assignment statement wasused to add values. You can use any of the array fuNCtions withthese nested data structures.<H3><A NAME="ExampleInterpolatingFuNCtionsInsideDoubleQuotedStrings">Example: Interpolating FuNCtions Inside Double-Quoted Strings</A></H3><P>You can use refereNCes to force Perl to interpolate the returnvalue of a fuNCtion call inside double-quoted strings. This helpsto reduce the number of temporary variables needed by your program.<P><IMG SRC="pseudo.gif" BORDER=1 ALIGN=RIGHT><p><BLOCKQUOTE><I>Call the </I><TT><I>makeLine()</I></TT><I>fuNCtion from inside a double-quoted string.<BR>Define the </I><TT><I>makeLine()</I></TT><I>fuNCtion.<BR>Return the dash character repeated a specified number of times.The first element in the parameter array is the number of timesto repeat the dash.</I></BLOCKQUOTE><BLOCKQUOTE><PRE>print("Here are 5 dashes ${\makeLine(5)}.\n");print("Here are 10 dashes ${\makeLine(10)}.\n");sub makeLine { return("-" x $_[0]);}</PRE></BLOCKQUOTE><P>This program displays:<BLOCKQUOTE><PRE>Here are 5 dashes -----.Here are 10 dashes ----------.</PRE></BLOCKQUOTE><P>The trick in this example is that the backslash turns the scalarreturn value into a refereNCe, and then the dollar sign and curlybraces turn the refereNCe back into a scalar value that the <TT>print()</TT>fuNCtion can interpret correctly. If the backslash character isnot used to create the refereNCe to the scalar return value, thenthe <TT>${}</TT> derefereNCing operationdoes not have a refereNCe to derefereNCe, and you will get an"initialized value" error.<H2><A NAME="Summary"><FONT SIZE=5 COLOR=#FF0000>Summary</FONT></A></H2><P>In this chapter you learned about refereNCes. RefereNCes are scalarvariables used to hold the memory locations. When refereNCes arederefereNCed, the actual value is returned. For example, if thevalue of the refereNCe is assigned like this: <TT>$refScalar= \10</TT>, then, derefereNCing <TT>$refScalar</TT>would be equal to 10 and would look like this <TT>${$refScalar}</TT>.You always can create a refereNCe to a value or variable by precedingit with a backslash. DerefereNCing is accomplished by surroundingthe refereNCe variable in curly braces and preceding the leftcurly brace with a character denoting what type of refereNCe itis. For example, use <TT>@</TT> forarrays and <TT>&</TT> for fuNCtions.<P>There are five types of refereNCes that you can use in Perl. Youcan have a refereNCe to scalars, arrays, hashes, fuNCtions, andother refereNCes. If you need to determine what type of refereNCeis passed to a fuNCtion, use the <TT>ref()</TT>fuNCtion.<P>The <TT>ref()</TT> fuNCtion returnsa string that indicates which type of refereNCe was passed toit. If the parameter was not a refereNCe, the undefined valueis returned. You discovered that it is always a good idea to checkrefereNCe types to prevent errors caused by passing the wrongtype of refereNCe. An example was given that caused an error bypassing a scalar refereNCe when the fuNCtion expected an arrayrefereNCe.<P>A lot of time was spent discussing data records and how to accessinformation stored in them. You learned how to step through dissectinga derefereNCing expression, how to dynamically add new data recordsto an associative array, and how to add new data members to anexisting record.<P>The last thing covered in this chapter was how to interpolatefuNCtion calls inside double-quoted strings. You'll use this technique-attimes-to avoid using temporary variables when printing or coNCatenatingthe output of fuNCtions to other strings.<P><A HREF="ch9.htm" >Chapter 9</A> "Using Files," introduces you to opening,reading, and writing files. You find out how to store the datarecords you've constructed in this chapter to a file for long-termstorage.<H2><A NAME="ReviewQuestions"><FONT SIZE=5 COLOR=#FF0000>Review Questions</FONT></A></H2><P>Answers to Review Questions are in Appendix A.<OL><LI>What is a refereNCe?<LI>How many types of refereNCes are there?<LI>What does the <TT>ref()</TT> fuNCtionreturn if passed a non-refereNCe as a parameter?<LI>What notation is used to derefereNCe a refereNCe value?<LI>What is an anonymous array?<LI>What is a nested data structure?<LI>What will the following line of code display?<BR><BR><TT>print("${\ref(\(1..5))}");</TT><LI>Using the <TT>%database</TT> arrayin Listing 8.6, what will the following line of code display?<BR><BR><TT>print(%{$database{"MRD-100"}}->{"Zip"}. "\n");</TT></OL><H2><A NAME="ReviewExercises"><FONT SIZE=5 COLOR=#FF0000>Review Exercises</FONT></A></H2><OL><LI>Write a program that will print the derefereNCed value of<TT>$ref</TT> in the following lineof code:<BR><BR><TT>$ref = \\\45;</TT><LI>Write a fuNCtion that removes the first element from eacharray passed to it. The return value of the fuNCtion should bethe number of elements removed from all arrays.<LI>Add error-checking to the fuNCtion written in Exercise 3 sothe <TT>undef</TT> value is returnedif one of the parameters is not an array.<LI>Write a program based on Listing 8.7 that adds a data memberindicating which weekdays a salesman may call the customer withan id of MRD-300. Use the following as an example:<BR><BR><TT> "Best days to call" =>["Monday", "Thursday" ]</TT></OL><HR><CENTER><P><A HREF="ch7.htm"><IMG SRC="pc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="#CONTENTS"><IMG SRC="cc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="index.htm"><IMG SRC="hb.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="ch9.htm"><IMG SRC="nc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><HR WIDTH="100%"></P></CENTER></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -