📄 tij0168.html
字号:
translateHex(URLstr[i + 1]) * 16 +
translateHex(URLstr[i + 2]);
i += 2; <font color="#009900">// Move past hex code</font>
} <font color="#0000ff">else</font> <font color="#009900">// An ordinary character</font>
result[j] = URLstr[i];
}
<font color="#0000ff">return</font> result;
}
<font color="#009900">// Translate a single hex character; used by</font>
<font color="#009900">// decodeURLString():</font>
<font color="#0000ff">static</font> <font color="#0000ff">char</font> translateHex(<font color="#0000ff">char</font> hex) {
<font color="#0000ff">if</font>(hex >= 'A')
<font color="#0000ff">return</font> (hex & 0xdf) - 'A' + 10;
<font color="#0000ff">else</font>
<font color="#0000ff">return</font> hex - '0';
}
};
<font color="#009900">// Parses any CGI query and turns it</font>
<font color="#009900">// into an STL vector of Pair objects:</font>
<font color="#0000ff">class</font> CGI_vector : <font color="#0000ff">public</font> vector<Pair> {
<font color="#0000ff">char</font>* qry;
<font color="#0000ff">const</font> <font color="#0000ff">char</font>* start; <font color="#009900">// Save starting position</font>
<font color="#009900">// Prevent assignment and copy-construction:</font>
<font color="#0000ff">void</font> operator=(CGI_vector&);
CGI_vector(CGI_vector&);
<font color="#0000ff">public</font>:
<font color="#009900">// const fields must be initialized in the C++</font>
<font color="#009900">// "Constructor initializer list":</font>
CGI_vector(<font color="#0000ff">char</font>* query) :
start(<font color="#0000ff">new</font> <font color="#0000ff">char</font>[strlen(query) + 1]) {
qry = (<font color="#0000ff">char</font>*)start; <font color="#009900">// Cast to non-const</font>
strcpy(qry, query);
Pair p;
<font color="#0000ff">while</font>((p = nextPair()) != 0)
push_back(p);
}
<font color="#009900">// Destructor:</font>
~CGI_vector() { delete start; }
<font color="#0000ff">private</font>:
<font color="#009900">// Produces name-value pairs from the query </font>
<font color="#009900">// string. Returns an empty Pair when there's </font>
<font color="#009900">// no more query string left:</font>
Pair nextPair() {
<font color="#0000ff">char</font>* name = qry;
<font color="#0000ff">if</font>(name == 0 || *name == '\0')
<font color="#0000ff">return</font> Pair(); <font color="#009900">// End, return null Pair</font>
<font color="#0000ff">char</font>* value = strchr(name, '=');
<font color="#0000ff">if</font>(value == 0)
<font color="#0000ff">return</font> Pair(); <font color="#009900">// Error, return null Pair</font>
<font color="#009900">// Null-terminate name, move value to start</font>
<font color="#009900">// of its set of characters:</font>
*value = '\0';
value++;
<font color="#009900">// Look for end of value, marked by '&':</font>
qry = strchr(value, '&');
<font color="#0000ff">if</font>(qry == 0) qry = ""; <font color="#009900">// Last pair found</font>
<font color="#0000ff">else</font> {
*qry = '\0'; <font color="#009900">// Terminate value string</font>
qry++; <font color="#009900">// Move to next pair</font>
}
<font color="#0000ff">return</font> Pair(name, value);
}
}; <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">After
the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>#include</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statements, you see a line that says:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">using
namespace std;
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Namespaces
in C++ solve one of the problems taken care of by the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>package</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
scheme in Java: hiding library names. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>std</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
namespace refers to the Standard C++ library, and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is in this library so the line is required.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class starts out looking pretty simple: it just holds two (
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">character
pointers, one for the name and one for the value. The default constructor
simply sets these pointers to zero, since in C++ an object’s memory
isn’t automatically zeroed. The second constructor calls the method
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>decodeURLString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that produces a decoded string in newly-allocated heap memory. This memory must
be managed and destroyed by the object, as you will see in the destructor. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>name( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>value( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods produce read-only pointers to the respective fields. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>empty( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method is a way for you to ask the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object whether either of its fields are empty; it returns a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>bool,</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
which is C++’s built-in primitive Boolean data type. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>operator
bool( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
uses a special case of <A NAME="Index2794"></A><A NAME="Index2795"></A>C++
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>operator
overloading
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which allows you to control automatic type conversion. If you have a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>p</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and you use it in an expression in which a Boolean result is expected, such as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>if(p)
{ //...
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
then the compiler will recognize that it has a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and it needs a Boolean, so it will automatically call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>operator
bool( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to perform the necessary conversion.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
next three methods are part of the bookkeeping that’s necessary when you
create a class in C++. In the so-called “canonical form” for a C++
class, you must define the necessary “ordinary” constructors as
well as a copy-constructor and the assignment operator,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>operator=
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(and
the destructor, to clean up the memory). You must define these because they can
be quietly called by the compiler when you pass objects in and out of a
function (this calls the copy-constructor) or when you assign objects (the
assignment operator). Once you’ve gone through the trouble to understand
how the copy-constructor and assignment operator work you can write robust
classes in C++, but it is a bit of a learning experience.
</FONT><A NAME="fnB67" HREF="#fn67">[67]</A><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
<A NAME="Index2796"></A><A NAME="Index2797"></A>copy-constructor
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair(const
Pair&)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is automatically called whenever you pass an object into or out of a function
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>by
value
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
That is, you aren’t passing the address of the object you’re making
a copy of the whole object inside the function frame. This isn’t an
option in Java since you pass only handles, thus there’s no
copy-constructor in Java. (If you want to make a local duplicate, you
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>clone( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
the object – see Chapter 12.) Likewise, if you assign a handle in Java,
it’s simply copied. But assignment in C++ means that the entire object is
copied. In the copy-constructor, you create new storage and copy the source
data, but with the assignment operator you must release the old storage before
allocating new storage. What you’re seeing is probably the worst-case
complexity scenario for a C++ class, but it’s one of the reasons Java
proponents can argue that Java is a lot simpler than C++. In Java you pass
handles and there’s a garbage collector, so you don’t have to do
this kind of thing.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
isn’t quite the whole story. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class is using
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>char*</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>nm</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>val</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and the worst-case complexity occurs primarily around pointers. If you use the
more modern Standard C++
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>string</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class instead of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>char*</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
things get much simpler (however, not all compilers have caught up enough to
come with
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>string</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">).
Then, the first part of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
looks like this:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">class</font> Pair {
string nm;
string val;
<font color="#0000ff">public</font>:
Pair() { }
Pair(<font color="#0000ff">char</font>* name, <font color="#0000ff">char</font>* value) {
<font color="#009900">// Creates new memory:</font>
nm = decodeURLString(name);
val = decodeURLString(value);
}
<font color="#0000ff">const</font> <font color="#0000ff">char</font>* name() <font color="#0000ff">const</font> { <font color="#0000ff">return</font> nm.c_str(); }
<font color="#0000ff">const</font> <font color="#0000ff">char</font>* value() <font color="#0000ff">const</font> { <font color="#0000ff">return</font> val.c_str(); }
<font color="#009900">// Test for "emptiness"</font>
bool empty() <font color="#0000ff">const</font> {
<font color="#0000ff">return</font> (nm.length() == 0) || (val.length() == 0);
}
<font color="#009900">// Automatic type conversion for boolean test:</font>
operator bool() <font color="#0000ff">const</font> {
<font color="#0000ff">return</font> (nm.length() != 0) && (val.length() != 0);
} </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(Also,
for this case
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>decodeURLString( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
returns a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -