Anyone interested in giving feedback on program/app I created?

Pages: 123
Two items I can think of off the top of my head that were removed are the smart pointer std::auto_ptr and the std::random shuffle algorithm.
Well it's a good thing that I have no idea what those are then :)

That has changed. C++11 added the <random> library, along with the <chrono> for C++ time usage.
I'm actually quite glad to hear that.. Every time I've had to use a random number generator I've found it to suck really bad... I guess I also have to get myself into <chrono> since my program uses <time.h> which I find sucks arse too.

Haha that dude in the video against the use of rand() is awesome! I can't help but cringe though about his braces. Is there one way of formatting code, or a known better way? I really cringe when I read code written like that
1
2
3
4
5
void foo() {
    for (int count = 0; count <= 10; count ++) {
        std::cout << "\nIterator is : " << count;
    }
} 


Instead I'm either used to
1
2
3
4
5
6
7
void foo()
{
    for (int count = 0; count <= 10; count ++)
    {
        std::cout << "\nIterator is : " << count;
    }
} 
or
1
2
3
4
void foo()
{
    for (int count = 0; count <= 10; count ++) { std::cout << "\nIterator is : " << count; }
} 

I find it easier to read and easier to see how braces connect to one another.

Am I doing anything wrong?

Which brings up another topic I am evangelically militant about (militantly evangelical?), how to generate random number in C++.
Haha maybe both, depending from where you look at things :)
Last edited on
"The Proper Way To Format" inspires Religious Wars. Brace Placement, Indent Size, Spaces vs. Tabs.

I prefer opening and closing braces that line up, vs. the K & R style of your first example.

Though on occasion I've done the all-on-the-same-line formatting as in your 3rd example.

My indents are 3 spaces, not a tab that moves 3 spaces.

Formatting is IMO all about HUMAN readability. As long as the formatting is consistent and understandable, then great. The preprocessor and compiler don't give a tinker's dam about whitespace.

So, no, you are not doing anything wrong. :)

If you get hired to code and the company has a different style, you have to adapt.

One feature of Visual Studio I really like is formatting can be done "on the fly." As you type, or when you copy'n'paste some code.

The rules for formatting are quite extensive, and changeable via Options.
"The Proper Way To Format" inspires Religious Wars. Brace Placement, Indent Size, Spaces vs. Tabs.
Haha sounds like you have some experience in the matter, maybe it's related to all those things you're evengically militant about? :)

I prefer opening and closing braces that line up, vs. the K & R style of your first example.
So you mean my 2nd example?

My indents are 3 spaces, not a tab that moves 3 spaces.
That sounds peculiar, I actually haven't seen or heard people talk about preferring spaces, most of the time it seems to be frowned upon. So when you're writing code you physically have to press the space bar 3 times when going on a new line? Isn't that sort of tedious? (unless you use some sort of macro to have your keyboard do that for you).

One feature of Visual Studio I really like is formatting can be done "on the fly." As you type, or when you copy'n'paste some code.
Oh that sounds interesting, I didn't know that, I'll have to check out that option.
So when you're writing code you physically have to press the space bar 3 times when going on a new line?

heck no lol. Only an idiot would put up with that for more than 5 min.
modern editors have a 'replace tab with spaces' -- configurable by how many. When I press the tab key on the keyboard, it inserts spaces to the tab stop, that is, if I set it to 5 spaces, and am in column 3, it adds 2 spaces. If I am in column 1, it adds 5 spaces. Or whatever ... point it is moves the cursor to the right 'tab stop' location and injects spaces to get there. The result is EXACTLY like tab except its filed with multiple spaces instead of 1 tab character.

- spaces take up more space (hah!). The text file is larger in terms of pure bytes, often by a fair amount.
- spaces may not look right if for some insane reason your editor is not using fixed width fonts.
- spaces may be cleaned up incorrectly, eg replace all double space with single space to clean up will bork things. It is less common to do a blanket replace of double tab or whatever.

on the other side, tabs can get kind of nuts in some languages. they are too big. Like javascript, its not uncommon to be inside 8 pairs of {} which is a lot less aggravating if its 2 or 3 spaces instead of tab-5. Tabs are also configurable in modern editors, but the default is too big for some code.
Ive been known to single space indent. I do not need much to see that something is inside something else. So I generally use space over tab in spite of the drawbacks.
I really only have a few things I get grouchy about. Brackets need to align in columns is one of my very short list of must haves. If it does not, I will happily run a program over it that fixes that problem, I don't complain, I just fix it and move on, takes a nano second. For that matter, replace all \t with triple space is only a nanosecond to do as well. No sense getting all bent out.
Last edited on
Let me state flat out what follows is part of MY formatting style; others can and will likely disagree.

So when you're writing code you physically have to press the space bar 3 times when going on a new line?

No.

The VS formatting setup lets you set the tab indent size, and whether it uses tabs as tabs or converts tabs to spaces.

I hit tab and the VS editor puts in 3 spaces.

If I copy and paste code that uses tabs VS changes the tabs to spaces.

If I copy and paste code that is indented less than 3 spaces, or more than 3, it uses 3 spaces for the indent.

Your first example is K&R style formatting, your second is Allman style.

Your third example is not a style that is officially named that I can find.

VS lets you set how brace control blocks are style formatted.

https://en.wikipedia.org/wiki/Indent_style#Brace_placement_in_compound_statements

That same page also talks about the religious wars over tabs vs. spaces

I generally follow Allman style, with a mandatory braces variation.

https://en.wikipedia.org/wiki/Indent_style#Variant:_mandatory_braces

Here's a code snippet that "misuses" whitespace without control braces, to a casual reader the actual execution flow is obscured:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

int main()
{
   std::cout << "Enter a number less than 10 or greater than 100: ";
   int x { };
   std::cin >> x;
   std::cout << '\n';

   if (x >= 10)
      if (x > 100)
         std::cout << "More than 100, Thanks!\n";
   else // not the else intended!
      std::cout << "Less than 10, Thanks!\n";
}

The else statement belongs to the second if, not the first. If I were to paste that code into VS, it would automatically be properly formatted. Indenting the else clause to its proper place

I personally go one step further, with "mandatory" braces:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

int main()
{
   std::cout << "Enter a number less than 10 or greater than 100: ";
   int x { };
   std::cin >> x;
   std::cout << '\n';

   if (x >= 10)
   {
      if (x > 100)
      {
         std::cout << "More than 100, Thanks!\n";
      }
   }
   else // fixed!
   {
      std::cout << "Less than 10, Thanks!\n";
   }
}

Now it is very obvious where the else chains up. By brace usage and indentation.

For me readability is improved for what is intended.

Should I decide later to add one or more statements to the else clause they will be properly contained since the brace control block is already there.

I set VS to do brace completion, if I type an opening brace the editor automatically adds the closing brace.

The bottom line is IMO:

No matter what formatting style one uses, use it as consistently as possible for readability.

If on occasion using the third style you posted doesn't decrease readability, then I use it.
Last edited on
@jonnin

I see what you mean, that makes as lot of sense actually. I've struggles myself sometimes with indents, after like 3-4 nested loops you end up way to the right of the page and if you're working with several windows on your computer it can get annoying.

I'll try to experiment with that and mess around with the settings in VS since I really compact yet clear code. It's really interesting though, because when you start learning programming you just pick up the style from your book or whatever and you're not really confronted to other styles until you exchange or look at other people's code.


@Furry Guy

If I copy and paste code that uses tabs VS changes the tabs to spaces.
That sounds really handy

Dear god, when I look at your link fro Wikipedia all of the brace placement below Pico are hurting me on a physical level haha, do people actually write that way, and god why? O_o

I'm on board with what you call mandatory brace, I think it increases readability by quite a lot and do it most of the time, even though if what follows ifor else statement isn't long at all, I like plopping it on the same line like in my 3rd example because in the instance of long functions for instance it can take up quite some space, vertically.


That brings me to another formatting style questions. On the one hand you have braces but on another I'm never consistant about variable definition and cout statements. How do you go about spacing those.

Here are some examples to illustrate what I mean, I'm conflicted between the following and never consistently know what to chose:
1_
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

int main()
{
    int i1 = 1, i2 = 2, i_result;
    double d1 = 5.5, d2 = 10.8, d_result;
    
    i_result = i1 + i2;
    d_result = d1 + d2;
    
    std::cout << "i_result is : " << i_result;
    std::cout << "\nd_result is : " << d_result;
    
    return (0);    
}

2_
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

int main()
{
    int i1 = 1,
        i2 = 2,
        i_result;
    double d1 = 5.5,
           d2 = 10.8,
           d_result;
    
    i_result = i1 + i2;
    d_result = d1 + d2;
    
    std::cout << "i_result is : " << i_result;
    std::cout << "\nd_result is : " << d_result;
    
    return (0);    
}

3_
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

int main()
{
    int i1 = 1,
        i2 = 2,
        i_result;
    double d1 = 5.5,
           d2 = 10.8,
           d_result;
    
    i_result = i1 + i2;
    d_result = d1 + d2;
    std::cout << "i_result is : " << i_result;
    std::cout << "\nd_result is : " << d_result;
    
    return (0);    
}

EDIT: 4_ I also find myself doing this (durr I'm so inconsistent...)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

int main()
{
    int i1 = 1,
        i2 = 2,
        i_result;
        
    double d1 = 5.5,
           d2 = 10.8,
           d_result;
    
    i_result = i1 + i2;
    d_result = d1 + d2;
    
    std::cout << "i_result is : " << i_result;
    std::cout << "\nd_result is : " << d_result;
    
    return (0);    
}


For some reason I always my cout statements to be separate from any other statement which can sometimes leave quite some white spaces everywhere..
Last edited on
Don't stress so much over your style, whatever makes your code easier for you to read and understand, great.

As long as you are the one who regularly reads it. If you are an employee doing the coding, then you need to follow the company's style guidelines.

How and why I would mangle stylistically your example code (ignore the excessive comments, added for illustrative purposes):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// no "unnecessary" headers, include only the ones you use
#include <iostream>

int main()
{
   // using old style variable initialization
   // one variable per definition
   int i1 = 1;
   int i2 = 2;

   // I prefer uniform initialization
   double d1 { 5.5 };
   double d2 { 10.8 };

   // uniform initialization catches type mismatch/implicit conversion problems

   // initializing an int variable with a double value truncates
   int bad_int = 12.5;

   // using uniform initialization catches the problem
   // VS stops the compilation, other compilers issue a warning
   int bad_int2 { 14.7 };

   // define a variable as close to where you use it as possible
   int i_result = i1 + i2;

   // I prefer to have an output generate a newline
   // if the next output is to occur on a new line
   std::cout << "i_result is : " << i_result << '\n';

   double d_result { d1 + d2 };

   std::cout << "d_result is : " << d_result << "\n\n";

   std::cout << "Enter an integer: ";
   int input { };
   std::cin >> input;
   std::cout << '\n';  // <--- gotta skip to a newline

   std::cout << "Yo dude, you entered " << input << '\n';

   // main does not NEED to return a value
   // the only function with a return type not void that can do this
}

I write "sloppy" style code initially, I format and clean it up as I do tests.

I test my code constantly as I add new bits and pieces, or make changes to existing.

VS does a lot of the formatting for me on the fly. I still like cleaner, neater code I don't originally write.
Every time I've had to use a random number generator I've found it to suck really bad... I guess I also have to get myself into <chrono> since my program uses <time.h> which I find sucks arse too.


C++ random number generation can seem a bit overwhelming at first, there are so many choices for what to use.

A C++ working group paper I found a while back helped me get over the intimidation factor:

http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3551.pdf

I went so far as to create my own header-only version of the tool-kit mentioned.

When I want to generate random numbers now in a C++ program I simply include my custom header.

Is it C++ language standard quality? Hardly.

I haven't found any major problems, yet. It makes simple random number generation as easy as using the C library. Yet not as sucky. :)

[Edited to add:]
One really nice feature of <random>......you can now generate real numbers. floats and doubles.
Last edited on
Oh I didn't know uniform initialisation did catch type mismatch, I use it sometimes for arrays for instance but I guess it's a good thing to use it more often.

Thanks for taking the time to explain all this, you're also right, I think it makes more sense to declare a variable as late as possible in the code, so you can directly see where you're actually using it.

The only thing I would do different is put the new lines at the beginning of my outputs instead of at the end like you do, but that's a matter of habit I guess (unless there's a practical reason no to do that?) :)

Is there a difference between initialising a variable without anything and initialising it with empty braces? (like you did line 36).

Why are you taught in books that your main function should always return 0 if successful?

Thanks so much for the pdf you linked, I was actually looking for reference for the random header, and it is true that it's quite clear and very understandable.

I went so far as to create my own header-only version of the tool-kit mentioned.
You mean you created a class to generate random numbers and you include it every time you need to do just that?

One really nice feature of <random>......you can now generate real numbers. floats and doubles.
I haven't had the need for that just yet but it's a big plus I guess, might you need something else than integers..
Extra post, badly formatted. See the real comment below.
Last edited on
Is there a difference between initialising a variable without anything and initialising it with empty braces?
int i; // <-- contains a garbage value

int i { }; // <--- contains the default value of zero

C++ template class objects, such std::vector or std::string, are default constructed with a default value. Plain Old Data objects (PODs) and C style arrays aren't.

Think, and use, RAII:

https://en.cppreference.com/w/cpp/language/raii

The only thing I would do different is....

You are not alone in that. Several C++ books in my library use the same style.

I found FOR ME it can produce output messiness that I don't like. My approach is more intuitive for me.

Neither approach is bad, or one is better than the other. They are just......different, yet achieve the same output.
for c++ random, I highly recommend you make a little reusable class or even a free form function or two that do the most common things (eg, produce uniform integers). In practice you don't need anywhere near the full capability of the tools for most code, and when you do, you can fall back to a custom setup for that program. You could easily wrap it up to be pretty much identical to rand() in 3 functions (or less), with the benefit that you can get rid of all the modulo gibberish that rand users need with a parameter or two, making it all just myrand() calls instead of rand()%something+offset everywhere. An object would let you support multiple ranges if you need a bit more.
Last edited on
for c++ random, I highly recommend you make a little reusable class or even a free form function or two that do the most common things (eg, produce uniform integers).

That's what I have in my custom header only toolkit. :)

I took a slightly different approach than you suggest, still the same idea.

KISS for most random number uses.
Oooh right, my bad I had forgotten about that. I see what you did there, I presume it's better to make sure that a variable is initialised to something rather than a default value which could be anything, right?

I see what both of you mean when you say I should better create my own function / class for random number generation. Does that mean I have to physically copy the header I would create into each of my projects' folder or is there a place I can put it so that I can include it from any program without having to either copy and paste it or write the entire path for the header?
Oooh right, my bad I had forgotten about that. I see what you did there, I presume it's better to make sure that a variable is initialised to something rather than a default value which could be anything, right?

yes, its considered best practice to initialize. I honestly find it kind of irritating to see this
int x = 0;
cin >> x;

but no one asked me when making the best practices.

---
you have to manage your own code libraries yourself.
that means MAKE a folder on YOUR computer that has your reusable tools inside it. Then you have some choices ... you can include them with a full path or you can add the path to your compiler's search so it will see them without the full path. I prefer to use the full path, but both have issues. Full path breaks if you move to another machine with a different path, while putting it in the compiler breaks if you swap to a new machine or different compiler that lacks the search path. Make files can set this path, but then you have to deal with make files, which is a headache for small / personal projects. Any of those 3 ideas will work. And bad practice but effective for personal/small work, you can also dump your reusable stuff in a folder the compiler already searches. You can also copy it to each project but that is frustrating, what if you find and fix a bug, then you have 50 copies to update.... this is missing the boat on the reuse concept, really, and the worst option of them all, or even more alarming, you morph into 2 distinct versions that are incompatible between projects.

I recommend making a root (windows) or near root (unix) folder with the traditional names (src and inc) and put your sources in src and your includes in inc, and map those 2 to your IDE so it can use them.
Last edited on
here is a quick 10 second hack at replacing rand. It could be better (the whole dist function thing is all kinds of clunky) but I only had a couple of min.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

 class rand2
 {
   default_random_engine generator;          
   uniform_int_distribution<unsigned int>& dist(unsigned int strt=0, unsigned int fnsh=0)
   {
	 static uniform_int_distribution<unsigned int> distribution(strt,fnsh); 
	 return distribution;
   }   
   public:
   rand2(unsigned int strt=0, unsigned int fnsh=-1){dist(strt,fnsh);}     
   void seed(unsigned int s) {generator.seed(s); dist()(generator); }
   unsigned int operator()(){return dist()(generator);}     
 };
 
int main()
{
  rand2 r(0,10);
  r.seed(time(0));
  for(int i = 0; i < 25; i++)
    cout << r() << endl;		
}

edit.. circled back to it for a min, put 0 and -1 in to allow default ctor like behavior. Also fixed dist to be a reference.
... I don't see a way to reset a distro once its been made. I suppose I could make a new one to allow that feature, but meh. The point was to KISS. Im open to suggestions for dealing with the distro without making it significantly more complicated. All it would be for is to allow you to change the bounds to reuse a variable.

-- you could get rid of seed and have it auto use time(0) or whatever, but I like to have it. I like to be able to get the same values over and over when testing stuff.
Last edited on
I took a different tack than jonnin, using the proposed toolkit in that working paper (N3551) as a starting point.

The C library has one advantage for beginners when creating random numbers, easy to understand functionality:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <cstdlib>
#include <ctime>

int main()
{
   srand((unsigned) time(0));

   int num = rand() % 100 + 1;

   std::cout << num << '\n';
}

One way to write equivalent code in C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <chrono>
#include <random>

int main()
{
   // construct a trivial random generator engine from a time-based seed:
   unsigned seed = static_cast<unsigned> (std::chrono::system_clock::now().time_since_epoch().count());

   std::default_random_engine urng(seed);

   // create a distribution from 1 to 100:
   std::uniform_int_distribution<int> dist(1, 100);

   int num = dist(urng);

   std::cout << num << '\n';
}

Not so trivial looking.

Using a toolkit to hide all those messy implementation details (wrapped in a custom namespace):
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include "random_toolkit.hpp"

int main()
{
   rtk::srand();

   int num = rtk::rand(1, 100);

   std::cout << num << '\n';
}

One of the biggest mistake newbies make when generating random numbers, repeatedly seeding the generator:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <cstdlib>
#include <ctime>

int func();

int main()
{
   for (int i { }; i < 25; i++)
   {
      int num { func() };

      std::cout << num << ' ';
   }
   std::cout << '\n';
}

int func()
{
   srand((unsigned) time(0));

   return rand() % 100 + 1;
}

My custom header checks if the engine was previously seeded, so accidentally trying to seed multiple times won't happen.

Unless you tell my seeding function to force the seed. rtk::srand(true);

The toolkit also allows for seeding with a set value: rtk::srand(12);

If you want to get the same series of "random numbers" omit rkt::srand. The C library exhibits the same behavior.

C++ random number generation has one advantage over the C library, being able to generate real numbers natively:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include "random_toolkit.hpp"

int main()
{
   rtk::srand();

   for (int i { }; i < 25; i++)
   {
      std::cout << rtk::rand(1.0, 50.5) << '\t';
   }
   std::cout << '\n';
}

http://www.cplusplus.com/reference/random/uniform_real_distribution/

Now when I want some trivially obtained random numbers, I include my custom header. Easy to use, easy to remember functions.

Why did I do this?

1. Reusability.

2. As a learning experience to reinforce how to use <chrono> and <random>.

I took the working paper's proposed toolkit and added common functions/implementation I use and thought useful.

I personally copy the header to each project's folder when I use it.

It can be deposited in a "central location" but then you have to worry about path issues. Something I try to avoid with copying the header.
Last edited on
I actually did the one I posted yesterday, and the focus was on doing what rand() can do with minimal bloat (at the cost of some funky syntax). I have my own more advanced setup for the features that I use most including, as noted, random doubles. On things like this, I start small and add to it when I find that i wanted it to do more.
Last edited on
you have to manage your own code libraries yourself.
that means MAKE a folder on YOUR computer that has your reusable tools inside it. Then you have some choices ... you can include them with a full path or you can add the path to your compiler's search so it will see them without the full path. I prefer to use the full path, but both have issues. Full path breaks if you move to another machine with a different path, while putting it in the compiler breaks if you swap to a new machine or different compiler that lacks the search path. Make files can set this path, but then you have to deal with make files, which is a headache for small / personal projects. Any of those 3 ideas will work. And bad practice but effective for personal/small work, you can also dump your reusable stuff in a folder the compiler already searches. You can also copy it to each project but that is frustrating, what if you find and fix a bug, then you have 50 copies to update.... this is missing the boat on the reuse concept, really, and the worst option of them all, or even more alarming, you morph into 2 distinct versions that are incompatible between projects.
So is it like using an external library, You have an include and a lib folder which you include for your project (in VS for instance)?

@jonnin
Thanks for sharing that class, it's an interesting way of making it work, definitely wouldn't have thought of doing it that way!

@Furry Guy
That's really cool to see how you went from the 'default' way of doing thing with C -- how you're taught as a beginner -- and optimising it every time with features that make it a little better each time.

I See now why you're so militant about namespaces and I should really get myself into using them, I still don't know how to wrap something in a custom namespace, and I see now, how it can make things way clearer and more structured to use!
I was giving you ways to do it from cpp files, not compiled.
Compiled to a lib file is an option as well. If you do that, it may be worth making one lib from all your little tools that you use over and over. This is a really handy way to do it.

Last edited on
Pages: 123