Thursday, May 18, 2017

Digest for comp.lang.c++@googlegroups.com - 25 updates in 6 topics

Bob Langelaan <bobl0456@gmail.com>: May 17 09:06PM -0700

I teach a beginner C++ course and have taught my students that they should minimize the use of the break; and continue; statements. Recently I have been getting push back from some of my students with statements like "my friends at Microsoft tell me they use break; statements all the time" and similar types of objections.
 
I created the post below for my students on this topic some time ago. I would be interested in getting feedback on my post and the topic in general.
 
Thanks in advance,
 
Bob
 
===============================================================================
 
Many beginner programmers will unfortunately use the break statement and the continue statement a great deal more than they should.
 
I will go further and say that, generally speaking, a programmer should try to limit the use of break statements to exiting from a switch statement. And that the continue statement should almost never be used.
 
Here are examples of using the break statement and continue statement that should normally be avoided:
 
// An example of poor use of the break statement
 
while (exit_criteria not met)
{
.
.
.
if (exit_criteria_met)
{
break; // exit while loop immediately
}
.
.
.
} // end of while loop
 

 
// An example of poor use of the continue statement
 
while (exit_criteria not met)
{
.
.
.
if (exit_criteria_met)
{
continue; // Go immediately to the end of the while loop.
// Loop will exit with next iteration because
// the exit_criteria has been met.
}
.
.
.
} // end of while loop
 
 
In the 2 examples above, the exit_criteria is tested twice for each iteration of the while loop. This is considered both inefficient and poor programming style.
 
The following example is also considered poor programming style because you should be exiting a loop at the beginning of the loop or at the end of the loop, and not in the middle of the loop:
 
// Another example of poor use of the break statement
 
while (true) // The same as "while (1)" , but I prefer the former
{
.
.
.
if (exit_criteria_met)
{
break; // exit while loop
}
.
.
.
} // end of while loop
 

 
Using as an example a portion of the solution to exercise 4.13 of the text, here is how you can avoid the 3 poor examples above:
 
// prompt the user for the first value for miles
 
cout << "Enter the miles used (-1 to quit): ";
 
cin >> miles;
 

 
// Exit the loop if the input is -1, otherwise proceed with
 
// the next iteration of the loop.
 
while ( miles != -1 )
 
{
 
// prompt user for gallons and obtain the input from user
 
cout << "Enter gallons: ";
 
cin >> gallons;
 

 
.
. // Complete calculations using current values
 
. // input for miles and gallons
 

 
// prompt user for next value for miles
 
cout << "\n\nEnter the miles used (-1 to quit): ";
 
cin >> miles;
 
} // end while
 

 

 
The example above is a pattern that is used very commonly in well crafted code. You will note that it contains _NO_ break statements or continue statements, that there is only one test to exit the loop, and that this one test is done at the beginning of the loop.
 

 
Some of you will notice the solution above requires some code duplication. The code that inputs the miles is duplicated - once before entering the while loop and again at the end of the while loop. While we generally try to avoid code duplication, in this case, this code duplication is preferred over having an unnecessary break statement or continue statement in the loop. In other words, in this case it is considered the lessor of two evils :)
 

 
I will occasionally use a break statement in a situation similar to the next example:
 

 
// In the example below we are searching for a value in an array
 

 
bool found = false;
 
for (unsigned int value ; I < ARRAY_SIZE; ++i)// iterate through the array
{
 
if (myArray[i] == search_value)
 
{
 
found = true;
 
break; // exit loop since we have found search_value
 
}
 
}
 
// When we reach this point, "found" will be true if search_value was
// found in the array and false otherwise.
 
I tutor students from schools all over the lower mainland on C/C++. Several of these students have told me in the past that their instructors do not allow _ANY_ use of break statements, other than in a switch statement. So how would you rewrite the previous example without using a break statement, but still be equally efficient? Quite simply actually:
 

 
bool found = false;
 
// iterate through the array
for (unsigned int value ; (!found) && (i < ARRAY_SIZE); ++i)
{
 
if (myArray[i] == search_value)
 
{
 
found = true;
 
}
 
}
 

 
// When we reach this point, "found" will be true if search_value was found
 
// in the array and false otherwise.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 18 07:27AM +0200

On 18-May-17 6:06 AM, Bob Langelaan wrote:
> I teach a beginner C++ course and have taught my students that they
> should minimize the use of the break; and continue; statements.
 
Good advice. :)
 
 
 
> I created the post below for my students on this topic some time ago.
> I would be interested in getting feedback on my post and the topic in
> general.
 
Well, the concrete advice on rewriting a loop-and-a-half,
 
for( ;; )
{
int value;
cout << "Value (0 to quit? ";
cin >> value;
if( value == 0 )
{
break;
}
// Do computations, present result.
}
 
as
 
int value;
cout << "Value (0 to quit? ";
cin >> value;
while( value != 0 )
{
// Do computations, present result.
cout << "Value (0 to quit? ";
cin >> value;
}
 
is ungood, downright evil, because
 
1. it introduces undesirable redundancy, repeated code. Not doing that
is known as the DRY principle: Don't Repeat Yourself. Stick to DRY.
 
2. It needlessly expands the scope of the support variables.
And if that scope is contained via an outer curly braces block,
then it needlessly adds extra indentation.
 
You say about it:
 
> duplication is preferred over having an unnecessary break statement or
> continue statement in the loop. In other words, in this case it is
> considered the lessor of two evils :)
 
No, it's not the lesser of two evils. It's an evil introduced to avoid
perfectly good ordinary code because you have OVER-GENERALIZED a rule
about avoiding `break`. You have made it an absolute rule, which is easy
to follow mechanically but produces rather sub-optimal results, instead
of a guideline that requires intelligence in its application.
 
Instead IMO you should teach your students about loop-and-a-half: how to
recognize that it's logically there (code duplication) and how to
express it properly (with a break or return or throw in the middle).
 
• • •
 
That said, your students' argument about `break` being used at Microsoft
is not a valid argument.
 
Very seldom do you find as dirty and invalid code as at Microsoft. To
wit, their documentation has a host of instances of invalid `void main`.
Not to mention the Microsoft monstrosities such as `tmain`. These are
beginner mistakes. And they're all over the place at MS.
 
 
Cheers & hth.,
 
- Alf
Christian Gollwitzer <auriocus@gmx.de>: May 18 08:13AM +0200

Am 18.05.17 um 07:27 schrieb Alf P. Steinbach:
 
> No, it's not the lesser of two evils. It's an evil introduced to avoid
> perfectly good ordinary code because you have OVER-GENERALIZED a rule
> about avoiding `break`.
 
+1.
 
Upon reading this paragraph, I thought it to be satirical, but from the
following it appears that you mean it as written. It is neither good to
repeat the loop condition, nor to repeat the code, but repeating more
than one line of code as a trade-in for not repeating the loop condition
nor using break sounds absurd.
 
Break is there for a reason. The alternative would be to set a condition
flag, not to repeat the code. I prefer break over condition flags if it
can be clearly expressed that way.
 
Christian
Christian Gollwitzer <auriocus@gmx.de>: May 18 08:14AM +0200

Am 18.05.17 um 08:13 schrieb Christian Gollwitzer:
>> about avoiding `break`.
 
> +1.
 
> Upon reading this paragraph, I thought it to be satirical,
 
I meant the OP's paragraph, just to make that clear ;)
 
Christian
bitrex <bitrex@de.lete.earthlink.net>: May 18 02:30AM -0400

On 05/18/2017 12:06 AM, Bob Langelaan wrote:
 
 
> found = true;
 
> }
 
> }
 
bool found = false;
 
for (size_t i = 0; i < ARRAY_SIZE; ++i)
{
if (!found) { found = (myArray[i] == search_value); } else break;
}
 
Break statements are cool
Ian Collins <ian-news@hotmail.com>: May 18 06:34PM +1200

On 05/18/17 04:06 PM, Bob Langelaan wrote:
> I teach a beginner C++ course and have taught my students that they
> should minimize the use of the break; and continue; statements.
 
Good advice with an emphasis on "minimise", they sometimes have their place.
 
Most places where beak is used in a loop can be replaced with a return
if the loop is extracted into a function :)
 
--
Ian
David Brown <david.brown@hesbynett.no>: May 18 09:36AM +0200

(/Please/ get a proper newsreader. It is nearly impossible to deal with
google-groups line split crap without making a mess.)
 
On 18/05/17 06:06, Bob Langelaan wrote:
> I have been getting push back from some of my students with statements
> like "my friends at Microsoft tell me they use break; statements all the
> time" and similar types of objections.
 
/Minimizing/ the use of "break" is good - obsessing about it or banning
it is not. I find "continue" to be very rarely useful - I could happily
live without it in the language. But sometimes "break" really is the
best way to structure a loop.
 
 
> I will go further and say that, generally speaking, a programmer
> should try to limit the use of break statements to exiting from a switch
> statement. And that the continue statement should almost never be used.
 
That paragraph does not read well. I first thought you had said that
"break" should not be used to exit switch statements either.
 
> .
> .
> } // end of while loop
 
It is rare that you want to have the same test twice - but not /always/
bad. It is likely that in a case like this, you could remove the
condition at the start, making it a "while (true)" loop. In a "while
(true)" loop, it is perfectly clear that the loop exit will be done
somewhere in the middle of the loop (except for intentionally
never-ending loops).
 
> .
> .
> } // end of while loop
 
"Continue" here is daft - it should be "break".
 
 
> In the 2 examples above, the exit_criteria is tested twice for each
> iteration of the while loop. This is considered both inefficient and
> poor programming style.
 
Don't claim that something "is considered" unless you can back it up
with clear justifications. Provide references from the Google C++ style
guide, or MISRA, or quotations from one of the C++ "greats". If you
cannot, then be honest and write "I consider it...".
 
And I don't think you can really claim it is inefficient, if the test
condition does not require external calls - the compiler will probably
be able to optimise that "continue" into a single jump to outside the
loop, just like a "break".
 
 
> The following example is also considered poor programming style
> because you should be exiting a loop at the beginning of the loop or at
> the end of the loop, and not in the middle of the loop:
 
Who says? /Why/ do you think that is a good idea?
 
This all comes across as very dogmatic to me. It looks like you want to
avoid exits in the middle of a loop simply because that is a rule that
/you/ were taught.
 
It is fine to say that exits in the middle of a loop are often hard to
follow, and make the flow of the code unclear. That is a /reason/ for
minimising the use of "break" and "continue". Saying they should be
avoided because it is "considered poor programming style" is not a
reason - any more than saying that "friends at Microsoft use break" is a
good reason to use them.
 
> // Another example of poor use of the break statement
 
> while (true) // The same as "while (1)" , but I prefer the former
 
(Side issue - I agree that "while (true)" is the nicest way to write
such loops. I dislike the use of "1" for a boolean, and I think the
alternative "for (;;)" is ugly. But beauty is in the eye of the beholder.)
 
> .
> .
> } // end of while loop
 
Often that is a perfectly good way to structure a loop. When you see
"while (true)" at the start of a loop, you are in no doubt that the exit
condition comes in the middle of the loop somewhere. If you don't know
that it is time to exit until the middle of the loop, then putting a
"break" (or perhaps "return") there seems perfectly reasonable.
 
Another situation where the use of "while (true)" and breaks can make
sense is if the exit criteria is complex. It may be natural to put
these at the beginning or the end of the loop, but it can be clearer to
have multiple statements, with space for comments, rather than jamming
everything into one exit expression. (There are, of course, alternative
restructurings - such as re-factoring the conditions into a function.)
 
So rather than:
 
while (A && B && !C) {
...
}
 
consider:
 
while (true) {
if (!A) break; // Exit if A does not hold
if (!B) break; // Exit if B does not hold
if (C) break; // Exit when C is reached
...
}
 
 
> duplication is preferred over having an unnecessary break statement or
> continue statement in the loop. In other words, in this case it is
> considered the lessor of two evils :)
 
Sometimes code duplication is unavoidable. In such cases, choose to
duplicate the simplest, shortest, clearest code - not the major lines.
Testing "(miles == -1)" is far simpler and "smaller" than "cin >>
miles". Thus it is the test that should be duplicated, /not/ the action
of reading cin.
 
So while I agree that you may need to choose the lesser of two evils, I
think you have got the answer completely wrong in this case.
 
The best structuring here is very simple:
 
while (true) {
cout << "Enter the miles used (-1 to quit): ";
cin >> miles;
if (miles == -1) break;
...
}
 
Then there is /no/ duplication of either the important statements, or
the test.
 
 
 
> }
 
> // When we reach this point, "found" will be true if search_value was
> // found in the array and false otherwise.
 
Baring typos in the code (which are a /really/ bad idea in a post to
students!), that is a perfectly good use of "break".
 
> switch statement. So how would you rewrite the previous example without
> using a break statement, but still be equally efficient? Quite simply
> actually:
 
The world is a big place, and this is an international newsgroup - no
one can guess where "the lower mainland" is.
 
I am always wary of hard and fast rules such as /never/ using break
statements. I need justification - the stronger the rule, the more
justification I need.
 
And efficiency should not be your major concern here - code clarity and
correctness trump efficiency every time. If you are going to have a
rule about code style, ask yourself:
 
Does it make it easier to write correct code?
Does it make it harder to write incorrect code?
Does it make it easier to see that correct code is correct?
Does it make it easier to see that incorrect code is incorrect?
 
For the most part, pick efficient algorithms and let the compiler worry
about the efficiency of the detail in the code. The compiler is not
going to follow your structure of loops and breaks anyway.
 
 
> found = true;
 
> }
 
> }
 
In my book, the complex condition in the for loop makes it poor code -
it is unclear. It is not as bad as using "i = ARRAY_SIZE" to jump to
the end of the loop, but it is still bad. This kind of exercise is a
very artificial problem, and there are no nice answers. They can be
useful while learning, but that does not make them good style in practice.
 
"Fred.Zwarts" <F.Zwarts@KVI.nl>: May 18 10:00AM +0200

"bitrex" schreef in bericht news:KbbTA.89595$rl4.68345@fx35.iad...
> if (!found) { found = (myArray[i] == search_value); } else break;
>}
 
>Break statements are cool
 
Matter of taste. I would write:
 
bool found = false;
for (size_t i = 0; i < ARRAY_SIZE && !found; ++i) {
found = (myArray[i] == search_value);
}
Cholo Lennon <chololennon@hotmail.com>: May 18 10:07AM -0300

On 18/05/17 08:53, Stefan Ram wrote:
 
> int read_miles()
> { int miles {};
> ::std::cout << "Enter the miles used (-1 to quit): "s;
 
Why the use of the literal s? It's really unnecessary :-O
 
 
 
--
Cholo Lennon
Bs.As.
ARG
bitrex <bitrex@de.lete.earthlink.net>: May 18 09:49AM -0400

On 05/18/2017 04:00 AM, Fred.Zwarts wrote:
> for (size_t i = 0; i < ARRAY_SIZE && !found; ++i) {
> found = (myArray[i] == search_value);
> }
 
Years of Python has corrupted me I think. ;-)
 
I don't like having multiple conditionals in for loops, I think it can
be kinda confusing
bitrex <bitrex@de.lete.earthlink.net>: May 18 09:53AM -0400

On 05/18/2017 09:49 AM, bitrex wrote:
 
> Years of Python has corrupted me I think. ;-)
 
> I don't like having multiple conditionals in for loops, I think it can
> be kinda confusing
 
Under gcc 7.1 x86 with -std=c++11 -O1 FWIW both our variations compile
to the same sequence of instructions.
bitrex <bitrex@de.lete.earthlink.net>: May 18 10:08AM -0400

On 05/18/2017 08:14 AM, Stefan Ram wrote:
 
> that without SESE it can be much more difficult to
> apply an "extract method" refactor or to add something
> that should be done on every entry to or exit of a block.
 
If one's methods are so bloated that one can't pretty much immediately
see where the exit points are then they need to go on a diet...
bitrex <bitrex@de.lete.earthlink.net>: May 18 10:17AM -0400

On 05/18/2017 10:08 AM, bitrex wrote:
>> that should be done on every entry to or exit of a block.
 
> If one's methods are so bloated that one can't pretty much immediately
> see where the exit points are then they need to go on a diet...
 
Granted I'm a relative newcomer to C++; I never used the language "back
in the day", I mostly have experience with straight C99, Python, and a
little Lisp/Clojure.
 
I've been trying to go straight to learning "modern C++" i.e. how things
are done post C++11. I feel like big blocks of conditionals/if
statements/switch statements are old 90s shit like what I was writing in
C back then. I can't remember the last time I used a switch statement or
multiple layers of if/else blocks in something I've written in C++...it
feels too much like the "bad old days" and I figure I must be doing
something wrong.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 18 04:20PM +0200

On 18-May-17 9:36 AM, David Brown wrote:
[snip]
> with clear justifications. Provide references from the Google C++ style
> guide, or MISRA, or quotations from one of the C++ "greats". If you
> cannot, then be honest and write "I consider it...".
 
Uhm, the Google C++ style guide is designed (if it is designed) for a C
style legacy code base.
 
It would not be a good idea to use it as an authority on anything C++.
 
Don't know about MISRA but I suspect the same story: a special purpose
thing.
 
 
Cheers!,
 
- Alf
qak <q3k@mts.net.NOSPAM>: May 18 02:18PM

David Brown <david.brown@hesbynett.no> wrote in
> code to achieve the effect. In some operating systems (such as
> Linux), code that is not executed on a particular platform might not
> even be loaded off the disk when you run a program.
 
Can individual instruction be 'hot', or only the whole block of code can
be cached ? I always wish:
if(AMD) do REP RET
else do RET
then after the first run all the first lines disappear from every PROC
alexo <alessandro.volturno@libero.it>: May 18 01:26PM +0200

Il 17/05/2017 20:39, Paavo Helde ha scritto:
 
> It should compile if you define the destructor and make data public. If
> it does not, then you introduced some other error. Please post the new
> code and matching error messages, we are not psychics here!
 
I thought you were that ; )
 
 
> If you get to the linker errors, this means that at least the compiler
> was satisfied with your syntax. Whether the code is actually correct and
> does what you wanted is another story.
 
It happened a strange thing.
I put all the code in a single main.cpp file and it compiles, links and
executes correctly.
While having a MyClass.h and MyClass.cpp files whorking with a main
function in a separate file, it gives those strange linker error messages.
 
here is the correct code:
 
#include <iostream>
#include <typeinfo>
#include <string>
 
#include <stdio.h>
 
using std::cout;
using std::endl;
using std::string;
 
 
/// the class' declaration
 
 
template <class T>
class MyClass
{
public:
T data;
MyClass();
MyClass(T);
MyClass(const MyClass &);
};
 
 
/// the class' definition
 
 
// constructor
 
template <class T>
MyClass<T>::MyClass(T val)
{
data = val;
}
 
template <class T>
MyClass<T>::MyClass()
{
data = 10;
}
 
// copy constructor
 
template <class T>
MyClass<T>::MyClass(const MyClass<T> &obj)
{
if( typeid(T) == typeid(char *) )
{
int len = strlen(obj.data);
strncpy(data, obj.data, len+1);
}
else
{
data = obj.data;
}
}
 
int main()
{
MyClass<string> test("THREE");
 
cout << test.data << endl;
 
return 0;
}
Paavo Helde <myfirstname@osa.pri.ee>: May 18 04:19PM +0300

On 18.05.2017 14:26, alexo wrote:
> executes correctly.
> While having a MyClass.h and MyClass.cpp files whorking with a main
> function in a separate file, it gives those strange linker error messages.
 
Seems like https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
ram@zedat.fu-berlin.de (Stefan Ram): May 18 11:36AM

>my students that they should minimize the use of the break
 
In your whole post I have searched for a /rationale/
(reason) for the above. I only found this so far:
 
>In the 2 examples above, the exit_criteria is tested twice
>for each iteration of the while loop. This is considered
>both inefficient and poor programming style.
 
This rationale is founded on DRY (don't repeat yourself,
"tested twice"). Ok, we all agree on DRY.
 
>style because you should be exiting a loop at the beginning
>of the loop or at the end of the loop, and not in the middle
>of the loop:
 
I do not deem this a rationale because it is only founded on
»because you should ...«, but then another rule is given
which itself does not have a rationale.
 
>duplication, in this case, this code duplication is preferred
>over having an unnecessary break statement or continue
>statement in the loop.
 
Either code duplication is a major evil, than it can be used
as a rationale for the avoidance of »break«, but then it
also will dictate to avoid the »break«-less code given later.
 
Or code duplication is acceptable, in which case your
»break«-less code duplication is ok, but it now also is
no rationale for the avoiding of break.
 
And it still is to be disputed whether it is true at
all that break will necessarily lead to code duplication or
whether this is only the property of a constructed example.
 
So far you have not given me a convincing rationale for the
avoidance of »break«. Students find it hard to follow
guidelines for which no convincing reasons are given.
ram@zedat.fu-berlin.de (Stefan Ram): May 18 11:53AM

> cout << "\n\nEnter the miles used (-1 to quit): ";
> cin >> miles;
>}
 
My course participants have learned function definitions
/before/ control structures. So they could avoid the
definition using:
 
#include <initializer_list>
#include <iostream>
#include <ostream>
#include <string>
 
using namespace ::std::literals;
 
int read_miles()
{ int miles {};
::std::cout << "Enter the miles used (-1 to quit): "s;
::std::cin >> miles;
return miles; }
 
int main()
{ int miles {};
while(( miles = read_miles() )!= -1 )
{ /* ... */ }}
 
However, I deem the whole field of input too difficult for
my beginner's course and only treat it later in the advanced
course.
 
I usually do not mention »break;« at all and so I never saw
it in the program of a participant IIRC. However, I do not
avoid »break;« because I thing that ignorance will lead to
a better programming style, but only because my beginner's
course usually is too short and the advanced course has a
different scope (user-defined types).
ram@zedat.fu-berlin.de (Stefan Ram): May 18 12:14PM

>I teach a beginner C++ course and have taught my students
>that they should minimize the use of the break;
 
It seems that you might not be aware of the whole background
and only have heard of some guidelines yourself.
 
The background is usually the (in)famous article
»Go To Statement Considered Harmful« by Edgar Dijkstra.
 
This lead to the school of »Structured Programming«
(Dijkstra, Hoare, Dahl, Wirth, and others).
 
There, you can find /reasons/ for /why/ every block
should have exactly one entry (at the beginning)
and exactly one entry (at the exit). SESE =
single entry, single exit.
 
And »break;« and »continue;« /are/ (restricted)
forms of »goto«.
 
One reason, I give to my participants for SESE is
that without SESE it can be much more difficult to
apply an "extract method" refactor or to add something
that should be done on every entry to or exit of a block.
 
In C++, however, one must also take into account that
objects can be destroyd on /every/ path exiting a
block, which leads to RAII.
ram@zedat.fu-berlin.de (Stefan Ram): May 18 12:19PM

>Well, the concrete advice on rewriting a loop-and-a-half,
 
Kudos for introducing the proper term into the discussion!
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: May 17 07:51PM -0700

+1. Awesome. You do good work, Leigh.
 
Thank you,
Rick C. Hodgin
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 18 09:24AM +0200

On 17-May-17 2:05 AM, Mr Flibble wrote:
 
> My upcoming C++ game/GUI library/framework "neoGFX" now has a wiki:
 
> http://neogfx.io/wiki/index.php/Main_Page
 
> neoGFX version 1.0 is about 75% complete at this stage.
 
It looks good.
 
Thanks for mentioning Vulcan, so I could learn about it.
 
 
Cheers!,
 
- Alf
Jerry Stuckle <jstucklex@attglobal.net>: May 17 10:33PM -0400

On 5/17/2017 12:42 PM, Gareth Owen wrote:
 
> Yup. The cost of speeding up the code with assembler (time, money, like
> of portability) are far greater than just throwing a bunch more
> processors at them
 
Except that doubling the number of processors does NOT halve the time it
takes to compute. Some computations cannot be started until previous
computers have been completed. That is the case in most weather
prediction algorithms.
 
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Jerry Stuckle <jstucklex@attglobal.net>: May 17 10:35PM -0400

On 5/17/2017 1:53 PM, Gareth Owen wrote:
 
>> Christian
 
> From the NOAA, not NASA or github. Not in assembly, either.
> http://www.nco.ncep.noaa.gov/pmb/codes/nwprod/
 
Ok, so now let's see you compile and run the code successfully. You
will find this is not the complete code for the models.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: