Monday, March 28, 2016

Digest for comp.lang.c++@googlegroups.com - 10 updates in 2 topics

James Moe <jimoeDESPAM@sohnen-moe.com>: Mar 28 02:26PM -0700

On 03/26/2016 09:34 PM, Alf P. Steinbach wrote:
> byte size is formally Undefined Behavior.
 
> However, I'm sure that that's not your current problem, which seems to
> be using a very old compiler version.
 
So it would seem. I added initializing "txt = NULL" with no change in
execution.
 
> Oh well, that class is badly designed, but, it will probably do the job.
 
Thanks?
I haven't done any C++ programming in over a decade, and hadn't done
much before then.
 
--
James Moe
jmm-list at sohnen-moe dot com
"Heinz-Mario Frühbeis" <Div@Earlybite.individcore.de>: Mar 28 11:30AM +0200

Am 28.03.2016 um 01:39 schrieb Geoff:
 
>> Why?
 
> Because your copy call results in undefined behavior. The contents of
> the array will not be the zero-terminated string that strlen needs.
 
I difn't know that the zero.termination has to be set manually...
Thanks.
 
BTW: If I can use std::string, I will do that.
 
Regards
Heinz-MArio Frühbeis
 
#include <string.h>
//#include <algorithm>
 
using namespace std;
 
int main(){
char a[512];
char *b = a;
const char *nString = "Hallo";
copy(nString, nString + (strlen(nString)), b);
b[strlen(nString)] = '\0';
//for(int i = 0; i <= (int) strlen(b); ++i){
for(int i = 0; i < (int) strlen(b); ++i){
if(b[i] == '\0'){
cout << "A " << b[i] << "\n";
} else {
cout << "B " << b[i] << "\n";
}
}
cout << b << " " << strlen(b) << "\n";
cout.flush();
return 0;
}
 
Cout:
B H
B a
B l
B l
B o
A '\0'
Hallo 5
jt@toerring.de (Jens Thoms Toerring): Mar 28 11:22AM

> char a[512];
> char *b = a;
> const char *nString = "Hallo";
 
This makes 'nString' point to a (const) array of char
with 6 elements, that contains the following elements
 
'H', 'a', 'l', 'l', 'o', '\0'
 
Note the terminating '\0' - otherwise it wouldn't be
a string. A C-style string is always a char arry that
conatains a '\0', indicating where the string ends. And
this terminating '\0' is used by all the functions that
operate on strings to find the end. Thus, if there's
no '\0' it's not a string and none of the functions that
accept strings as their arguments can be used!
 
The terminating '\0' is the only thing that indicates
the length of the strings - there's no "hidden" vari-
able where that information would be stored and could
be retrieved by the functions operating on strings!
 
That's an important difference to a std::string, which
does keep track of the length of a string by other means!
(That also means that you never can have a '\0' in a C-style
string - it would be interpreted as the end of the string -
while you can store '\0' characters in std::strings.)
 
> copy(nString, nString + (strlen(nString)), b);
 
Here you copy only 5 of the 6 elements from 'nString',
missing the trailing '\0' - strlen() only gives you the
number of non-'\0' characters in a string. So 'b' isn't
pointing to a string, but to a mere array of chars. What
comes after these 5 characters is pure random garbage
and you can't forsee what it will be.
 
What you need is
 
copy(nString, nString + strlen(nString) + 1, b);
 
to also copy the trailing '\0'. (And you also would
need to copy 6 characters when using memcpy() or the
exact same reason!)
 
> for(int i = 0; i < (int) strlen(b); ++i){
> cout << b[i] << "\n";
> }
 
This is wrong. Since you didn't copy the terminating '\0'
to what 'b' points to strlen() can't be used because what
'b' points to isn't a string (remember a char array only
is a string if it contains a '\0' somewhere!). Instead
strlen() will keep on running over the array (or even past
its end!) until it finds a '\0' somewhere by chance. Its
result thus is completely bogus. Consider that a primitive
implementation of strlen() may just look like this:
 
size_t strlen(const char * str) {
size_t len = 0;
while (*str++ != '\0')
len++;
return len;
}
 
Thus everything printed out after the first 5 chars is
simply garbage and may be different each time you run
your program.
 
> cout << b << " " << strlen(b) << "\n";
 
And neither this can work since it also will print out cha-
racters until, by chance, there's a '\0' in the memory some-
where after what 'b' points to.
 
> cout.flush();
 
By the way outputting a 'std::endl' will both print out a
'\n' and flush the stream.
 
> o
> ?0 // 0 stands for '\0'
> Hallo0? 6
 
"?0' definitely doesn't stand for '\0'. '\0' can't be
printed. What you got there was some random garbage from
the mmeory pointed to by 'b' behind the 5 characters you
copied.
 
 
> Prints out:
> Hallo 5
 
> Why?
 
Because what's in 'a' is random and one thing that can happen
is that the sixth element of 'a', when it's not initialized.
is a '\0'. So it may seem to work at times.
 
And, BTW, you don't need the 'b' variable at all, you
could simply use 'a' instead - in most places 'a', when
not followed by an index in square braces, is taken to
be a pointer to the first element of 'a'.
 
It looks a bit as if you're trying to learn C/C++ by experi-
mentation. That's the worst way because these are languages
where minor mistakes can have really bad consequences and
where there's something called "undefined behaviour" which
means that the same code can seem to work at one time and
fail the next or seem to work on one platform but fail on
a different one. And 'fail' can mean a lot more than just
the program crashing...
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Mr Flibble <flibble@i42.co.uk>: Mar 28 03:31PM +0100

>> C++, is when you start using std::string and the standard containers,
>> and the things around them (algorithms and iterators).
 
> It's a short list in my opinion -- string, vector and deque.
 
Short list? ALL the containers have their uses.
 
/Flibble
woodbrian77@gmail.com: Mar 28 09:43AM -0700

On Monday, March 28, 2016 at 9:31:28 AM UTC-5, Mr Flibble wrote:
 
> > It's a short list in my opinion -- string, vector and deque.
 
> Short list? ALL the containers have their uses.
 
> /Flibble
 
We've been over this a few times. I remember David Brown
posting two scenarios where he thought using std::list
makes sense. I don't remember the scenarios now, but I
remember thinking that the second one he mentioned
was kind of far-fetched. Recently one of Ian's posts
made it clear that std::set is just a std::list that's
sorted. I almost never use any of the standard
containers other than vector or deque.
 
I don't really disagree with Jorgen's point. String,
vector and deque are important. You don't get them
though without classes so classes are the big advantage
of C++ over C.
 
Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net
"Öö Tiib" <ootiib@hot.ee>: Mar 28 11:53AM -0700

> makes sense. I don't remember the scenarios now, but I
> remember thinking that the second one he mentioned
> was kind of far-fetched.
 
Cheap split and merge of collections and persistent position of
an element in memory are the notable features of 'std::list'.
When such properties are not needed then other containers likely
fit better.
 
> Recently one of Ian's posts made it clear that std::set is just a
> std::list that's sorted.
 
What? Set is built upon weighted binary tree. There is too large
difference between sequence and tree.
 
> I almost never use any of the standard containers other than vector
> or deque.
 
May be you have limited use-cases?
 
> vector and deque are important. You don't get them
> though without classes so classes are the big advantage
> of C++ over C.
 
Flibble is correct that each container of standard library is performing
differently and so fits better than others into certain situations.
People tend to draw various decision charts how to choose
a container. http://i.stack.imgur.com/G70oT.png
Geoff <geoff@invalid.invalid>: Mar 28 01:12PM -0700

On Mon, 28 Mar 2016 11:30:34 +0200, Heinz-Mario Frühbeis
>B o
>A '\0'
>Hallo 5
 
In that case, eliminate all the standard library calls, eliminate the
copy function and use the std::string member functions without
worrying about arrays and pointers and all the fiddly bits. :)
 
#include <iostream>
using namespace std; //DON'T do this in production code.
 
int main()
{
const char *nString = "Hallo";
 
// copy-construct string from C string constant
string strn = nString;
strn.insert(3, "|");
cout << strn.data() << " " << strn.length() << "\n";
string::size_type pos = strn.find("|");
strn.erase(pos, 1);
cout << strn.data() << " " << strn.length() << "\n";
string mystring = "llo";
pos = strn.find(mystring);
strn.insert(pos + mystring.length(), "|");
cout << strn.data() << " " << strn.length() << "\n";
cout.flush();
return 0;
}
Mr Flibble <flibble@i42.co.uk>: Mar 28 09:13PM +0100


>> Short list? ALL the containers have their uses.
 
>> /Flibble
 
> We've been over this a few times.
 
You've been over this a few times and each time you are wrong.
 
/Flibble
Ian Collins <ian-news@hotmail.com>: Mar 29 09:15AM +1300

> was kind of far-fetched. Recently one of Ian's posts
> made it clear that std::set is just a std::list that's
> sorted.
 
Did I? Where?
 
--
Ian Collins
Daniel <danielaparker@gmail.com>: Mar 28 01:45PM -0700

On Monday, March 28, 2016 at 4:16:04 PM UTC-4, Ian Collins wrote:
> > made it clear that std::set is just a std::list that's
> > sorted.
 
> Did I? Where?
 
I think it was in the National Enquirer. Could be wrong.
 
Daniel
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: