📄 tij0168.html
字号:
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
beauty of the <A NAME="Index2782"></A><A NAME="Index2783"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>URL</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class is how much it shields you from. You can connect to Web servers without
knowing much at all about what’s going on under the covers.
</FONT><a name="_Toc408018779"></a><P></DIV>
<A NAME="Heading531"></A><H3 ALIGN=LEFT>
The
CGI program in C++
<P><A NAME="Index2784"></A><A NAME="Index2785"></A><A NAME="Index2786"></A></H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">At
this point you could follow the previous example and write the CGI program for
the server using ANSI C. One argument for doing this is that ANSI C can be
found virtually everywhere. However, C++ has become quite ubiquitous,
especially in the form of the <A NAME="Index2787"></A><A NAME="Index2788"></A>GNU
C++ Compiler
</FONT><A NAME="fnB66" HREF="#fn66">[66]</A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>g++</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">that
can be downloaded free from the Internet for virtually any platform (and often
comes pre-installed with operating systems such as Linux). As you will see,
this means that you can get the benefit of object-oriented programming in a CGI
program.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
avoid throwing too many new concepts at you all at once, this program will not
be a “pure” C++ program; some code will be written in plain C even
though C++ alternatives exist. This isn’t a significant issue because the
biggest benefit in using C++ for this program is the ability to create classes.
Since what we’re concerned with when parsing the CGI information is the
field name-value pairs, one class (
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</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">will
be used to represent a single name-value pair and a second class (
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CGI_vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
will automatically parse the CGI string into
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects that it will hold (as a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
so you can fetch each
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
out at your leisure.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
program is also interesting because it demonstrates some of the pluses and
minuses of <A NAME="Index2789"></A><A NAME="Index2790"></A>C++
in contrast with Java. You’ll see some similarities; for example the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword. Access control has identical keywords
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
but they’re used differently: they control a block instead of a single
method or field (that is, if you say
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private:</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
each following definition is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
until you say
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public:</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">).
Also, when you create a class, all the definitions automatically default to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">One
of the reasons for using C++ here is the convenience of the <A NAME="Index2791"></A><A NAME="Index2792"></A><A NAME="Index2793"></A>C++
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>Standard
Template Library
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Among other things, the STL contains a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class. This is a C++
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>template</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which means that it will be configured at compile time so it will hold objects
of only a particular type (in this case,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects). Unlike the Java
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which will accept anything, the C++
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
template will cause a compile-time error message if you try to put anything but
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 into the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and when you get something out of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
it will automatically be 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, without casting. Thus, the checking happens at compile time and
produces a more robust program. In addition, the program can run faster since
you don’t have to perform run-time casts. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>vector
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">also
overloads the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>operator[]
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">so
you have a convenient syntax for extracting
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">objects.
The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
template will be used in the creation of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CGI_vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which you’ll see is a fairly short definition considering how powerful it
is.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">On
the down side, look at the complexity of the definition of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in the following code.
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">has
more method definitions than you’re used to seeing in Java code, because
the C++ programmer must know how to control copying with the copy-constructor
and assignment with the overloaded
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>operator=</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
As described in Chapter 12, occasionally you need to concern yourself with
similar things in Java, but in C++ you must be aware of them almost constantly.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
project will start with a reusable portion, which consists of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Pair</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CGI_vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in a C++ header file. Technically, you shouldn’t cram this much into a
header file, but for these examples it doesn’t hurt anything and it will
also look more Java-like, so it will be easier for you to read:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: CGITools.h</font>
<font color="#009900">// Automatically extracts and decodes data</font>
<font color="#009900">// from CGI GETs and POSTs. Tested with GNU C++ </font>
<font color="#009900">// (available for most server machines).</font>
#include <string.h>
#include <vector> <font color="#009900">// STL vector</font>
using namespace std;
<font color="#009900">// A class to hold a single name-value pair from</font>
<font color="#009900">// a CGI query. CGI_vector holds Pair objects and</font>
<font color="#009900">// returns them from its operator[].</font>
<font color="#0000ff">class</font> Pair {
<font color="#0000ff">char</font>* nm;
<font color="#0000ff">char</font>* val;
<font color="#0000ff">public</font>:
Pair() { nm = val = 0; }
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; }
<font color="#0000ff">const</font> <font color="#0000ff">char</font>* value() <font color="#0000ff">const</font> { <font color="#0000ff">return</font> val; }
<font color="#009900">// Test for "emptiness"</font>
bool empty() <font color="#0000ff">const</font> {
<font color="#0000ff">return</font> (nm == 0) || (val == 0);
}
<font color="#009900">// Automatic type conversion for boolean test:</font>
operator bool() <font color="#0000ff">const</font> {
<font color="#0000ff">return</font> (nm != 0) && (val != 0);
}
<font color="#009900">// The following constructors & destructor are</font>
<font color="#009900">// necessary for bookkeeping in C++.</font>
<font color="#009900">// Copy-constructor:</font>
Pair(<font color="#0000ff">const</font> Pair& p) {
<font color="#0000ff">if</font>(p.nm == 0 || p.val == 0) {
nm = val = 0;
} <font color="#0000ff">else</font> {
<font color="#009900">// Create storage & copy rhs values:</font>
nm = <font color="#0000ff">new</font> <font color="#0000ff">char</font>[strlen(p.nm) + 1];
strcpy(nm, p.nm);
val = <font color="#0000ff">new</font> <font color="#0000ff">char</font>[strlen(p.val) + 1];
strcpy(val, p.val);
}
}
<font color="#009900">// Assignment operator:</font>
Pair& operator=(<font color="#0000ff">const</font> Pair& p) {
<font color="#009900">// Clean up old lvalues:</font>
delete nm;
delete val;
<font color="#0000ff">if</font>(p.nm == 0 || p.val == 0) {
nm = val = 0;
} <font color="#0000ff">else</font> {
<font color="#009900">// Create storage & copy rhs values:</font>
nm = <font color="#0000ff">new</font> <font color="#0000ff">char</font>[strlen(p.nm) + 1];
strcpy(nm, p.nm);
val = <font color="#0000ff">new</font> <font color="#0000ff">char</font>[strlen(p.val) + 1];
strcpy(val, p.val);
}
<font color="#0000ff">return</font> *<font color="#0000ff">this</font>;
}
~Pair() { <font color="#009900">// Destructor</font>
delete nm; <font color="#009900">// 0 value OK</font>
delete val;
}
<font color="#009900">// If you use this method outide this class, </font>
<font color="#009900">// you're responsible for calling 'delete' on</font>
<font color="#009900">// the pointer that's returned:</font>
<font color="#0000ff">static</font> <font color="#0000ff">char</font>*
decodeURLString(<font color="#0000ff">const</font> <font color="#0000ff">char</font>* URLstr) {
<font color="#0000ff">int</font> len = strlen(URLstr);
<font color="#0000ff">char</font>* result = <font color="#0000ff">new</font> <font color="#0000ff">char</font>[len + 1];
memset(result, len + 1, 0);
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0, j = 0; i <= len; i++, j++) {
<font color="#0000ff">if</font>(URLstr[i] == '+')
result[j] = ' ';
<font color="#0000ff">else</font> <font color="#0000ff">if</font>(URLstr[i] == '%') {
result[j] =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -