Program to change case of user input, not reading spaces/symbols/already cased words..

Pages: 12
> 32 is the answer to 'a' - 'A' !

The value of 'a' - 'A' is implementation defined.

The standard specifies only this much: the null character is encoded with a value of zero; the encoded value of each decimal digit character after zero is one greater than the value of the previous.
Well it's better than just using 32!
Well it's better than just using 32!

No one "argh!ed" about my use of the "magic number +/- 32. Heh.
Rather than fix the problem some reasonable way (IMNSHO) the committee chose to introduce a new syntax which is non-obvious and just looks wrong. Like, how the quiznak are you supposed to get “assignment/initialization” out of int x {12};?

A web search, or a visit to the next room, I suppose. But the average C++ program wouldn't be substantially more efficient, correct, or cheaper if another notation was used instead of braces. Because the devil isn't in the notation, but in its semantics, which introduces some new problems and eliminates others.

Yeah, more arbitrary rules to be parachuted in, irrespective of context, like use auto.

This is asking for some Core Guidelines clickbait:
Write Good Code with these 100 simple rules!

On the other hand the folks who are responsible for that project know their stuff. And the project calls these entries guidelines by deliberate choice. I guess the reader is expected not to follow blindly.
= and {} are not equivalent. = will do a narrowing conversion whilst {} will generate a compile error.
A lot of people get bit by integer division. Initializing a floating point from the division of two (or more) integers using = is happily shined on by the compiler because an implicit conversion is allowed and happens.

Use uniform initialization and *BOOM!* You get a rude reminder things are not all kosher.

1
2
3
4
5
6
7
8
9
int main()
{
   int num1 { 2 };
   int num2 { 42 };

   // lots of code later

   double dbl { num1 / num2 };  // crash and BURN!
}

To smother the compiler with a pillow so it shuts up you have to make a cast. So the programmer and anyone who reads the code knows something is "off" with the line of code.

As someone mentioned using uniform initialization generates the same code as using =. Yet has additional safeguards against programmer boo-boos built in.

Don't like the syntax? You are free to not use it. It is MY choice.

Pax, I'm done with this triviality.
My whole point is that syntax matters to humans — and we see that regularly.

It would have been very easy to simply make the default standards err when a narrowing conversion is done, and require something explicit to tell the compiler you meant to do that. Older programs that would otherwise break can be compiled without problem using a compiler flag.

Instead we introduce a new, weird syntax to try to fix the problem.


And, I contend, it is a problem with the way C++ people are conditioned to think about their programming languages.

I personally prefer languages with less arcane minutiae in syntax to do something simple.


The common problem with num1 / num2 has nothing to do with the narrowing conversion (MSVC will warn about it unless you tell it to shut up), but the fact that / is an integer division because its operands are integers. This fits with C++’s ability to overload functions based on argument type, but confuses the snot out of people in the case of the division operator: people expect floating-point division and don’t get it. Hence the plethora of threads everywhere about making sure at least one operation is non-integer to effect a floating-point division:

    double x = (double)a / b;

That doesn't get the narrowing conversion warning/error simply because floating point division doesn’t return a different (larger) type than its operands like integer division does.

Many languages recognize that division is a particularly special case and provide a special operator to signify integer division is desired. For example, in Object Pascal I say:

    x := a / b;    // This is a floating-point division, regardless of operand type.
                   // If 'x' is real, the stored value is real. Else it is truncated to integer.

    x := a div b;  // This is an integer division. Operands must be integers.
                   // If 'x' is real, the stored value is promoted to real. Else it is integer.

That is straight-forward and instantly easy to grasp, something we cannot say about any C-derived language.


Furry Guy wrote:
Don't like the syntax? You are free to not use it. It is MY choice.

No, the choice is foisted on everyone whether they like it or not. I can present code to neophytes, grandparents, PhDs in mathematics, ...anyone, and they will nominally understand:

    double x = a / b;

but be unduly confused by:

    double x { a / b };

I’m not sure why you got so hot under the collar about this discussion though. C++ committee members obviously agree with you, not me.


But the fact that the language is at odds to what humans expect says something important, methinks.
Instead we introduce a new, weird syntax to try to fix the problem.

Opinion, not fact.

But then I don't find it weird.

Ciao.
I'll be honest, Thomas, if'n you had been less hostile and over-the-top irate maybe what you have to say might be worth reading. But you are getting all wee-weed up and obsessed over quite frankly what for me is a rather trivial bit of syntax.

You don't like it. Gee, I get it. Now you need to get OVER it.

Or not. Not my problem, never was.
I think you are reading a whole lot more into this than there is.

I have not been the least bit hostile, or irate.

I have been clear that it is my opinion from the start.

You might ask yourself why you are feeling so personally upset / attacked / defensive about it? It’s not like my opinion is going to change anything about C++. [edit] And I never thought that my commentary could be construed as a personal attack...
Last edited on
@Furry Guy, if you think all the recent changes to C++ are good, you probably need to stop and reflect on what @Duthomhas posted, you've clearly missed the point.
Well I put braces around function arguments - it at least helps at compile time, but really one needs to be doing runtime validation. And that is something neophyte coders generally don't do.

Defensive programming also says to check denominators before doing division, unless it can be proven that division will work given sane input.

I like the Pascal way in this case, but on the narrowing front, I wonder how many other languages have that? I see it as a very useful feature, along with const correctness and [[nodiscard]] .

Another aspect of this is the use of strong types. In the surveying world we have a plethora of angles, distances, and coordinate systems, and corrections or adjustments to them. All these values have a type of double, so I do:

template <int N>

This simplest form of template is very useful to create differing types on the value of N, and I use it for function overloading and validation classes. It also helps avoid large inheritance trees.

Strong types also help with preventing the coder from doing the wrong thing. For example in UTM (Universal Transverse Mercator) coordinate systems, each zone has a false NORTH ordinate of 10'000'000.000 metres at the equator, and a false EAST ordinate 500'000.000 metres on it's central meridian. Now it doesn't make any sense to add these world coordinates, but it is valid to subtract them to obtain a delta. Strong types can be used to enforce that.

Edit:

I also use explicit constructors with the strong types.
Last edited on
@kbw
I think there was just a miscommunication. Furry Guy tends to be very exacting in how he expresses his code, and I think he misunderstood my commentary to be attacking that — a valid reading of what was posted, even if it presupposes ill intent on my part. He may just be having a very bad day (or more), and that perspective leaked into his perception of my comments.

More on the narrowing:

It's one thing to loose significant figures in narrowing, but it is another when dealing with unsigned types:

1
2
3
4
5
6
7
void f(std::size_t a) {
   std::cout << a ;
}

int b = -1;

f(b);


So I do:

f({b}); //Houston we have a problem at compile time

So the thing to do here is to not use an unsigned type, so the value can be validated, trapped, and dealt with at runtime. But it is probably still worth putting braces around the argument anyway.

I was thinking it may be better to be able to use unsigned types more for things that are intrinsically unsigned:

1
2
3
constexpr unsigned short DaysPerWeek {7};
unsigned short Day;
std::cin >> Day;  // runtime problem input value is -1 


The problem is immediacy of the implicit cast. But the more I think about it being a language feature, then it would probably be some kind of exception, which is probably what validation code would do anyway.

So in the end it isn't worth worrying about because validation code is a fact of life, even if only for the domain of values.
Last edited on
Duothomas, my only real complaint was your apparent emphatic use of "ARGH!" to start off your commentary. Implying great disgust.

I am fully cognizant of the pros and cons of using uniform initialization, in all its myriad usages. I have my reasons for preferring it over using "=".

I wasn't having a "bad day" at all. I was merely more than a bit surprised at the perceived vehemence of your comment. Something I considered unwarranted and over the top.

I've been using uniform initialization in code example I post here for quite some time. Why now object?

If'n the discussion had included my usage of "magic numbers" then things might not have been so prone to misinterpretation and misunderstanding.

Explanations work wonders to soothe any ruffled feathers.

I'll still use it, along with other stylistic guidelines I use. Such as avoiding "using namespace std;" as if it were the plague.
You know me, if I can get some fun out of it I will. :0)

Imagine my “argh!” as the Macaulay Culkin version (https://www.youtube.com/watch?v=_qu4ZBCU6Fc&t=53s) — so yes, I was expressing that at the syntax.

There is no rhyme or reason for the timing, and your perception of vehemence is a little misplaced, though as I explained I do have a genuine (and reasoned) dislike for it.

Nothing to do about it but use it properly, though. You just happened to be the person present when my derailment soapbox came out.
Topic archived. No new replies allowed.
Pages: 12