- A failure to handle exceptions - 1 Update
- How to split a char array? - 9 Updates
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:
Post a Comment