Thursday, September 23, 2021

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

Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 23 02:03AM

> std::cin >> a >> b >> c;
> std::cout << a << " " << b << " " << c << "\n";
> }
 
Same thing.
But there is bug if user enters more or less then three. How you handle
that case?
In Swift:
let values = readLine()?.components(separatedBy: CharacterSet.whitespacesAndNewlines) ?? []
 
let valueOne = values.count > 0 ? Int(values[0]) : nil
let valueTwo = values.count > 1 ? Int(values[1]) : nil
 
so this handles correct.
 
 
> None of those problems appear in mine:
 
> * It reads at most 3 numbers from the line
 
> * If fewer are present, it'll read them as zeros
 
nowhere is clear from code.
read as you write, write as you speak, that's the rule...
 
 
> * If more, they are ignored. Whatever is entered on one line NEVER
/what if that is not desired behavior? it is not clear from code.
Don't do things behind peoples backs.
 
--
7-77-777
\|/
---
/|\
 
 
--
/Volumes/air AFP Music Volume/NATASA/temp/peste noire/(2007) Folkfuck Folie/04 - D'un Vilain.mp3
Paavo Helde <myfirstname@osa.pri.ee>: Sep 23 09:15AM +0300


> Strange that in a language that's supposed to support genericity and
> user provided allocators, we have these things that support neither
> genericity or user provided allocators.
 
std::to_string() is a convenience function, meant for people who are
uncapable of writing their own 3-liner wrappers around sprintf().
 
stream<< is generic, but potentially slower and not so convenient to
use, especially when the result should not go to a C++ stream.
 
std::to_chars() is fast, but not generic (plus it also lacks locale
support) and is not so convenient to use either as demonstrated by Alf's
multi-page example about how to use it. It does not use allocators though.
 
TBH, most std::string implementations are using short-string
optimization nowadays, so in most cases std::to_string() should not
involve any dynamic memory allocation either.
Juha Nieminen <nospam@thanks.invalid>: Sep 23 07:26AM


>> So what's the alternative that you suggest?
 
> Overloading whatever 'tostring' operations that are implicitly used when
> printing.
 
So your only alternative is to only support a "tostring" function?
 
How about thanks, but no thanks? I'll take the operator<< overloading
if your suggestions is the only available alternative.
 
> OK, let's try it. Here's a program that writes 1 million lines of the
> same 3 variables:
 
You are comparing the seed of std::ostream to some other way of writing
to a file. You are not comparing string creation vs. direct writing of
values.
Juha Nieminen <nospam@thanks.invalid>: Sep 23 07:31AM

>> program.
 
> Not at all. I used to write compilers and applications for 8-bit
> computers; I know how to be efficient!
 
If that were the case, then you would abhor the idea of forcing every
custom type to have a "tostring" function which is the only way to
add support to the standard printing function for your type.
 
> If you need to use sprintf() C, then that's when you might also consider
> using sprint() elsewhere.
 
sprintf() cannot be extended to support your own custom types.
Paavo Helde <myfirstname@osa.pri.ee>: Sep 23 11:05AM +0300

23.09.2021 10:31 Juha Nieminen kirjutas:
 
> If that were the case, then you would abhor the idea of forcing every
> custom type to have a "tostring" function which is the only way to
> add support to the standard printing function for your type.
 
And how is it better to force every custom type to add support for
std::ostream streaming? At least one can easily add formatting
parameters to tostring() functions, with streams it becomes complicated
and hidden.
 
If memory and speed issues are critical then most probably one cannot or
should not use iostreams anyway, so this point is moot.
Juha Nieminen <nospam@thanks.invalid>: Sep 23 08:28AM

> std::ostream streaming? At least one can easily add formatting
> parameters to tostring() functions, with streams it becomes complicated
> and hidden.
 
So, what's *your* suggested alternative?
 
(One could suggest std::format(), but AFAIK that's not going to be enormously
more efficient either. It's more of a convenience thing than an efficiency
thing.)
 
Whatever your suggestion may be, it would be nice if it could be used in
generic code, without much hassle. In other words, being able to do this
kind of thing:
 
template<typename T>
void foobar(int value, const T& obj)
{
std::cout << "With value " << value << " we got:\n" << obj << "\n";
}
 
Preferably whatever the solution is, it shouldn't require the type
to dynamically construct a string to be printed, and instead the
type should get an std::ostream (or FILE*, or whatever) that it
can use to directly write whatever it wants there.
 
I'm not saying such an alternative is impossible (which is better than
overloading operator<< for std::ostream). I'm just asking what it would
look like.
HorseyWorsey@the_stables.com: Sep 23 09:01AM

On Wed, 22 Sep 2021 14:13:39 -0700
>> who writes sensible code.
 
>Were you not aware that reaching the closing "}" of main() does an
>implicit "return 0;"?
 
And in C function return types default to int so perhaps for int functions
we shouldn't bother to specify the types? Whats your point? If he decides
to be a smartarse by using that syntax you'd think he'd dot all the i's etc.
Bart <bc@freeuk.com>: Sep 23 11:18AM +0100

On 23/09/2021 03:03, Branimir Maksimovic wrote:
 
> Same thing.
> But there is bug if user enters more or less then three. How you handle
> that case?
 
How do you handle it in C++? There, if the user enters less than 3,
nothing happens: the program apparenty hangs (waiting for more input).
If more than 3, it doesn't detect that either, until mysterious things
start happening on the next line.
 
If you put my example into a loop, then for inputs of:
 
10 20 30 40 50
100 200 300 400 500
 
where the user expects to see outputs of:
 
10 20 30
100 200 300
 
they will in fact see, after entering only 2 lines:
 
10 20 30
40 50 100
 
plus 200 300 400 as the output of a 3rd line that they haven't even
entered! Then '500' will figure as the first number of the next line.
 
It's missing an important thing: the ability to synchronise to each
fresh line of input.
 
In my version, there are a number of checks that can be made; missing
items are zero. Error flags are set and can be accessed by special reads:
 
read x:'E'
 
but which need to be done after item (I'd need to look into my code, as
I never bother for the casual use this is put to). In the dynamic
version, missing items are set to "", so you can check the type.
 
But you don't have to worry about input from multiple lines being
jumbled up and losing track of which was the first number on a line, or
using "," instead of " " screwing things up.
 
 
 
> let valueOne = values.count > 0 ? Int(values[0]) : nil
> let valueTwo = values.count > 1 ? Int(values[1]) : nil
 
> so this handles correct.
 
Yeah, this is Python-style too. You just grab the line of input as a
string, and then have to effectively do your tokenising and conversions.
 
But note that with this method, for the next line, it will discard the
last line and read a fresh line, unlike the C++. It will resync.
 
However, does you example allow spaces OR commas as separators?
 
>> * If more, they are ignored. Whatever is entered on one line NEVER
> /what if that is not desired behavior? it is not clear from code.
> Don't do things behind peoples backs.
 
Poeple are familiar with CLIs and know what to expect. Every fresh line
of input is separate. They don't get a CLI which effectively
concatenates all the user's input into one long line.
 
On a Windows prompt, I can do:
 
dir a b c
 
or I can do:
 
dir a, b, c
HorseyWorsey@the_stables.com: Sep 23 10:26AM

On Thu, 23 Sep 2021 11:18:02 +0100
>> But there is bug if user enters more or less then three. How you handle
>> that case?
 
>How do you handle it in C++? There, if the user enters less than 3,
 
You read in the entire line then split it up into tokens using whatever method
takes your fancy.
Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 23 10:26AM

> nothing happens: the program apparenty hangs (waiting for more input).
> If more than 3, it doesn't detect that either, until mysterious things
> start happening on the next line.
 
Same way as in Swift. getline on ' ' or '\'
 
Greetings, Branimir.
--
7-77-777
\|/
---
/|\
 
--
/Volumes/air AFP Music Volume/NATASA/temp/Exciter/heavy metal maniac/05 Mistress Of Evil.mp3
Bart <bc@freeuk.com>: Sep 23 11:29AM +0100

On 23/09/2021 08:31, Juha Nieminen wrote:
 
> If that were the case, then you would abhor the idea of forcing every
> custom type to have a "tostring" function which is the only way to
> add support to the standard printing function for your type.
 
I'm not forcing anything at all. Custom types can have dedicated
tostring routines; or use default ones; or have nothing.
 
You should look more towards scripting languages, you can learn a lot
from them! They will usually have default printing of any types.
 
(The first one I implemented was on IBM PCs with floppy disks, in
mid-80s. The advantage was that functionality of a program could be
stored as separate bytecode modules that could be loaded as needed,
easing pressure on main memory.
 
Of course, there were used where appropriate; not for the core routines
(of my GUI apps) that needed to be fast.)
 
>> If you need to use sprintf() C, then that's when you might also consider
>> using sprint() elsewhere.
 
> sprintf() cannot be extended to support your own custom types.
 
My point is that sprintf is used when you /want/ to end up with a
string. Which is what my sprint() version of my print statement does.
You didn't seem to like the idea of any print routine generating strings.
Bart <bc@freeuk.com>: Sep 23 12:21PM +0100


>> How do you handle it in C++? There, if the user enters less than 3,
 
> You read in the entire line then split it up into tokens using whatever method
> takes your fancy.
 
Example?
 
My original point was for a language to provide ready means to do
/line-oriented/ input.
 
You're saying each programmer needs to reinvent this stuff?
 
I've tested my version some more (still trying to read 3 integers):
 
Input Output of my code Output of C++ code:
 
"10" 20 30 10 20 30 Continuous zeros
123'456 7 8 123456 7 8 123 then myriad zeros
123_456 7 8 123456 7 8 Same
.1234 5 6 0 5 6 Same
-1234 5 6 -1234 5 6 -1234 5 6 (A miracle!)
123e4 5 6 123 5 6 Goes crazy like above
10,20,30 10 20 30 Goes crazy
10+20+30 10 0 0 10 20 30
10 10 0 0 Waits for more input
19000000000000000000 3 4
wrong val 3 4 i32.max then goes crazy
 
 
Mine could be improved; but the C++ definitely needs some attention.
 
7/10 and 3/10 respectively I think!
Bart <bc@freeuk.com>: Sep 23 12:40PM +0100

On 23/09/2021 12:21, Bart wrote:
>  123'456 7 8    123456 7 8              123 then myriad zeros
>  123_456 7 8    123456 7 8              Same
>  .1234 5 6      0 5 6                   Same
 
I mean same as the last example; just crazy stuff. Not the same as mine.
 
Example:
 
C:\c>a # C++ program with loop
Prompt> 123'456 7 8 # this is what is typed
123 0 0
Prompt> 123 0 0 # these appear automatically
Prompt> 123 0 0
Prompt> 123 0 0
Prompt> 123 0 0
Prompt> 123 0 0
Prompt> 123 0 0
Prompt> 123 0 0
Prompt> 123 0 0
Prompt> 123 0 0
....
Richard Damon <Richard@Damon-Family.org>: Sep 23 08:05AM -0400

On 9/23/21 7:21 AM, Bart wrote:
 
> Example?
 
> My original point was for a language to provide ready means to do
> /line-oriented/ input.
 
Then use line oriented processing. That would be gets (or maybe better
fgets to avoid overrun attacks) to get the line, and then parse with the
method you want, sscanf if you can deal with the default error handling.
 
C++ has similar functions for streams.
 
Don't complain that your hammer doesn't work well on screws.
 
Bonita Montero <Bonita.Montero@gmail.com>: Sep 23 05:38AM +0200

>> of writing your own state-machine ? That's much worse.
 
> I find state machines very clear and easy to follow as well as being explicit
> rather than having some stack in an unknown (from the programmers POV) state.
 
No, that's much less clearer than having a state like you're in a normal
function.
Juha Nieminen <nospam@thanks.invalid>: Sep 23 07:42AM

>>necessary variables are stored so that execution can continue from
>>the point where it left, and you have to manually create jump statements
 
> Isn't that the point of class methods and variables? Ie: Black boxing state.
 
I don't understand what that has anything to do with what I wrote.
 
Classes don't remove the need to manually write them, with all the
variables necessary to retain state, as said.
 
>>to wherever there are these yield points. (The more yield points there
>>are in your "coroutine", the more conditional gotos are required.)
 
> Having multiple yield points sounds like asking for sphagetti code.
 
No, yielding precisely *avoids* spaghetti code, because the complexity
is taken care by the compiler rather than explicitly by your code.
You won't have large switch blocks or chained ifs, with gotos or
function calls in each branch, nor separate classes or structs containing
the state of the function. Instead of all that, you have a single
'yield' at every location where you need to return to the caller. After
that the execution continues from there as if nothing had happened.
 
*Significantly* simpler.
 
>>thing a lot simpler, as at any point you can just add a yield, with
>>essentially no extra work to store the state of the decompressor.
 
> Hmm, not convinced thats any simpler than using object or global state.
 
So you think that a couple of 'yield' instructions here and there is
not any simpler than having to have some class or struct containing the
state of the decompresser, and some chained if, or a switch block, that
jumps wherever the processing was going on at that moment, based on those
state variables?
 
In that case, I don't know what to say.
Juha Nieminen <nospam@thanks.invalid>: Sep 23 07:45AM

> due to underlying OS design and/or limitations. This was MS's way of
> attempting to implement an alternative fake-multithreading that doesn't suck
> on their platform.
 
You seem to have a strange misconception that coroutines are nothing
but simulating multithreading in a single-threaded program.
 
They are aren't.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Sep 23 01:53AM -0700

On 9/23/2021 12:45 AM, Juha Nieminen wrote:
 
> You seem to have a strange misconception that coroutines are nothing
> but simulating multithreading in a single-threaded program.
 
> They are aren't.
 
Jeeze... This makes me think of the time I was using fibers in windows.
Iirc, it was for sorting things. Also, iirc, it was broken down into,
multiple fibers on a single thread. Multiple threads per process, then
multiple processes. This was so long ago its making my head itch. Back
on WinNT 4.0.
 
I had to use them in Linux as well. Iirc, setcontext comes to mind. ;^)
Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 23 09:05AM

>> rather than having some stack in an unknown (from the programmers POV) state.
 
> No, that's much less clearer than having a state like you're in a normal
> function.
coroutines are just same thing as threads except that cancellation points
yield context switch instead of preemptive scheduler, or this way should
be ...
 
--
7-77-777
\|/
---
/|\
 
--
/Volumes/air AFP Music Volume/NATASA/temp/peste noire/(2007) Folkfuck Folie/04 - D'un Vilain.mp3
HorseyWorsey@the_stables.com: Sep 23 09:11AM

On Thu, 23 Sep 2021 05:38:54 +0200
 
>> rather than having some stack in an unknown (from the programmers POV) state.
 
>No, that's much less clearer than having a state like you're in a normal
>function.
 
That is a matter of opinion.
HorseyWorsey@the_stables.com: Sep 23 09:14AM

On Thu, 23 Sep 2021 07:42:22 -0000 (UTC)
 
>I don't understand what that has anything to do with what I wrote.
 
>Classes don't remove the need to manually write them, with all the
>variables necessary to retain state, as said.
 
Where did I say they did? I'm saying the point of them is to black box state,
not that it doesn't require any effort to attain that.
 
>the state of the function. Instead of all that, you have a single
>'yield' at every location where you need to return to the caller. After
>that the execution continues from there as if nothing had happened.
 
Oh sure, just do a co_call or co_resume, obvious where it'll go. Not. Its
a magical mystery tour of the code dependent on the stack. At least state
machines are explicit.
 
>*Significantly* simpler.
 
Syntatically maybe.
 
>state of the decompresser, and some chained if, or a switch block, that
>jumps wherever the processing was going on at that moment, based on those
>state variables?
 
Yes.
 
>In that case, I don't know what to say.
 
Good, say nothing. We'll just have to disagree.
Bonita Montero <Bonita.Montero@gmail.com>: Sep 23 06:18AM +0200

Am 22.09.2021 um 21:37 schrieb Chris M. Thomasson:
>> different approaches in implementing a condvar for Win32. Maybe I can
>> implement some improvemehts here also.
 
>> You snipped it out.
 
You were referring to what I implemented so far.
And this wasn't a condvar.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Sep 22 10:23PM -0700

On 9/22/2021 9:18 PM, Bonita Montero wrote:
 
>>> You snipped it out.
 
> You were referring to what I implemented so far.
> And this wasn't a condvar.
 
Its been a while Bonita. Heck, last time I used a monitor was WAY back
when I was forced to work on some damn Java code, grrr. I was able to do
the work, but did not really, "enjoy" it so to speak, argh.
 
Actually, you are making me think back to a god damn horror show I had
to debug where it turned out that somebody thought it was a good idea to
use a condvar, with more than one mutex! My GOD!
Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 23 09:07AM


>>> You snipped it out.
 
> You were referring to what I implemented so far.
> And this wasn't a condvar.
 
condvar assumes way to signal state, and upon receiveing
signal to acquire lock, think about it.
 
--
7-77-777
\|/
---
/|\
 
--
/Volumes/air AFP Music Volume/NATASA/temp/peste noire/(2007) Folkfuck Folie/04 - D'un Vilain.mp3
Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 23 09:09AM


> Actually, you are making me think back to a god damn horror show I had
> to debug where it turned out that somebody thought it was a good idea to
> use a condvar, with more than one mutex! My GOD!
You can implement condvar via semaphore easilly and Windows has semaphores...
Think about it...
 
--
7-77-777
\|/
---
/|\
 
--
/Volumes/air AFP Music Volume/NATASA/temp/peste noire/(2007) Folkfuck Folie/04 - D'un Vilain.mp3
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: