⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wzoutputtest.html

📁 有限元学习研究用源代码(老外的),供科研人员参考
💻 HTML
字号:
<TITLE>WZ 1.0 - formatted output</TITLE>

<H1>Formatted Output</H1>

 <P>The standard output possibilities are not very nice. We suggest an
improvement.  We want to combine the advantages of formatting and a
comma-separated parameter list as in printf with C++ type control.

 <OL>

 <LI> The place for the next parameter is marked with brackets. That
means, "x = <>" instead of "x = %d" or "x = %f" and so on.  The type
will be correctly detected by C++.

 <LI> Text inside &lt;&gt; is the "format description".  It's
meaning is type-dependent and implemented in a single output function
for every type.

 <LI> The length may be fixed as &lt;number&gt; for any type.  This
number may be followed by a format description.

 </OL>

 <P>See examples <A HREF="#usage">how to use it</A> below. 

<H2>Implementing Formatted Output For An Application</H2>

 <P>The application programmer who wants to allow formatted output for
a given class should implement a function of the following type:

<PRE>
static void _output_(void *o,char *t,unsigned m,char *f);
</PRE>

 <P>Then this function has to be used to define a conversion of the
class of his application into the class <B>wzOutputItem</B>:

<PRE>
#include "<A HREF="wzoutput.hxx">wzoutput.hxx</A>"

class application_class{
public:
// the application-dependent data:
  int i;
// internal definition:
  operator wzOutputItem(){return wzOutputItem((void*)this,_output_);}
};

</PRE>

 <P>Thus, we have to add only one not very beautiful edge into the
class code.  But this edge has an advantage compared with the usual
basic class technique - we do not use virtual functions, that means,
we do not obtain a pointer to a virtual function table.  Thus, we do
not need any additional storage even for scalar classes.

<H3>Implementing the function _output_</H3>

 <P>Now, let's look how the application programmer has to implement
the output function. 

<PRE>
#include &lt;string.h&gt;
#include &lt;stdio.h&gt;
static void _output_(void *obj, char *text, unsigned max, char *format)
</PRE>

 <P>The parameters are:

 <OL>

 <LI> <B>obj</B> is the pointer to the object which should be
printed. We recommend to convert it immediately into the correct type:

<PRE>
{application_class& object = *(application_class*)obj;
</PRE>

 <LI> <B>text</B> is the place where we should write the output;

 <LI> <B>max</B> is the length which will be visible. If zero, the
whole text up to the first '\0' will be visible.  Don't forget to
write it.  If max is greater zero, exactly max chars will be written.

 <P>You have more memory (wzOutput::allocated&gt;999), thus, you can
ignore max for fast prototyping.

 <LI> <B>format</B> is the string the user has written into the
&lt;&gt;.  The application programmer has to explain in his
documentation which strings are allowed for his application_class and
to implement them.  You can use any string not beginning with a number
(the leading number will be interpreted as the requested length of the
output, it becomes the parameter max, and not part of format).

 </OL>

 <P>If there is something wrong with the data, the application
programmer should throw the exception <B>wzOutputDataError</B>.  If an
unknown format is given, he should write the default output and then
throw the exception <B>wzOutputFormatError</B>.

 <P>Thus, if you choose a single letter to characterize your format,
you should write something similar to

<PRE>
 if(object.i==0) {throw wzOutputDataError();}
 switch(format[0]){
 case 'x':
	sprintf(text,"%x",object.i); break;
 case '\0':
	sprintf(text,"%d",object.i); break;
 default:
	sprintf(text,"%d",object.i);
	if(format[0]!='\0') {throw wzOutputFormatError();}
 }
}
</PRE>

<H2><A NAME=usage>Usage</A></H2>

 <P>The class <B>wzOutput</B> should replace the output stream:

<PRE>
void test()
{wzOutput p1(cerr);
 wzOutput&amp; pout = wzOutput::Default;
 application_class x={5},y={16};
</PRE>

 <P>Now instead of C printf(format,...) write  pout(format)&lt;&lt;...; 

 <P>We have additionally defined the comma operator as a synonym of
the &lt;&lt; operator. Thus, choose what looks more natural:

<PRE>
	printf("x = %d, y = %d;\n",x,y);
	pout  ("x = &lt;&gt;, y = &lt;&gt;;\n")&lt;&lt;x,y;
	pout  ("string output: \\&lt;&lt;&gt;\\&gt; \n")&lt;&lt;"xxx";
</PRE>

 <P>Now, by comparing the following edges with the result of the test
example call, you can learn various things: How to use the format
&lt;x&gt; which has been defined previously, what happens if the
number of arguments doesn't fit the number of places in the format
string, how to include the signs &lt;&gt; into the output text:

<PRE>
	pout("x = &lt;x&gt;, y = &lt;x&gt;;\n")&lt;&lt;x,y;
	pout("x = &lt;&gt;, y = &lt;&gt;, ")&lt;&lt;x,y,x,y,x;
	pout,y,x,y,x; 
	pout("&lt;&gt;;\n")&lt;&lt;y;
	pout("&lt;&gt; \\&lt; &lt;&gt;;\n")&lt;&lt;x,y;
</PRE>

The output of the example should be

<PRE>
/*
x = 5, y = 16;
x = 5, y = 16;
x = 5, y = 10;
x = 5, y = 16, x = 5, y = 16, x = 5, y = 16, x = 5, y = 16, x = 5, y = 16;
5 < 16;
x = 5, this should be written, y = 16;
x = 5, y = 16;
+-----+-----+
|16   |10   |
+-----+-----+
x = 5;
x = 5;
x = ****;
x = ****;
*/
</PRE>

<H2>The text before the next format statement</H2>

 <P>What happens with the part of text between two format statements?
There are two modi:

 <UL>
 <LI> <B>pout.flush(1)</B> prints this part immediately after the first parameter.
 <LI> <B>pout.flush(0)</B> prints this part only before the second
parameter is available.  In this state, you can print this part by
hand with <B>pout.flush()</B>.
 </UL>

 <P>This makes not only a difference if you have a slow program. The
more essential difference is that after the first parameter has been
written the format may be changed. In this case, the remaining part of
the previous format will be ignored.  Let's see how this works:

<PRE>
 pout.flush(1);
 pout("x = &lt;&gt;, this should be written, &lt;&gt;;\n")&lt;&lt;x;
 pout("y = &lt;&gt;;\n")&lt;&lt;y;
 pout.flush(0);
 pout("x = &lt;&gt;, this should not be written, &lt;&gt;;\n")&lt;&lt;x;
 pout(", y = &lt;&gt;;\n")&lt;&lt;y;
 pout.flush();  // else we do not get the end of the edge.
 pout.flush(1);
</PRE>

<H2>Output Size</H2>

 <P>If you want to fix the length of the output, write the length
<B>&lt;5&gt;</B> into the brackets.  After this length, you can write
the format label like <B>&lt;5x&gt;</B>:

<PRE>
	pout("+-----+-----+\n|&lt;5&gt;|&lt;5x&gt;|\n+-----+-----+\n")&lt;&lt;y,y;
</PRE>


<A NAME="errors"> <hr></A>
<H2><A HREF="errors.html">Errors</A></H2>

<A NAME="FormatError"> <hr></A>
<H3>wzOutputFormatError</H3>

 <P>This error should be raised by the application programmer if he
detects an unexpected format description.  Nonetheless, the text
should be written in the default format.

 <P>A format error will be ignored by default, but you can change this
behaviour:

<PRE>
 pout.throw_format_error();
 try{
	pout &lt;&lt; "x = &lt;a&gt;;\n")&lt;&lt;x;
	should_fail();
 }catch(wzOutputFormatError e){;}
 pout.ignore_format_error();
 pout &lt;&lt; "x = &lt;a&gt;;\n")&lt;&lt;x;	// incorrect format a should be ignored.
</PRE>

<A NAME="DataError"> <hr></A>
<H3>wzOutputDataError</H3>

 <P>This exception has to be thrown by the application programmer if
the data are invalid. In this case, he should not write any text. 

 <P>Instead, the default text **** will be automatically written.  The
data error will be ignored by default, but you can change this
behaviour:

<PRE>
 x.i = 0;	// zero is invalid - see _output_ before.
 pout.throw_data_error();
 try{
	pout &lt;&lt; "x = &lt;a&gt;;\n")&lt;&lt;x;
	should_fail();
 }catch(wzOutputDataError e){;}
 pout.ignore_data_error();
 pout &lt;&lt; "x = &lt;a&gt;;\n")&lt;&lt;x;	// incorrect value should be ignored
</PRE>

<A NAME="End"> <hr></A>
<PRE>
}
</PRE>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -