473,472 Members | 2,145 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Use != rather than < in for loops ?

In C++ Primer 4th, sec 3.3.2, it states that C++ programmers use !=
rather than < in a for loop.

The following small snippet erases punctuations in a string. It works
well with < used in the for loop but it breaks when != is used instead.

#include <string>
#include <iostream>
#include <exception>
#include <cctype>
using namespace std;

int main(){
string s = "hello, world!";//s: i18n
//for (string::size_type sz = 0; sz < s.size(); ++sz){
/*works with < */
for (string::size_type sz = 0; sz != s.size(); ++sz){
/*doesn't work with != */
try{
if (ispunct(s.at(sz))){
s.erase(sz, 1);
}
}catch(exception &e){
cout << e.what() << endl;
}
}
cout << s << endl;
}

Jan 9 '07 #1
32 2063
lovecreatesbea...@gmail.com wrote:
In C++ Primer 4th, sec 3.3.2, it states that C++ programmers use !=
rather than < in a for loop.

The following small snippet erases punctuations in a string. It works
well with < used in the for loop but it breaks when != is used instead.

#include <string>
#include <iostream>
#include <exception>
#include <cctype>
using namespace std;

int main(){
string s = "hello, world!";//s: i18n
//for (string::size_type sz = 0; sz < s.size(); ++sz){
/*works with < */
for (string::size_type sz = 0; sz != s.size(); ++sz){
/*doesn't work with != */
try{
if (ispunct(s.at(sz))){
s.erase(sz, 1);
}
}catch(exception &e){
cout << e.what() << endl;
}
}
cout << s << endl;
}
I don't have that book so I can only comment on what you've typed above.
The problem with the != version is that every time you call s.erase,
s.size() decreases by 1. Because s ends in a punctuation character you
erase the '!', thereby decrementing s.size() (12 to 11). Immediately
thereafter you increment sz (11 to 12), and the two values "pass
through" each other without ever being equal. Then you end up going out
of bounds with sz, throwing an out_of_range exception. In general I'd
prefer < to != for loop continuation conditions.
Jan 9 '07 #2
lovecreatesbea...@gmail.com wrote:
In C++ Primer 4th, sec 3.3.2, it states that C++ programmers use !=
rather than < in a for loop.
They do? Well, I do that when using iterators, but for a loop using an
integer loop counter, I use <.
The following small snippet erases punctuations in a string. It works
well with < used in the for loop but it breaks when != is used instead.

#include <string>
#include <iostream>
#include <exception>
#include <cctype>
using namespace std;

int main(){
string s = "hello, world!";//s: i18n
//for (string::size_type sz = 0; sz < s.size(); ++sz){
/*works with < */
for (string::size_type sz = 0; sz != s.size(); ++sz){
/*doesn't work with != */
try{
if (ispunct(s.at(sz))){
s.erase(sz, 1);
}
}catch(exception &e){
cout << e.what() << endl;
}
}
cout << s << endl;
}
The problem is that s.size() will be reduced by 1 when you erase a
character. When the last character in your string is removed, your
index "jumps" over the end of the string, so sz will be greater than
s.size(). Therefore the version with < works, but not the one with !=.

Here is a table that shows what it looks like at the beginning of each loop
iteration:

index size character
0 13 h
1 13 e
2 13 l
3 13 l
4 13 o
5 13 , -erased
6 12 w -space is jumped over
7 12 o
8 12 r
9 12 l
10 12 d
11 12 ! -erased
12 11 <none -index is past string end

Jan 9 '07 #3

lovecreatesbea...@gmail.com wrote:
In C++ Primer 4th, sec 3.3.2, it states that C++ programmers use !=
rather than < in a for loop.

The following small snippet erases punctuations in a string. It works
well with < used in the for loop but it breaks when != is used instead.

#include <string>
#include <iostream>
#include <exception>
#include <cctype>
using namespace std;

int main(){
string s = "hello, world!";//s: i18n
//for (string::size_type sz = 0; sz < s.size(); ++sz){
/*works with < */
for (string::size_type sz = 0; sz != s.size(); ++sz){
/*doesn't work with != */
try{
if (ispunct(s.at(sz))){
s.erase(sz, 1);
}
}catch(exception &e){
cout << e.what() << endl;
}
}
cout << s << endl;
}
Hi
The use of != is good practice when using iterators since the only type
of iterator that < will be meaningful to it is random access iterator
(the one used in vector and string but not in list, map ..). In this
case since you are not using iterators but comparing ints it is better
using < from the reasons the others pointed out. By the way I will
steer clean from this book. And anther by the way, its better to use
STL algorithms in this case and not to write this kind of explicit
loops so those type of troubles will not arise in the first place

Jan 9 '07 #4

Rolf Magnus wrote:
lovecreatesbea...@gmail.com wrote:
In C++ Primer 4th, sec 3.3.2, it states that C++ programmers use !=
rather than < in a for loop.

They do? Well, I do that when using iterators, but for a loop using an
integer loop counter, I use <.
The following small snippet erases punctuations in a string. It works
well with < used in the for loop but it breaks when != is used instead.

#include <string>
#include <iostream>
#include <exception>
#include <cctype>
using namespace std;

int main(){
string s = "hello, world!";//s: i18n
//for (string::size_type sz = 0; sz < s.size(); ++sz){
/*works with < */
for (string::size_type sz = 0; sz != s.size(); ++sz){
/*doesn't work with != */
try{
if (ispunct(s.at(sz))){
s.erase(sz, 1);
}
}catch(exception &e){
cout << e.what() << endl;
}
}
cout << s << endl;
}

The problem is that s.size() will be reduced by 1 when you erase a
character. When the last character in your string is removed, your
index "jumps" over the end of the string, so sz will be greater than
s.size(). Therefore the version with < works, but not the one with !=.

Here is a table that shows what it looks like at the beginning of each loop
iteration:

index size character
0 13 h
1 13 e
2 13 l
3 13 l
4 13 o
5 13 , -erased
6 12 w -space is jumped over
7 12 o
8 12 r
9 12 l
10 12 d
11 12 ! -erased
12 11 <none -index is past string end
Thank you, and thank you all.

Yes, the problem in my last code snippet is not because of those two
operators.
I write a new one. I hope this one doesn't have so many errors like the
last one.

#include <string>
#include <iostream>
#include <exception>
#include <cctype>
using namespace std;

int main(){
string s = "hello, world!";
string::size_type sz = s.size();

cout << s << endl;
for(string::size_type idx=0; idx!=sz; ++idx){
//...; idx<sz; ... works
try{
if(ispunct(s.at(idx))){
s.erase(idx, 1);
idx--;
sz--;
}
}catch(exception &e){
cout << e.what() << endl;
}
}
cout << s << endl;

return 0;
}

Jan 9 '07 #5
Mark P <us****@fall2005REMOVE.fastmailCAPS.fmwrote in news:UAJoh.30298
$h*****@newssvr11.news.prodigy.net:
lovecreatesbea...@gmail.com wrote:
>In C++ Primer 4th, sec 3.3.2, it states that C++ programmers use !=
rather than < in a for loop.
You may want to look at the context in which that's used. That "rule"
applies to using iterators in a loop.
[snip]
of bounds with sz, throwing an out_of_range exception. In general I'd
prefer < to != for loop continuation conditions.
I'd amend that statement to clarify about what your using as a loop
continuation condition. Using < when working with iterators may not work.

Jan 9 '07 #6
In article <11**********************@v33g2000cwv.googlegroups .com>,
"lovecreatesbea...@gmail.com" <lo***************@gmail.comwrote:
In C++ Primer 4th, sec 3.3.2, it states that C++ programmers use !=
rather than < in a for loop.

The following small snippet erases punctuations in a string. It works
well with < used in the for loop but it breaks when != is used instead.

#include <string>
#include <iostream>
#include <exception>
#include <cctype>
using namespace std;

int main(){
string s = "hello, world!";//s: i18n
//for (string::size_type sz = 0; sz < s.size(); ++sz){
/*works with < */
for (string::size_type sz = 0; sz != s.size(); ++sz){
/*doesn't work with != */
try{
if (ispunct(s.at(sz))){
s.erase(sz, 1);
}
}catch(exception &e){
cout << e.what() << endl;
}
}
cout << s << endl;
}
I think the above could be done in a better way:

int main() {
string s = "hello, world!";
// first skip through the string to the first punct
string::size_type pos = 0;
while ( pos != s.size() && !ispunct(s[pos]) )
++pos;
// if a punct was found...
if ( pos != s.size() )
{
// start shifting characters to the left,
// overwriting any puncts found along the way
string::size_type index = pos++;
while ( pos != s.size() ) {
if ( !ispunct(s[pos]) ) {
s[index++] = s[pos];
}
++pos;
}
s.resize( index );
}
cout << s << '\n';
}

Of course this simplest and most idiomatic way would be:

bool is_punct( char c ) {
return ispunct( c );
}

int main() {
string s = "hello, world!";
s.erase( remove_if( s.begin(), s.end(), &is_punct ), s.end() );
cout << s << '\n';
}
Jan 9 '07 #7
Daniel T. wrote:
In article <11**********************@v33g2000cwv.googlegroups .com>,
"lovecreatesbea...@gmail.com" <lo***************@gmail.comwrote:
Of course this simplest and most idiomatic way would be:

bool is_punct( char c ) {
return ispunct( c );
}

int main() {
string s = "hello, world!";
s.erase( remove_if( s.begin(), s.end(), &is_punct ), s.end() );
cout << s << '\n';
}
I don't understand why do you need the is_punct() wrapper, cannot ispunct()
work directly as in:
s.erase( remove_if( s.begin(), s.end(), &ispunct ), s.end() );

--
Dizzy
http://dizzy.roedu.net

Jan 9 '07 #8
Dizzy wrote:
I don't understand why do you need the is_punct() wrapper, cannot
ispunct() work directly as in:
s.erase( remove_if( s.begin(), s.end(), &ispunct ), s.end() );
There is a problem with the direct use of functions of the ispunct family,
his siganture and return type can give problems to choose the appropriate
template parameters. And there can be other problems if the implemenation
use signed char in the plain char type. The less problematic solution will
be a wrapper that calls ispunct (static_cast <unsigned char(c) )

--
Salu2
Jan 9 '07 #9
lovecreatesbea...@gmail.com wrote:
In C++ Primer 4th, sec 3.3.2, it states that C++ programmers use !=
rather than < in a for loop.
Not smart programmers, who understand what it means for a loop guard
test to check for the correct precondition.

Fact is, if there is some loop variable i, and a limiting value N, and
if it is incorrect to execute the loop body if i is equal to N, or if i
is greater than N, then the proper guard for executing that loop body
is (i < N).

The test (i != N) only works when other logic has already ensured that
(i <= N) is true. That other logic is usually the fact N is
nonnegative, and that i starts at value 0 (and so i <= N) is initially
true, and that i increments by one in each loop iteration toward the
limiting value, and that N does not change.

The correct test (i < N) doesn't rely on any such assumptions. It
doesn't matter what happens to the value of i in each iteration.
The following small snippet erases punctuations in a string. It works
well with < used in the for loop but it breaks when != is used instead.
That's because the body of the loop changes N. If N is a moving target,
then the invariant (i <= N) does not hold from one iteration to the
next. On one iteration, it could be that i == N - 1. But then, i
increments, and N decrements, so that i is suddenly N + 1.
#include <string>
#include <iostream>
#include <exception>
#include <cctype>
using namespace std;

int main(){
string s = "hello, world!";//s: i18n
//for (string::size_type sz = 0; sz < s.size(); ++sz){
/*works with < */
for (string::size_type sz = 0; sz != s.size(); ++sz){
/*doesn't work with != */
try{
if (ispunct(s.at(sz))){
s.erase(sz, 1);
}
You have another bug here anyway, because if you erase an element of
the string, then you must not increment the sz index. By doing that,
you skip a character, which could be a punctuation character.

Imagine that the action of erase is like that of the Del key on your
keyboard in a typical text editor. When you use Del, the character
under the cursor is eaten, and everything after it moves one position
to the left. If you wanted to delete several punctuation characters in
a row, you'd type Del several times without having to move the cursor.

Similarly, the zs ``cursor'' must not move while characters are being
deleted; after each erasure, the next character to be processed shifts
into the current position, and so that position of the string must be
reevaluated.

If that logic is corrected, then the != test will work, since in any
given iteration, only the s.size() value or the sz value will change,
not both at the same time. Either the size decrements by one, bringing
it closer to sz, or sz increments by one closer to s.size().

Jan 10 '07 #10
lovecreatesbea...@gmail.com wrote:
Thank you, and thank you all.

Yes, the problem in my last code snippet is not because of those two
operators.
The error you had is one reason why I use != rather than <: it goes
dramatically wrong if there is an error in the loop control conditions.
That is a *good* thing because when the program fails dramatically, I
fix the problem. If the program "works" but has a misunderstanding, it
could bite me in a more subtle but more damaging way when the program is
in production use.

--
Ron House ho***@usq.edu.au
http://www.sci.usq.edu.au/staff/house
Ethics website: http://www.sci.usq.edu.au/staff/house/goodness
Jan 10 '07 #11
Julián Albo wrote:
Dizzy wrote:
>I don't understand why do you need the is_punct() wrapper, cannot
ispunct() work directly as in:
s.erase( remove_if( s.begin(), s.end(), &ispunct ), s.end() );

There is a problem with the direct use of functions of the ispunct family,
his siganture and return type can give problems to choose the appropriate
template parameters. And there can be other problems if the implemenation
use signed char in the plain char type. The less problematic solution will
be a wrapper that calls ispunct (static_cast <unsigned char(c) )
I have used directly with ispunct and it worked (in my case ispunct is a int
ispunct(int) signature). I don't understand what could be wrong with "chose
the appropiate template parameters" as long as the standard says that
remove_if is of the form:
template<class ForwardIterator, class Predicate>
ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
Predicate pred);

Thus the Predicate is it's own type and it can be anything that can be
called with a syntax like "pred(*iterator)" and returns an implicitely
convertible to bool value (and has no side effects) where iterator is of
ForwardIterator type. I think in this case functions with the kind of
ispunct signature should work just fine.

Also what can it be wrong with signed/unsigned char thingy, because if the
implementation uses a signed char then this is true for everything
(std::string, the values that ispunct() check for, etc).

I'm asking all this because I want to know more, where I am wrong. Of course
if you talk about non-standard compliant implementations then I'm
interested :)

Thanks!

--
Dizzy
http://dizzy.roedu.net

Jan 10 '07 #12
Dizzy wrote:
Julián Albo wrote:
>Dizzy wrote:
>>I don't understand why do you need the is_punct() wrapper, cannot
ispunct() work directly as in:
s.erase( remove_if( s.begin(), s.end(), &ispunct ), s.end() );

There is a problem with the direct use of functions of the ispunct
family, his siganture and return type can give problems to choose the
appropriate template parameters. And there can be other problems if the
implemenation use signed char in the plain char type. The less
problematic solution will be a wrapper that calls ispunct (static_cast
<unsigned char(c) )

I have used directly with ispunct and it worked (in my case ispunct is a
int ispunct(int) signature). I don't understand what could be wrong with
"chose the appropiate template parameters" as long as the standard says
that remove_if is of the form:
template<class ForwardIterator, class Predicate>
ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
Predicate pred);

Thus the Predicate is it's own type and it can be anything that can be
called with a syntax like "pred(*iterator)" and returns an implicitely
convertible to bool value (and has no side effects) where iterator is of
ForwardIterator type. I think in this case functions with the kind of
ispunct signature should work just fine.
It might, or it might not. Basically, the behavor is undefined.
Also what can it be wrong with signed/unsigned char thingy, because if the
implementation uses a signed char then this is true for everything
(std::string, the values that ispunct() check for, etc).
The problem is that ispunct needs the value to be in the range of unsigned
char. If char is signed, it could be negative, and that's not allowed. As
an example, ispunct might internally use a table to determine if a
character is a punctuation character or not. A negative index into that
table could be desaterous.
So the implicit conversion from char to int is not enough. You need to add a
conversion to unsigned char before it.

Jan 10 '07 #13
Dizzy wrote:
>There is a problem with the direct use of functions of the ispunct
family, his siganture and return type can give problems to choose the
appropriate template parameters. And there can be other problems if the
implemenation use signed char in the plain char type. The less
problematic solution will be a wrapper that calls ispunct (static_cast
<unsigned char(c) )

I have used directly with ispunct and it worked (in my case ispunct is a
int ispunct(int) signature). I don't understand what could be wrong with
"chose the appropiate template parameters" as long as the standard says
that remove_if is of the form:
template<class ForwardIterator, class Predicate>
ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
Predicate pred);
But using a function or functor with the right signature is cleaner, it will
works correctly in all cases, so you don't need to recheck if you change of
algorithm, or add an adapter in the call.
Also what can it be wrong with signed/unsigned char thingy, because if the
implementation uses a signed char then this is true for everything
(std::string, the values that ispunct() check for, etc).
ispunct and familly assumes the his int argument contains the conversion to
int of an unsigned char or EOF. If your implementation has plain chars with
sign, passing it directly is bad according to the standard because does not
follow the rules, and also can be esaisly seen in the practice as bad, for
example in several implementations '\xFF' will be converted to EOF when
promoted to int. Naturally, if you always use a non-extended ascii
character set you will never see this problem.

--
Salu2
Jan 10 '07 #14
"Kaz Kylheku" <kk******@gmail.comwrote in message
news:11**********************@i56g2000hsf.googlegr oups.com...
lovecreatesbea...@gmail.com wrote:
>In C++ Primer 4th, sec 3.3.2, it states that C++ programmers use !=
rather than < in a for loop.
Not smart programmers, who understand what it means for a loop guard
test to check for the correct precondition.
Fact is, if there is some loop variable i, and a limiting value N, and
if it is incorrect to execute the loop body if i is equal to N, or if i
is greater than N, then the proper guard for executing that loop body
is (i < N).
Hey Kaz, I expected better from you -- you're usually not this careless :-)

There are two issues here, and you've caught only one of them:

1) Under what conditions is the body of the loop executed?

2) What conditions pertain after the loop completes?

If we write

while (i < N) { /* do something */ }

we are certain that whenever we execute /* do something */, i is less than
N. So far, we agree.

However, if we write

while (i != N) { /* do something */ }

we are certain that after the loop completes, i is equal to N. We do not
have this certainty in the first case, because it is conceivable that i
might be greater than N.

In other words, if you use < for index comparisons, you make it easier to
verify that the loop doesn't do anything undefined, but harder to verify
that the loop produces the correct result.

Personally, I would rather write my programs in a way that makes it easier
to prove correctness.
Jan 10 '07 #15
Dizzy <di***@roedu.netwrote:
Julián Albo wrote:
Dizzy wrote:
I don't understand why do you need the is_punct() wrapper, cannot
ispunct() work directly as in:
s.erase( remove_if( s.begin(), s.end(), &ispunct ), s.end() );
There is a problem with the direct use of functions of the ispunct family,
his siganture and return type can give problems to choose the appropriate
template parameters. And there can be other problems if the implemenation
use signed char in the plain char type. The less problematic solution will
be a wrapper that calls ispunct (static_cast <unsigned char(c) )

I have used directly with ispunct and it worked (in my case ispunct is a int
ispunct(int) signature). I don't understand what could be wrong with "chose
the appropiate template parameters" as long as the standard says that
remove_if is of the form:
template<class ForwardIterator, class Predicate>
ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
Predicate pred);

Thus the Predicate is it's own type and it can be anything that can be
called with a syntax like "pred(*iterator)" and returns an implicitely
convertible to bool value (and has no side effects) where iterator is of
ForwardIterator type. I think in this case functions with the kind of
ispunct signature should work just fine.
There are two 'ispunct' functions in C++ with different signatures. One
of them is sometimes (allowably) implemented as a macro. There is simply
no way for the compiler to tell which ispunct you wanted to use without
more context, and there is no way for the template code to properly use
a macro.

If you have used it in the past and it worked, great for you. Undefined
behavior sometimes does that.
Also what can it be wrong with signed/unsigned char thingy, because if the
implementation uses a signed char then this is true for everything
(std::string, the values that ispunct() check for, etc).
There is nothing wrong. Julián's concern is that if the char is signed,
it will expand out to an int with a bunch of 1s, but I don't think that
is an issue because 'ispunct' and family only looks at 7 bits of the
char. I could be wrong on this one...
Jan 11 '07 #16
Daniel T. wrote:
There is nothing wrong. Julián's concern is that if the char is signed,
it will expand out to an int with a bunch of 1s, but I don't think that
is an issue because 'ispunct' and family only looks at 7 bits of the
char. I could be wrong on this one...
It looks for EOF, and the value of EOF can be the same as the conversion to
int of a char '\xFF', depending on the implementation and possibly of
compiler options used. Also, the way it evaluates the non-EOF valid values
is dependant of the current locale.

--
Salu2
Jan 11 '07 #17
Andrew Koenig wrote:
"Kaz Kylheku" <kk******@gmail.comwrote in message
news:11**********************@i56g2000hsf.googlegr oups.com...
>lovecreatesbea...@gmail.com wrote:
>>In C++ Primer 4th, sec 3.3.2, it states that C++ programmers use !=
rather than < in a for loop.
>Not smart programmers, who understand what it means for a loop guard
test to check for the correct precondition.
>Fact is, if there is some loop variable i, and a limiting value N, and
if it is incorrect to execute the loop body if i is equal to N, or if i
is greater than N, then the proper guard for executing that loop body
is (i < N).

Hey Kaz, I expected better from you -- you're usually not this careless :-)

There are two issues here, and you've caught only one of them:

1) Under what conditions is the body of the loop executed?

2) What conditions pertain after the loop completes?

If we write

while (i < N) { /* do something */ }

we are certain that whenever we execute /* do something */, i is less than
N. So far, we agree.

However, if we write

while (i != N) { /* do something */ }

we are certain that after the loop completes, i is equal to N. We do not
have this certainty in the first case, because it is conceivable that i
might be greater than N.
You can always make this certainty with a simple one-liner:

if ( i != N ) return(255);
(or a throw is just as valid)

... That is if you NEED i as a certain value - but why would you if you
have N? - Surely you'd be using N because it could change?

I suppose it really depends on what it is used for - but I still think <
is less error-prone than a != (as any value can be != - while you're
limiting a range using <) .

>
In other words, if you use < for index comparisons, you make it easier to
verify that the loop doesn't do anything undefined, but harder to verify
that the loop produces the correct result.
What "correct" result are you after?
The last point in the loop?
... Surely the data effected by the code inside the loop proves if it is
"correct" or not - and not the result of an incrementing index?

If you wanted the last point using "i != N" then you're after N... Why
not just USE N?
>
Personally, I would rather write my programs in a way that makes it easier
to prove correctness.

... I really don't like that.
Reminds me of all these buffer over-run errors where something
unexpected means CONSTANT bug-fixing.

It also reminds me of a current position I have at work, using an
un-named application (I don't think it's my place to name-names) which
produced an endless loop because of some incorrect data.. It took them 3
days to track this down on a production environment (the data was
incorrect for 2 weeks over the xmas and only produced errors after
people started again: adding to the difficulty).

I actually support the previous posters' paragraph which states
"limiting value N", and "if it is incorrect to execute the loop body
if.. i is greater than N".

I just thought I'd post my thoughts on this, because I'd prefer my code
to do what I program - rather than produce a program which may do 'other
things'.

--
Tr**@Computer-Whizz.Linux.com

A pumpkin warrior, brave and good
The last survivor from the wood
So go now swiftly climb the stair
And cut a lock of witch’s hair.
Jan 11 '07 #18
Julián Albo <JU********@terra.eswrote:
Daniel T. wrote:
There is nothing wrong. Julián's concern is that if the char is signed,
it will expand out to an int with a bunch of 1s, but I don't think that
is an issue because 'ispunct' and family only looks at 7 bits of the
char. I could be wrong on this one...

It looks for EOF, and the value of EOF can be the same as the conversion to
int of a char '\xFF', depending on the implementation and possibly of
compiler options used.
There is no char '\xFF' in ASCII (which is what ispunct(int) and family
are designed to handle.) The alternative ispunct (which also takes a
locale parameter) is templated to the char type, thus ispunct<charand
ispunct<unsigned charmight be different functions, but I would expect
each to work for its type, thus not requiring a cast. It seems to me,
that in any case \xFF and EOF would both return false from ispunct, so
the issue is moot.

Is there an authoritative source about this issue?
Jan 11 '07 #19
Daniel T. wrote:
There is no char '\xFF' in ASCII (which is what ispunct(int) and family
are designed to handle.)
Are you saying that C++ is only intended to machines with ascii compatible
charsets?

--
Salu2
Jan 11 '07 #20
Julián Albo <JU********@terra.eswrote:
Daniel T. wrote:
There is no char '\xFF' in ASCII (which is what ispunct(int) and family
are designed to handle.)

Are you saying that C++ is only intended to machines with ascii compatible
charsets?
I'm saying that the is... functions in <cctypeare intended to be used
only on characters that can be represented using 7 bits. i.e., if
assert( ch & 0x7F == ch || ch == EOF ) fails, then the result returned
by ispunct and family on 'ch' is undefined. As such a cast to unsigned
char is meaningless. Again, I could be wrong on this, but that is my
understanding. If you know of an authoritative source that says the cast
is necessary, I'd love to see it.

There are a separate set of is... functions defined in <localthat can
be used for characters that are represented using more than 7 bits, and
a cast is never needed for any of those.
Jan 12 '07 #21
Daniel T. wrote:
I'm saying that the is... functions in <cctypeare intended to be used
only on characters that can be represented using 7 bits. i.e., if
Do you know of an authoritative source that says that? All I have readed is
that the int argument must be EOF or the value of an unsigned char.

--
Salu2
Jan 12 '07 #22
Julián Albo <JU********@terra.eswrote:
Daniel T. wrote:
I'm saying that the is... functions in <cctypeare intended to be
used only on characters that can be represented using 7 bits.
i.e., if

Do you know of an authoritative source that says that?
I don't have much in the way of authoritative sources. I was hoping
someone who had the standard could tell us one way or the other.

I did find, "In the C locale or in a locale where character type
information is not defined, characters are classified according to the
rules of the ASCII 7-bit coded character set." (Found at
http://www.mksxserver.com/docs/man3/ispunct.3.asp,
http://www-zeuthen.desy.de/apewww/AP.../ctype_8h.html,
http://ou800doc.caldera.com/en/man/h.../ctype.3C.html et al.)

I have to admit, I know very little about the locale system and fully
expect that those who ask about using ispunct here have not called
setlocale() (a function which is not even mentioned in TC++PL AFAICT.)

TC++PL does make a comment that passing a signed char into the cctype
functions can be problematic but it gives no details.

According to
http://www.dinkumware.com/manuals/?m...age=ctype.html the
only standard (i.e., not-implementation defined) characters that ispunct
will return true for are within the ascii character set. Passing a non
7-bit ASCII character to ispunct seems to be, at best, implementation
spicific.
Jan 12 '07 #23
Daniel T. wrote:
Julián Albo <JU********@terra.eswrote:
>Daniel T. wrote:
>>I'm saying that the is... functions in <cctypeare intended to be
used only on characters that can be represented using 7 bits.
i.e., if
Do you know of an authoritative source that says that?

I don't have much in the way of authoritative sources. I was hoping
someone who had the standard could tell us one way or the other.

I did find, "In the C locale or in a locale where character type
information is not defined, characters are classified according to the
rules of the ASCII 7-bit coded character set." (Found at
http://www.mksxserver.com/docs/man3/ispunct.3.asp,
http://www-zeuthen.desy.de/apewww/AP.../ctype_8h.html,
http://ou800doc.caldera.com/en/man/h.../ctype.3C.html et al.)
Those are manpages, specific to particular platforms.
I have to admit, I know very little about the locale system and fully
expect that those who ask about using ispunct here have not called
setlocale() (a function which is not even mentioned in TC++PL AFAICT.)

TC++PL does make a comment that passing a signed char into the cctype
functions can be problematic but it gives no details.

According to
http://www.dinkumware.com/manuals/?m...age=ctype.html the
only standard (i.e., not-implementation defined) characters that ispunct
will return true for are within the ascii character set. Passing a non
7-bit ASCII character to ispunct seems to be, at best, implementation
spicific.
Yes, those characters are all in the ASCII standard, but that doesn't
mean that they have to be represented by the equivalent ASCII values.
here is nothing preventing a conforming C++ implementation on a platform
that uses EBCDIC for instance (which is an 8-bit encoding).
--
Clark S. Cox III
cl*******@gmail.com
Jan 12 '07 #24
"Tr0n" <ol*********@hotmail.comwrote in message
news:eo**********@aioe.org...
I suppose it really depends on what it is used for - but I still think <
is less error-prone than a != (as any value can be != - while you're
limiting a range using <) .
No -- it's more error-prone, not less, because it makes it easier for errors
to escape undetected.
>In other words, if you use < for index comparisons, you make it easier to
verify that the loop doesn't do anything undefined, but harder to verify
that the loop produces the correct result.
What "correct" result are you after?
The last point in the loop?
.. Surely the data effected by the code inside the loop proves if it is
"correct" or not - and not the result of an incrementing index?
If you wanted the last point using "i != N" then you're after N... Why not
just USE N?
Here is a concrete example of what I'm talking about.

Suppose I want to write a loop that calls f(n) for every value of (integer)
n such that n>=0 and n<N.

Then I might write a loop with an invariant such as

I have called f(n) for every value of n such that n >= 0 and n < i

and initially establish the invariant by writing

i = 0;

This initialization of i establishes the invariant because there are no
values of n that are both >= 0 and < i.

The loop itself might look like this

while (i != N) { /* or i < N */
// increase i while maintaining the invariant
f(i);
++i;
}

Now, suppose we want to prove that this loop does what we intend.
Regardless of whether the loop condition is i != N or i < N, we have to
prove that the loop terminates.

If the condition is i != N, we can't prove that the loop terminates unless
we prove that N >= 0, a fact that you are claiming argues that i < N is
superior.

However, if the condition is i < N, that complicates the second part of the
proof. Because in that case, when the loop does terminate, we do not know
that i == n, which means that instead of proving the original requirement:

we have called f(n) for every value of (integer) n such that n >= 0 and
n < N

we have instead proved

we have called f(n) for every value of (integer) n such that n >= 0 and
n < i, where i is an unknown value >= n

In other words, in exchange for simplifying the proof of termination, we
have complicated the proof of correctness.

I would much rather simplify the proof of correctness, because if for some
reason the program doesn't terminate, we'll surely know about it. In other
words, I'd rather have a program that goes into an infinite loop than one
that quietly produces the wrong answer.
>Personally, I would rather write my programs in a way that makes it
easier to prove correctness.
.. I really don't like that.
Reminds me of all these buffer over-run errors where something unexpected
means CONSTANT bug-fixing.
I have no idea what you're talking about here.
It also reminds me of a current position I have at work, using an un-named
application (I don't think it's my place to name-names) which produced an
endless loop because of some incorrect data.. It took them 3 days to track
this down on a production environment (the data was incorrect for 2 weeks
over the xmas and only produced errors after people started again: adding
to the difficulty).

I actually support the previous posters' paragraph which states "limiting
value N", and "if it is incorrect to execute the loop body if.. i is
greater than N".

I just thought I'd post my thoughts on this, because I'd prefer my code to
do what I program - rather than produce a program which may do 'other
things'.
Exactly. And to be confident that your code does what you program, you
should make it as easy as possible to prove that it does what you intend.
Jan 12 '07 #25
Daniel T. wrote:
I did find, "In the C locale or in a locale where character type
information is not defined, characters are classified according to the
rules of the ASCII 7-bit coded character set." (Found at
http://www.mksxserver.com/docs/man3/ispunct.3.asp,
http://www-zeuthen.desy.de/apewww/AP.../ctype_8h.html,
http://ou800doc.caldera.com/en/man/h.../ctype.3C.html et al.)
Those looks like the documentation of an implementation, non a standard
description. And is highly likely that all those implementations are
intended for machines with ascii-compatible character set.

But even in that case, the locale can be not 'C' and can not work as 'C' in
this regard.
I have to admit, I know very little about the locale system and fully
expect that those who ask about using ispunct here have not called
setlocale()
Very nice for your part to ignore all people in the world that use languages
with more characters than the ascii set.
TC++PL does make a comment that passing a signed char into the cctype
functions can be problematic but it gives no details.
A good indication that you should not do it if without a good reason, IMO.
Passing a non 7-bit ASCII character to ispunct seems to be, at best,
implementation spicific.
But passing it as unsigned char, the result will always be the intended by
the user who knows about his locale. Passing it as signed char, maybe not.
An unnecessary risk for no other benefit than avoid to write a few chars in
the source.

--
Salu2
Jan 12 '07 #26
Julián Albo <JU********@terra.eswrote:
Daniel T. wrote:
I did find, "In the C locale or in a locale where character type
information is not defined, characters are classified according to the
rules of the ASCII 7-bit coded character set." (Found at
http://www.mksxserver.com/docs/man3/ispunct.3.asp,
http://www-zeuthen.desy.de/apewww/AP.../ctype_8h.html,
http://ou800doc.caldera.com/en/man/h.../ctype.3C.html et al.)

Those looks like the documentation of an implementation, non a standard
description.
Which is why I have been asking someone to look it up in the standard.
TC++PL says that implementation documentation is the authoritative
source.
But even in that case, the locale can be not 'C' and can not work as 'C' in
this regard.
Odd, the documentation I can find for setlocale says that the default
local is "C", "A minimal environment for C-language translation"
I have to admit, I know very little about the locale system and fully
expect that those who ask about using ispunct here have not called
setlocale()

Very nice for your part to ignore all people in the world that use languages
with more characters than the ascii set.
Please, no need to be combative. If one wants to handle languages with
more characters than the ascii set, one is probably better off using
some form of unicode which means all of the functions in cctype are
useless.

I've said more than once that I'm not sure of the correct answer here.
I'm asking what it is. You seem to be sure of the correct answer, but
you haven't produced any authoritative source to back your answer up.
TC++PL does make a comment that passing a signed char into the cctype
functions can be problematic but it gives no details.

A good indication that you should not do it if without a good reason, IMO.
But I'd like to understand the details. Do you know of any source that
explains them? TC++PL says, "discussion of [local conversion between
codesets] is beyond the scope of this book. Please consult your
implementation's documentation." Well, I did that above for several
implementations. Is this something that is purely implementation defined?
Jan 12 '07 #27
Daniel T. wrote:
>Those looks like the documentation of an implementation, non a standard
description.
Which is why I have been asking someone to look it up in the standard.
TC++PL says that implementation documentation is the authoritative
source.
The standard says nothing about the working of the C-inherited functions,
other than some minor variants, and refering to the appropriate C-standard
document.
Please, no need to be combative. If one wants to handle languages with
more characters than the ascii set, one is probably better off using
some form of unicode which means all of the functions in cctype are
useless.
Probably today is a better approach, but there are still a lot of programs
that use 8-bit national charsets. And in may cases a program can be quickly
adapted with a change of locale and rewriting it with unicode support is
not an option. And even using uft-8 encoded unicode some locales can
correctly support several of the is... functions.
>A good indication that you should not do it if without a good reason,
IMO.
But I'd like to understand the details. Do you know of any source that
explains them?
I think the base point is clear: ispunct and family takes and int and
expects it contains the EOF value or the int value of an unsigned char,
passing it a plain char does not grant this expectation. You can check the
man page of some unix system, they are usually less ascii-centric than
other sources, see for example:

http://www.die.net/doc/linux/man/man3/ispunct.3.html

Or refer to the C-standard documents. I don't have it at hand.

And, as others have pointed, the fact that some documents talks about
character presents in the ascii charset, does not necessarily mean that the
ascii encoding is used.
TC++PL says, "discussion of [local conversion between
codesets] is beyond the scope of this book. Please consult your
implementation's documentation." Well, I did that above for several
implementations. Is this something that is purely implementation defined?
I think this quote refers to more elaborated things than character
classification functions. Chapter and point?

--
Salu2
Jan 12 '07 #28
Julián Albo <JU********@terra.eswrote:
Daniel T. wrote:

I think the base point is clear: ispunct and family takes and int and
expects it contains the EOF value or the int value of an unsigned char,
passing it a plain char does not grant this expectation.
Unfortunately, I don't have the C standard either.
>
TC++PL says, "discussion of [local conversion between
codesets] is beyond the scope of this book. Please consult your
implementation's documentation." Well, I did that above for several
implementations. Is this something that is purely implementation defined?

I think this quote refers to more elaborated things than character
classification functions. Chapter and point?
Section 21.7, the last paragraph.

It seems though, that you are right in that if the programer has any
reason to expect that the 8th bit will be on for any character, he
should cast to unsigned char before passing the char to the cctype
functions.
Jan 12 '07 #29
Daniel T. wrote:
TC++PL says, "discussion of [local conversion between
codesets] is beyond the scope of this book. Please consult your
implementation's documentation." Well, I did that above for several
implementations. Is this something that is purely implementation
defined?
I think this quote refers to more elaborated things than character
classification functions. Chapter and point?
Section 21.7, the last paragraph.
This paragraph looks confusing to me (I have a edition in Spanish, but I
think the translation is very good, and the paragraph you quoted confirms
it). Maybe it means "consult (the C++ standard or more specialized books
and) your implementation's documentation".

--
Salu2
Jan 12 '07 #30
Julián Albo <JU********@terra.eswrote:
Daniel T. wrote:
TC++PL says, "discussion of [local conversion between
codesets] is beyond the scope of this book. Please consult
your implementation's documentation." Well, I did that above
for several implementations. Is this something that is purely
implementation defined?
>
I think this quote refers to more elaborated things than
character classification functions. Chapter and point?
Section 21.7, the last paragraph.

This paragraph looks confusing to me (I have a edition in Spanish,
but I think the translation is very good, and the paragraph you
quoted confirms it). Maybe it means "consult (the C++ standard or
more specialized books and) your implementation's documentation".
Hmm... The English version (3rd ed) says:

...a locale can also be used explicitly to control the appearance
of monetary units, dates, etc., on in put and output and conversion
between codesets. However, discussion of that is beyond the scope
of this book. Please consult your implementation's documentation.

Oh well.
Jan 12 '07 #31
Oh c*** - I'm talking to Andrew Koenig!?
:)
Thanks for discussing this though Andrew - I haven't had a discussion
that added spice to my blood in a couple of years!

Andrew Koenig wrote:
"Tr0n" <ol*********@hotmail.comwrote in message
news:eo**********@aioe.org...
>I suppose it really depends on what it is used for - but I still think <
is less error-prone than a != (as any value can be != - while you're
limiting a range using <) .

No -- it's more error-prone, not less, because it makes it easier for errors
to escape undetected.
You still won't give an example of these "errors".
While my example is not only already provided - you can also have
something like this:

int N=3; # This is the index limit we have
int incr=2; # This is the loop incremental
int n=0; # This is the initial index

while (n != N) {
cout << f(n) << endl;
n+=incr;
}

Could crash when going to index 4 - which is out-of-bounds.. Or still
loop until n goes out of the integer limit.
>
>If you wanted the last point using "i != N" then you're after N... Why not
just USE N?

Here is a concrete example of what I'm talking about.

Suppose I want to write a loop that calls f(n) for every value of (integer)
n such that n>=0 and n<N.
Right, from here I'll add some notes just to make sure I get the right
idea..

... 0 <= n < N
>
Then I might write a loop with an invariant such as

I have called f(n) for every value of n such that n >= 0 and n < i

and initially establish the invariant by writing

i = 0;

This initialization of i establishes the invariant because there are no
values of n that are both >= 0 and < i.

The loop itself might look like this

while (i != N) { /* or i < N */
// increase i while maintaining the invariant
f(i);
++i;
}

Now, suppose we want to prove that this loop does what we intend.
.... and that intent is to step through each index (n) in the range:
0 <= n < N while:
0 <= n < i must also be held true
Regardless of whether the loop condition is i != N or i < N, we have to
prove that the loop terminates.

If the condition is i != N, we can't prove that the loop terminates unless
we prove that N >= 0, a fact that you are claiming argues that i < N is
superior.

However, if the condition is i < N, that complicates the second part of the
proof. Because in that case, when the loop does terminate, we do not know
that i == n, which means that instead of proving the original requirement:
You mean i == N? (I take it as you do..)
Since n < i as part of your above proof.

I think you are also missing a third statement from your proof.. That
you will call all values of i in the range:
0 <= i < N,
or increment i by the smallest integer value.
>
we have called f(n) for every value of (integer) n such that n >= 0 and
n < N
Which can also be stated as:
You call f(n) for every value of n where 0 <= n < i while i != N
(conceivably allowing f(N) to be called if i goes above N)
>
we have instead proved

we have called f(n) for every value of (integer) n such that n >= 0 and
n < i, where i is an unknown value >= n
I take it again you meant i as an unknown value >= N .
Which contradicts itself as the value of N may have possibly been passed
to f(n) - which it is unable to do.

This is better stated:
You call f(n) for every value of n where 0 <= n < i while i < N

I'll state this here;
In both cases, we assume that i is increased by the smallest integer
value, in which case the condition before invalidating the i < N
condition is where i = N-1 .

If you at all change the incrementing of the loop - or N - you can end
up in dangerous territory.
>
In other words, in exchange for simplifying the proof of termination, we
have complicated the proof of correctness.

I would much rather simplify the proof of correctness, because if for some
reason the program doesn't terminate, we'll surely know about it. In other
words, I'd rather have a program that goes into an infinite loop than one
that quietly produces the wrong answer.
Again, I see no proof that either way can produce an incorrect answer.
If an 'incorrect' answer is produced, surely it is the code inside the
loop which would be at fault.
(I've put 'incorrect' as it is technically an 'undesired' or
'unexpected' result which is produced)
>
>>Personally, I would rather write my programs in a way that makes it
easier to prove correctness.
>.. I really don't like that.
Reminds me of all these buffer over-run errors where something unexpected
means CONSTANT bug-fixing.

I have no idea what you're talking about here.
Loading an input line (say from a file) into a data array (let's say
char[N}) while the length of the data is more than N.
(rather simplistic version)

Also errors where a program is 'expecting' something to be correct.
When have humans ever been perfect, and 'correct' all the time? And why
should our programs expect this?
>
>I just thought I'd post my thoughts on this, because I'd prefer my code to
do what I program - rather than produce a program which may do 'other
things'.

Exactly. And to be confident that your code does what you program, you
should make it as easy as possible to prove that it does what you intend.
I try to program so that my code WILL do what I intend, but from the
above analysis - you are coming from the reverse angle - your code is
proven after the fact.

Thanks again for the discussion, it's really been an eye-opener.

--
Tr**@Computer-Whizz.Linux.com

A pumpkin warrior, brave and good
The last survivor from the wood
So go now swiftly climb the stair
And cut a lock of witch’s hair.
Jan 13 '07 #32
"Tr0n" <ol*********@hotmail.comwrote in message
news:eo**********@aioe.org...
Oh c*** - I'm talking to Andrew Koenig!?
Um, yes.
Thanks for discussing this though Andrew - I haven't had a discussion
that added spice to my blood in a couple of years!
You're quite welcome.
Andrew Koenig wrote:
>"Tr0n" <ol*********@hotmail.comwrote in message
news:eo**********@aioe.org...
>>I suppose it really depends on what it is used for - but I still think <
is less error-prone than a != (as any value can be != - while you're
limiting a range using <) .

No -- it's more error-prone, not less, because it makes it easier for
errors
to escape undetected.

You still won't give an example of these "errors".
While my example is not only already provided - you can also have
something like this:

int N=3; # This is the index limit we have
int incr=2; # This is the loop incremental
int n=0; # This is the initial index

while (n != N) {
cout << f(n) << endl;
n+=incr;
}

Could crash when going to index 4 - which is out-of-bounds.. Or still
loop until n goes out of the integer limit.
Yes it could. However, this is something of an unusual example, as I think
you will see if you try to figure out the invariant of this loop.

It would be something like "we have called f(n) for values of n with the
following properties..." and because n is being incremented by a variable
(which, for all we know might change during the loop as a side effect of
calling f), those properties might be a bit of a pain to define exactly.
>>If you wanted the last point using "i != N" then you're after N... Why
not
just USE N?

Here is a concrete example of what I'm talking about.

Suppose I want to write a loop that calls f(n) for every value of
(integer)
n such that n>=0 and n<N.

Right, from here I'll add some notes just to make sure I get the right
idea..

.. 0 <= n < N
Yes.
>Then I might write a loop with an invariant such as

I have called f(n) for every value of n such that n >= 0 and n < i

and initially establish the invariant by writing

i = 0;

This initialization of i establishes the invariant because there are no
values of n that are both >= 0 and < i.

The loop itself might look like this

while (i != N) { /* or i < N */
// increase i while maintaining the invariant
f(i);
++i;
}

Now, suppose we want to prove that this loop does what we intend.

... and that intent is to step through each index (n) in the range:
0 <= n < N while:
0 <= n < i must also be held true
I prefer not to think of loops in terms of concepts such as "step through".
Instead, I like to think of them this way:

establish an invariant
while (a condition is true) {
change the values of variables while maintaining the truth of the
invariant
}

Then, after the loop terminates, I know that the invariant is still true,
and that the condition is now false.

In the example above, the invariant is

f(n) has been called for every integer n with 0 <= n < i

and the condition is i != N.
>Regardless of whether the loop condition is i != N or i < N, we have to
prove that the loop terminates.

If the condition is i != N, we can't prove that the loop terminates
unless
we prove that N >= 0, a fact that you are claiming argues that i < N is
superior.

However, if the condition is i < N, that complicates the second part of
the
proof. Because in that case, when the loop does terminate, we do not
know
that i == n, which means that instead of proving the original
requirement:
You mean i == N? (I take it as you do..)
Yes.
I think you are also missing a third statement from your proof.. That
you will call all values of i in the range:
0 <= i < N,
or increment i by the smallest integer value.
I don't understand this statement. I agree that it is necessary to prove
that we will call f(i) for all 0<= i < N, but that proof is a trivial
consequence of two claims:

1) The loop invariant is that we have called f(n) for all 0 <= n < i
2) After the loop terminates, i == N

The point is that the loop invariant is still true after the loop
terminates, so if i == N, we can substitute N for i in (1) above and see
immediately that we have called f(n) for all 0 <= n < N. If the loop
condition were i < N instead of i != N, we would still have to prove that i
N was impossible.
> we have called f(n) for every value of (integer) n such that n >= 0
and
n < N

Which can also be stated as:
You call f(n) for every value of n where 0 <= n < i while i != N
(conceivably allowing f(N) to be called if i goes above N)
Sorry -- when I said "we will call f(i) for all 0 <= i < N", I meant "for
all 0 <= i < N and no other values of i".
>we have instead proved

we have called f(n) for every value of (integer) n such that n >= 0
and
n < i, where i is an unknown value >= n

I take it again you meant i as an unknown value >= N .
Yes.
Which contradicts itself as the value of N may have possibly been passed
to f(n) - which it is unable to do.
Sorry; which *what* is unable to do?
This is better stated:
You call f(n) for every value of n where 0 <= n < i while i < N

I'll state this here;
In both cases, we assume that i is increased by the smallest integer
value, in which case the condition before invalidating the i < N
condition is where i = N-1 .

If you at all change the incrementing of the loop - or N - you can end
up in dangerous territory.
Indeed. But I think that's slightly off the point--at least the point I'm
trying to make.

The point I'm trying to make is that if your condition is i != N, you know
that after the loop terminates, i == N -- and you can use that fact in
reasoning about the program. If your condition is i < N, you know only that
i >= N, which is a weaker condition. So you have to go through additional
steps to show that even though i N might be possible after the loop has
terminated, it cannot have happened while the loop was executing.
>In other words, in exchange for simplifying the proof of termination, we
have complicated the proof of correctness.

I would much rather simplify the proof of correctness, because if for
some
reason the program doesn't terminate, we'll surely know about it. In
other
words, I'd rather have a program that goes into an infinite loop than one
that quietly produces the wrong answer.

Again, I see no proof that either way can produce an incorrect answer.
If an 'incorrect' answer is produced, surely it is the code inside the
loop which would be at fault.
(I've put 'incorrect' as it is technically an 'undesired' or
'unexpected' result which is produced)
I completely agree that it is possible to prove that either form of the loop
is correct. I'm just saying that the proof is easier if the condition is i
!= N than if it is i < N.
>>>Personally, I would rather write my programs in a way that makes it
easier to prove correctness.
>>.. I really don't like that.
Reminds me of all these buffer over-run errors where something
unexpected
means CONSTANT bug-fixing.

I have no idea what you're talking about here.

Loading an input line (say from a file) into a data array (let's say
char[N}) while the length of the data is more than N.
(rather simplistic version)
If we're going to talk about pragmatics here, then we get into matters of
taste and experience. My experience is that it is common for people to
write i <= N when they really meant i < N, and that the problems that result
from such errors are exceedingly difficult to find. My taste is therefore
that it would be better to write i != N, yielding a program that works or
fails catastrophically, instead of possibly writing i <= N instead of i < N,
yielding a program that might fail undetectably.

But that's a matter of taste, about which reasonable people can disagree.
Also errors where a program is 'expecting' something to be correct.
When have humans ever been perfect, and 'correct' all the time? And why
should our programs expect this?
Programs don't expect anything; programmers do.
>>I just thought I'd post my thoughts on this, because I'd prefer my code
to
do what I program - rather than produce a program which may do 'other
things'.
>Exactly. And to be confident that your code does what you program, you
should make it as easy as possible to prove that it does what you intend.
I try to program so that my code WILL do what I intend, but from the
above analysis - you are coming from the reverse angle - your code is
proven after the fact.
Proving code after the fact is extremely difficult, unless the code was
constructed in the first place to be easy to prove.
Thanks again for the discussion, it's really been an eye-opener.
You're quite welcome.
Jan 13 '07 #33

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: george | last post by:
Can anyone help? I query a database and return a result on the column "reference". There might be 7 listings. Each row is displayed in a table, with links through to a detail page. I am working...
6
by: Some Clown | last post by:
Greetings, I'm trying to figure out how to loop through a vector of strings, searching each item as I go for either a boolean condition or a "contains" test. So if my vector is called 'v' I...
7
by: Jose Cuthberto | last post by:
WRAPPER CODE FOR A SET OF HTML FILES, AND BUTTON BAR LOOKS LIKE BELOW: |< < <> > >| => <= O' (magnifying glass for small gif text) I have a number of isolated html files for a 1000 page...
7
by: John Smith | last post by:
Why in the printout of the following code s, t, and u only go up to 9 but w and x 10? I would think they would at least go up to the same number, be it 9 or 10. The last line of the printout is:...
5
by: zaemin | last post by:
From a web-site that teaches optimization for c, I saw bellow optimization rule. int fact1_func (int n) { int i, fact = 1; for (i = 1; i <= n; i++) fact *= i; return (fact);
4
by: Jim Bancroft | last post by:
Hi everyone, I've been working with ASP.Net for about a month, and in all the samples I've seen the authors know ahead of time how many DropDownLists or Labels they're going to need. My...
6
by: Gonzalo Monzón | last post by:
Hi all! I have been translating some Python custom C extension code into Python, as I need these modules to be portable and run on a PocketPC without the need of compile (for the purpose its a...
32
by: T. Crane | last post by:
Hi, I'm struggling with how to initialize a vector<vector<double>> object. I'm pulling data out of a file and storing it in the vector<vector<double>object. Because any given file will have a...
4
by: mark4asp | last post by:
I have an element, report which contains tags which have been transformed. E.g. <pis &lt;p&gt <myXml> <report>This text has html tags in it.&lt;p&gt which but <has been changed to &lt;&gt</report>...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.