Sunday, March 27, 2016

Digest for comp.lang.c++@googlegroups.com - 23 updates in 4 topics

"Heinz-Mario Frühbeis" <Div@Earlybite.individcore.de>: Mar 27 11:17AM +0200

Hi,
 
momentary I'm working on a Textbox and I had to remove a single char by
Backspace at cursor position...
 
So, if I have e.g. 'char mText[256];' and the string is 'Hallo', how can
I split, where e.g. cursor position == 3, to 'Hal' and 'lo'?
 
Currently my idea is to set 'mText[3] = '|'' and using 'strtok' with
char *ptr;
ptr = strtok(mText, "|");
.
 
But maybe there is a predefined / better way, a function?
 
Regards and Happy Easter
Heinz-Mario Frühbeis
Ian Collins <ian-news@hotmail.com>: Mar 27 10:23PM +1300

On 03/27/16 22:17, Heinz-Mario Frühbeis wrote:
> char *ptr;
> ptr = strtok(mText, "|");
> ..
 
Use std::string and substr(0,3).
 
--
Ian Collins
Barry Schwarz <schwarzb@dqel.com>: Mar 27 03:40AM -0700

On Sun, 27 Mar 2016 11:17:12 +0200, Heinz-Mario Frühbeis
 
>Currently my idea is to set 'mText[3] = '|'' and using 'strtok' with
>char *ptr;
>ptr = strtok(mText, "|");
 
What do you want the result to be?
 
If you set mText[3] to '|' you will lose the second 'l'. After
strtok, your array will end up with two strings: "Hal" and "o",
perhaps better represented as "Hal\0o\0"
 
Your description implies you want "Hal\0lo\0". If that is the case,
and you are restricted to using an array of char instead of a
std::string, you can use memmove which will support overlapping source
and destination areas. Something like
set index to location of split (3 in your sample)
memmove(mText+(index+1), mText+index, sizeof mText - (index+1));
mText[index] = '\0';
 
--
Remove del for email
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 27 03:03PM +0200

On 27.03.2016 11:17, Heinz-Mario Frühbeis wrote:
> Backspace at cursor position...
 
> So, if I have e.g. 'char mText[256];' and the string is 'Hallo', how can
> I split, where e.g. cursor position == 3, to 'Hal' and 'lo'?
 
It's probably better to use a std::string.
 
 
> Currently my idea is to set 'mText[3] = '|'' and using 'strtok' with
> char *ptr;
> ptr = strtok(mText, "|");
 
To remove the character at index 2 in zero-terminated string you can do
 
for( int i = strlen( mText ) - 1; i >= 2; --i )
{
mText[i] = mText[i+1];
}
 
 
> But maybe there is a predefined / better way, a function?
 
std::string
 
 
Cheers & hth.,
 
- Alf
"Heinz-Mario Frühbeis" <Div@Earlybite.individcore.de>: Mar 27 03:20PM +0200

Am 27.03.2016 um 12:40 schrieb Barry Schwarz:
> set index to location of split (3 in your sample)
> memmove(mText+(index+1), mText+index, sizeof mText - (index+1));
> mText[index] = '\0';
 
memmove is working well...
memmove(vText + (nCursorPos - 1), vText + (nCursorPos), nLen_of_Str -
(nCursorPos));
E.g.:
heinz (cursor behind i == 3) // I begin pos counting at 1
After Backspace:
henz
a.s.o
 
Thank you, sir!
Regards
Heinz-Mario Frühbeis
"Heinz-Mario Frühbeis" <Div@Earlybite.individcore.de>: Mar 27 03:23PM +0200

Am 27.03.2016 um 11:23 schrieb Ian Collins:
>> ptr = strtok(mText, "|");
>> ..
 
> Use std::string and substr(0,3).
 
I cannot (currently) use std::string as data type for the member var of
mText, because I (currently) have trouble with this and an event loop,
which is running in a pthread...
But maybe temporarly, but <again> memmove is working really fine.
 
Anyway, thank you, sir.
 
Regards
Heinz-Mario Frühbeis
"Heinz-Mario Frühbeis" <Div@Earlybite.individcore.de>: Mar 27 03:28PM +0200

Am 27.03.2016 um 15:03 schrieb Alf P. Steinbach:
 
>> So, if I have e.g. 'char mText[256];' and the string is 'Hallo', how can
>> I split, where e.g. cursor position == 3, to 'Hal' and 'lo'?
 
> It's probably better to use a std::string.
 
Easier<?>. Do not know...
 
> {
> mText[i] = mText[i+1];
> }
 
But this is only working good/fast enough for small arrays...isn't it?
 
>> But maybe there is a predefined / better way, a function?
 
> std::string
 
Currently I've trouble with std::string for the member var (mText),
probably by an event loop running in a pthread and using a callback and
manipulating the string.
 
I think, I will use memmove. I love the style "bit pushing". :)
 
Anyway, thank you.
Regards
Heinz-Mario Frühbeis
Jorgen Grahn <grahn+nntp@snipabacken.se>: Mar 27 02:17PM

On Sun, 2016-03-27, Heinz-Mario Frühbeis wrote:
>>> I split, where e.g. cursor position == 3, to 'Hal' and 'lo'?
 
>> It's probably better to use a std::string.
 
> Easier<?>. Do not know...
 
He's right.
 
IMO, the single place where you can gain the most from going from C to
C++, is when you start using std::string and the standard containers,
and the things around them (algorithms and iterators).
 
And there are almost never, IME, any reasons to fall back to the C
mechanisms.
 
...
> probably by an event loop running in a pthread and using a callback and
> manipulating the string.
 
> I think, I will use memmove. I love the style "bit pushing". :)
 
At least use the modern C++ mechanism instead of memmove. That
would be std::copy or std::copy_backward.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Paavo Helde <myfirstname@osa.pri.ee>: Mar 27 05:47PM +0200

On 27.03.2016 15:28, Heinz-Mario Frühbeis wrote:
 
> Currently I've trouble with std::string for the member var (mText),
> probably by an event loop running in a pthread and using a callback and
> manipulating the string.
 
If you use multithreading then you need to synchronize access to shared
data anyway, be it std::string or char array. It might be that the
race-condition bugs manifest themselves less often with arrays, but this
does not mean they are not bugs.
 
And if you use proper synchronization, then there are no problems using
std::string as shared data.
 
Also note that strtok() is not guaranteed to be thread-safe and uses
hidden state behind the scenes, so it would be better to avoid it
altogether.
 
> I think, I will use memmove. I love the style "bit pushing". :)
 
It looks like you actually want comp.lang.c, not comp.lang.c++. A major
benefit of C++ over C is that one can get rid of things like fixed-size
arrays, memmove and strtok.
 
HTH
Paavo
"Heinz-Mario Frühbeis" <Div@Earlybite.individcore.de>: Mar 27 10:13PM +0200

Am 27.03.2016 um 16:17 schrieb Jorgen Grahn:
> On Sun, 2016-03-27, Heinz-Mario Frühbeis wrote:
>> Am 27.03.2016 um 15:03 schrieb Alf P. Steinbach:
>>> On 27.03.2016 11:17, Heinz-Mario Frühbeis wrote:
 
[...]
 
>> I think, I will use memmove. I love the style "bit pushing". :)
 
> At least use the modern C++ mechanism instead of memmove. That
> would be std::copy or std::copy_backward.
 
I've made a little test and I noticed a weird<?> behaviour...:
 
[Ah first]:
Here
<http://www.cplusplus.com/reference/algorithm/copy/>
is to read:
#include <algorithm> // std::copy
 
But my Test-Prog is working with 'string.h', too. Why?
 
Now...
 
int main(){
char a[512];
char *b = a;
const char *nString = "Hallo";
copy(nString, nString + (strlen(nString)), b);
for(int i = 0; i < (int) strlen(b); ++i){
cout << b[i] << "\n";
}
cout << b << " " << strlen(b) << "\n";
cout.flush();
return 0;
}
 
Cout prints:
H
a
l
l
o
0 // 0 stands for '\0'
Hallo0 6
 
But:
int main(){
char a[512];
char *b = a;
const char *nString = "Hallo";
copy(nString, nString + (strlen(nString)), b);
cout << b << " " << strlen(b) << "\n";
cout.flush();
return 0;
}
 
Prints out:
Hallo 5
 
Why?
 
Regards
Heinz-Mario Frühbeis
woodbrian77@gmail.com: Mar 27 04:10PM -0700

On Sunday, March 27, 2016 at 9:18:02 AM UTC-5, Jorgen Grahn wrote:
 
> IMO, the single place where you can gain the most from going from C to
> 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.
 
 
> And there are almost never, IME, any reasons to fall back to the C
> mechanisms.
 
Probably std::array<char, n> works fine.
 
Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net
Geoff <geoff@invalid.invalid>: Mar 27 04:39PM -0700

On Sun, 27 Mar 2016 22:13:10 +0200, Heinz-Mario Frühbeis
 
>Prints out:
>Hallo 5
 
>Why?
 
Because your copy call results in undefined behavior. The contents of
the array will not be the zero-terminated string that strlen needs.
Both versions are erroneous and both result in UB. That you get 5 in
the second instance is a function of whether or not the array was
initialized with zeros or not.
 
You should probably begin by writing C++, not C.
 
int main() {
const std::string str = "Hallo";
std::string strn = str;
strn.erase(3, 1);
std::cout << strn.data() << " " << strn.length() << "\n";
std::cout.flush();
return 0;
}
ram@zedat.fu-berlin.de (Stefan Ram): Mar 27 01:34AM

> default: txt = "Unhandled Error"; beak;
 
»beak«?
 
Why no SSCCE?
ram@zedat.fu-berlin.de (Stefan Ram): Mar 27 04:06AM

>call my custom algorithm with these two iterators.
>{ int N; ::std::cin >> N; ::std::vector< int >v( N );
> algorithm( v.begin(), v.end() ); }
 
You might think that it wastes resources to create a vector
of N ints just to encode the number N. This remembers me of
a part of an interview with Alexander Stepanov from 1998
where he said:
 
»It would be much nicer if begin and end were global - it
would allow us to define them for C arrays. It would be
so much nicer if operator* was global with the default
definitions:
 
template <class T> T& operator*(T& x) { return x;}
 
template <class T> const T& operator*(const T& x) { return x;}
 
It would allow us to write:
 
copy(0, 25, ostream_iterator<int>("\n"));«.
 
In the meantime, the global »begin« and »end« became a
reality, even »cbegin« and »cend«. And today, they are
recommended instead of the element functions. Maybe one
day we will even get the global dereference operators that
dereferences non-iterators to themselves!
ram@zedat.fu-berlin.de (Stefan Ram): Mar 27 05:34AM

>least the idea of the triad of functions begin(), end() and (c++17)
>size(), ever since I failed to attribute it at all in a blog posting
>long ago, and tried to make up for it.
 
That Stepanov said it in an interview in 1998 does not
exclude that Dietmar Kuehl said it earlier.
 
And since you mention »size«, Stepanov also said in the same
interview that its complexity was and should be linear not
constant. But he was not able to get this into the standard.
(The linear complexity would allow one to dispense with a
counter within the container in some cases.)
 
>length() for a string, say. In particular n_items() does not naturally
>map to the size() member function of std::bitset, but rather to its
>dynamic count(), which corresponds to the dynamic .size() of a std::set.
 
»Logical function« goes in this direction, I think:
 
If there should be a global, general »size« it must have a
single (not using distinct cases) English-language
specification that allows one to deduce its meaning for any
special case so that it can be used meaningfully and
consistent in generic algorithms in as many cases as
possible where this makes sense.
ram@zedat.fu-berlin.de (Stefan Ram): Mar 27 11:33PM

>So, if I have e.g. 'char mText[256];' and the string is 'Hallo', how can
>I split, where e.g. cursor position == 3, to 'Hal' and 'lo'?
 
No specification is given for »split«. When would a char
array be considered to »be split at a given position«?
 
I'd say that the split is nothing more than the pair
of the array and the position. We can then, for example,
print the two parts or do any other operation as seen fit:
 
#include <stdio.h>
 
struct split
{ int position;
char const * array; };
 
void struct_split_init
( struct split * const s,
int const p,
char const * const a )
{ s->position = p;
s->array = a; }
 
void struct_split_print_first( struct split const * const s )
{ printf( "%.*s\n", s->position, s->array ); }
 
void struct_split_print_second( struct split const * const s )
{ printf( "%s\n", s->position + s->array ); }
 
int main( void )
{ struct split s;
struct_split_init( &s, 5, "hello, world" );
struct_split_print_first( &s );
struct_split_print_second( &s ); }
 
hello
, world
James Moe <jimoeDESPAM@sohnen-moe.com>: Mar 26 05:46PM -0700

gcc v3.3.5
 
When the exception is thrown "throw error_handler(pmmsend_rc)" the
program aborts (SIGABRT). The constructor completes; the abort occurs
after initialization, presumably in the catch() statement.
I can see no reason for this unreasonable behavior.
Am I missing anything? Or should I blame the compiler?
 
 
class error_handler {
private:
const char * txt;
pmmsend_return_code_t rc;
 
public:
error_handler (pmmsend_return_code_t err_rc = RC_NO_ACTION) { rc =
err_rc; }
pmmsend_return_code_t return_code () const { return rc; };
 
const char * return_text () {
switch (rc)
{
default: txt = "Unhandled Error"; beak;
case RC_NO_ERROR: txt = "No Error"; break;
case RC_NO_ACTION: txt = "Nothing happened"; break;
case RC_HELP: txt = "Help displayed"; break;
// more to come...
}
return txt;
}
};
 
int main (int argc, char *argv[])
{
pmmsend_return_code_t pmmsend_rc = RC_NO_ACTION;
prog_args_t prog_args;
 
try {
if (RC_NO_ERROR != pmmsend_rc) // Make it fail
throw error_handler(pmmsend_rc);
 
// build message
// send message
}
catch (const error_handler & ex) {
cerr << "Error: " << ex.return_code() << endl;
}
catch (...) {
cerr << "Splat! The unhandled error." << endl;
}
 
exit(pmmsend_rc);
 
}
 
 
 
--
James Moe
jmm-list at sohnen-moe dot com
Ian Collins <ian-news@hotmail.com>: Mar 27 02:05PM +1300

On 03/27/16 13:46, James Moe wrote:
> gcc v3.3.5
 
Why? That very old.
 
Try the code with a modern compiler and see if the problem is still there.
 
When I try your code. I get
 
Error:0
 
--
Ian Collins
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 27 06:34AM +0200

On 27.03.2016 01:46, James Moe wrote:
> error_handler (pmmsend_return_code_t err_rc = RC_NO_ACTION) { rc =
> err_rc; }
> pmmsend_return_code_t return_code () const { return rc; };
[snip]
 
> if (RC_NO_ERROR != pmmsend_rc) // Make it fail
> throw error_handler(pmmsend_rc);
 
At this point you're copying the uninitialized pointer in member `txt`.
 
Copying (or even just inspecting) an indeterminate value of greater than
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.
 
With a newer compiler you get access to such goodies as
`std::system_error`, which passes an error code, with default
interpretation as a Posix error.
 
Oh well, that class is badly designed, but, it will probably do the job.
 
 
Cheers & hth.,
 
- Alf
 
PS: Calling `exit` at the end of `main` is sort of redundant. That's
what happens anyway on return from `main`. You should just return. ;-)
"Öö Tiib" <ootiib@hot.ee>: Mar 27 08:31AM -0700

On Sunday, 27 March 2016 02:47:19 UTC+2, James Moe wrote:
> gcc v3.3.5
 
On what platform?
 
> after initialization, presumably in the catch() statement.
> I can see no reason for this unreasonable behavior.
> Am I missing anything? Or should I blame the compiler?
 
Impossible (I will explain at end) to tell from your post but there is
always little chance of compiler defect.
 
The gcc 3.3 is over 10 years old version. If it is really an issue
with it and it was not fixed in gcc v3.3.6 then it will be likely
never fixed and so you have to work around of it.
 
Better take gcc 4.9.3 or 4.8.5 if you don't want to risk with the
bleeding edge 5. series. Likelihood of compiler defect to be fixed
(if found) is lot greater with newer compilers.
 
Do not erase #includes and declarations and other important things
if you post a test. Always try the test code if it manifests your
problem or not.
 
> private:
> const char * txt;
> pmmsend_return_code_t rc;
 
'pmmsend_return_code_t' undefined, I assume enum.
 
 
> public:
> error_handler (pmmsend_return_code_t err_rc = RC_NO_ACTION) { rc =
> err_rc; }
 
The 'txt' member uninitialized. U
 
> switch (rc)
> {
> default: txt = "Unhandled Error"; beak;
 
The 'beak' is unknown identifier.
 
> {
> pmmsend_return_code_t pmmsend_rc = RC_NO_ACTION;
> prog_args_t prog_args;
 
Unknown type 'prog_args_t' and unused variable 'prog_args'.
 
> cerr << "Splat! The unhandled error." << endl;
> }
 
> exit(pmmsend_rc);
 
replace 'exit' with 'return'.
 
 
> }
 
Can't reproduce your error. Highly likely you edited its reason away.
Keywords like 'beak' indicate that you never attempted to compile and
run posted code. But it may also be that compiler contained a defect.
IOW we are not psychic, sorry.
woodbrian77@gmail.com: Mar 27 11:29AM -0700

On Saturday, March 26, 2016 at 7:47:19 PM UTC-5, James Moe wrote:
> return txt;
> }
> };
 
That class name is misleading in my opinion.
 
> throw error_handler(pmmsend_rc);
 
> // build message
> // send message
 
I'm interested in what you are doing with messages. I'm
working on some software to build and send messages.
 
I have an offer to help someone on their project if
they are willing to use my software in their project.
Specifically, I'll donate 16 hours a week for 6 months
to a project that uses my software. If someone provides
me with a successful reference for this, I'll give them
$3,000 cash and a $2,000 investment in my company. There
are more details about this here -
http://webEbenezer.net/about.html .
 
That page has been titled "Making programming fun again"
for years. I've recently been enjoying a song called
"Everything Comes Alive" by an Irish band called "We are
Messengers." As ambassadors of The King, messages are
near and dear to us.
 
Maybe someone has had to put a project in mothballs for a
while. This could be an opportunity to resurrect your project.
 
Brian
Ebenezer Enterprises
http://webEbenezer.net
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 27 06:53AM +0200

On 27.03.2016 06:06, Stefan Ram wrote:
> recommended instead of the element functions. Maybe one
> day we will even get the global dereference operators that
> dereferences non-iterators to themselves!
 
Oh thanks. I've always attributed this idea to Dietmar Kuehl. Well, at
least the idea of the triad of functions begin(), end() and (c++17)
size(), ever since I failed to attribute it at all in a blog posting
long ago, and tried to make up for it.
 
Hrmf.
 
So, it was Stepanov, I should have guessed. :)
 
 
Cheers!,
 
- Alf
 
PS: Now that C++ is in the process of gaining a global size() function,
I have changed my view of it. I now think a size() function is *wrong*,
because it conflates two or three logical functions. Namely,
static_size() for arrays, n_items() for a dynamic size collection, and
length() for a string, say. In particular n_items() does not naturally
map to the size() member function of std::bitset, but rather to its
dynamic count(), which corresponds to the dynamic .size() of a std::set.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 27 08:05AM +0200

On 27.03.2016 07:34, Stefan Ram wrote:
 
[snip]
> special case so that it can be used meaningfully and
> consistent in generic algorithms in as many cases as
> possible where this makes sense.
 
Yes. Here's my (static, constexpr) static_size:
 
template< class Type, size_t n >
constexpr
auto static_size( In_ref_<Raw_array_of_<n, Type>> )
-> Size
{ return n; }
 
template< class Type, size_t n >
constexpr
auto static_size( In_ref_<Array_of_<n, Type>> )
-> Size
{ return n; }
 
template< size_t n >
constexpr
auto static_size( In_ref_<std::bitset<n>> )
-> Size
{ return n; }
 
And here's the (dynamic) n_items:
 
template< class Type >
auto n_items( In_ref_<Type> o )
-> Size
{ return o.size(); }
 
template< size_t n >
auto n_items( In_ref_<std::bitset<n>> o )
-> Size
{ return o.count(); } // Corresponds to std::set<int>::size()
 
template< class Type, size_t n >
constexpr
auto n_items( In_ref_<Raw_array_of_<n, Type>> a )
-> Size
{ return static_size( a ); }
 
The latter is in the process of being [1]overhauled, in order to support
overloads for base classes called with derived class arguments.
 
In addition there's length_of_literal, length and is_empty.
 
Shameless plug: this is all part of the still-in-flux [2]cppx library.
 
 
Cheers!,
 
- Alf
 
Notes:
[1] <url:
http://stackoverflow.com/questions/36232418/make-fooderived-object-x-call-foobase-const-x-instead-of-template-fun/36232419#36233442>
[2] <url: http://alf-p-steinbach.github.io/cppx/>
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: