I need some help learning C++

Well, yes, these things have been tested well, otherwise you need to consider all of the edge cases, like months that have missing days:

$ cal 9 1752
   September 1752   
Mo Tu We Th Fr Sa Su
    1  2 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30
  1. std::chrono is tested for edge cases
  2. it’s convenient - this whole exercise is 3 lines of code
  3. number of days in a month is decided by politics, and it’s encoded in tzdb or other similar timezone dependant OS packages; that std::chrono uses and there are lots of once off exceptions beyond Feb 29th.

As a junior professional programer, you should be aware of the standard libraries. Doing your own thing, contrary to people’s expectations (conform your style to existing style, use standard libraries, etc), will get you into trouble. Being repeatedly obstinate about doing your own thing and not working within the systems already in place and forcing your peers to second guess your code all the time will generally get you fired.

If std::chrono or any other part of standard library is broken / not fit for purpose for whatever reason, building your own, or augmenting the functionality with helpers after investigating alternatives, fixing std::chrono might be ok, but that takes time and effort and should be a deliberate decision and not something that I’d expect a junior programer to decide on their own at a whim.

Overall, I don’t think it’s stupid to give this to students as an exercise, as long as you teach them the above.

I have since submitted the assignment but someone did ask about using libraries and things like that to the teachers and their answer was that this isn’t about making it easy or whatever, that comes later they wanted us to know and understand how to write code from complete scratch so as to know and understand the underlying fundamentals.

They even tell us to try and write code in notepad or even pen and paper and learn how to do things from nothing.

Basically perfect using a hammer first, master the hammer and the nail gun can come later.

:+1:Hammer and chisel first - CNC later, makes sense.

I take it that means the exercise went well for you?


On a related note, you should bookmark:

https://en.cppreference.com/w/

, it’s very handy… but there’s a lot of c++ specific terminology that often gets used to explain stuff and it takes quite some getting used to.

I did manage to get the code to work for everything except one thing but ill take it that is obviously something I need to keep studying.

While none of the code i found online to reference really worked I would never have been able to do the assignment had I not studied other peoples code and visually seen how they did things.

Studying other peoples code and seeing how others did things gave me the understanding and confidence to write my own code.

It is like furniture. I’m no woodworker but if I watch a video of someone using the tools and making something I would feel more confident attempting it myself if I wanted.

3 Likes

Congrats on the assignment completion. For future reference, here is my take on the whole thing, I needed a break from my current problem in any case. :slight_smile:

Most people will probably hate me for using more esoteric features like call-by-reference (&) out parameters, which is bad practice - use objects, structs and constants instead! Same with the condensed tertiary operators (condition) ? truevalue : falsevalue - make sure to use them sparingly. That said, here we go:

#include <iostream>
#include <iomanip>

void calc_date(int &year, int &month, int &day, int offset) {
    int month_days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    // Check for leap year
    if ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))) {
        month_days[2] = 29;
    }

    // Add offset to new days
    day += offset;

    // If day is less than 1, month need to be decreased
    // If day is more than monthly limit, month need to be increased
    if (day < 1) {
        month -= (month ==  1) ? -11 : 1;        // If 1, "wrap" to 12
        year  -= (month == 12) ?   1 : 0;        // Only decrease year with 1 if we are in december
        day   += month_days[month];              // Day is 0 or negative, hence addition
    } else if (day > month_days[month]) {
        day   -= month_days[month];              // Remove days of current month, not next month
        month += (month == 12) ? -11 : 1;        // If 12, "wrap" to 1
        year  += (month ==  1) ?   1 : 0;        // Only increase year by 1 if we are in January
    }
}

int main(void) {
    int year, month, day, offset;

    // Read values
    std::cout << "Enter date (yyyy mm dd): ";
    std::cin >> year >> month >> day;
    std::cout << "Enter days to offset (-7, 7): ";
    std::cin >> offset;

    std::cout.fill('0');
    std::cout << "Date " << year << "-" << std::setw(2) << month << "-" << std::setw(2) << day << " with " << offset << " offset is ";

    calc_date(year, month, day, offset);

    std::cout << year << "-" << std::setw(2) << month << "-" << std::setw(2) << day << std::endl;

    return 0;
}

This is exactly what I submitted back in my college days.:sweat_smile:
I guess I should stick to marketing and leave the programming to the pro’s.

Here is one that has me completely stumped. I have written code where someone can input a number of judges between 4 and 8

it than via a loop will allow you to input each judges score

than it will calculate the average.

Here is the part that has me stumped. I need to exclude the highest and lowest score and only show the average of the rest.

The scores are whatever someone decides to type in they can be anything from 0.0 to 10.0

im not using arrays anything it is just basic code with floats and int’s

its one thing if its a set number of judges but I need this to work based on unkown quantities where it finds the highest and lowest and excludes them from the average.

Any tips guys?

Why not using arrays (vectors)? This is a perfect application.

Two obvious solutions: Three! Three obvious solutions, depending on whether the scores are unique (I imagine not):

  1. read the scores in and compare with running minimum and maximum values. If the scores are not unique then you’d also keep a count of the number of times you’ve seen the minimum and maximum score. Each time you get a new low or high the count goes to 1 for that value. Keep a running accumulator of the scores. When you’re done inputting, subtract N * min score and M * max score (where N and M are the number of times you saw the minimum and maximum score, respectively). Then divide by the number of values inputted minus N + M.

  2. Same as 1) but the scores are unique so you only need to keep track of the minimum and maximum scores; N and M are implicitly 1. The above algorithm would still work so it’s more like 2 and a bit solutions.

  3. read the values into an array or a vector. When done inputting, sort the array. Start at index i = 0: while the number at index i is the same as 0, increment the index. Do the same for the top of the array starting at index N - 1 (where N is the size of the vector, as returned by the size() method - it returns a size_t, not int) and decrement the index. Sum the array from index i to index j and divide by j - i + 1 making sure not to divide by zero. You should make sure not to divide by zero in any solution you submit.

You could get a bonus point by using std::accumulate() on an array or vector to add up the total, but calls to methods in might not be what the instructor is looking for.

If you’re faced with an arbitrary number of judges then std::vector would be a good data structure if you’re intending to do the sort (because it can grow dynamically whereas the size of a stack-based array has to be known when you allocate it; allocating an array on the heap would also suffice - it’s basically what std::vector does under the covers).

You could get another extra point by using std:copy and 3 iterators to read into the vector, but that’s probably more than required also.

There’s a handy minmax function, along with min and max that you should take a look at, rather than rolling your own.

If you don’t have cppreference.com on speed dial, you ought to have. (Speed dial? What’s that? Amirite?)

Thanks for the link. I don’t know why this is so difficult for me. I just read what you said and all I am thinking is how on earth do I write that?

This coding stuff is probably the only thing that makes me feel like an idiot because so much is left to interpretation and “figuring it out” where I would learn 100 times faster if I could just visually see how to do these things.

Well, yes, writing code is a creative endeavor and that’s where the interpretation comes in.

The key is to break down the problem into manageable chunks. In this case you’ve got essentially four steps:

  1. read in the scores; is there a fixed number - are you told up front how many scores there will be - or do you just need to keep going until you reach the end of the input? How is the end of input determined?
  2. you need to keep track of the minima and maxima. Either do that as you go, or batch process it with the sort method.
  3. calculate the average after taking into account the minima and maxima you found in the previous step.
  4. output the result.

Make sure you have a clear understanding of what is required in each step. Step 1 is important because that will determine what data structure you need: can you get away with just a few ints and/or floats, or do you need something a little more sophisticated like a vector? Step 4 is straightforward but vital because that provides the results to whoever or whatever runs your program and presumably makes a decision dependent upon the result you provide.

You have to keep at the problem until you get the correct result. The more you do the work, the more tips and tricks and methods you understand, the easier it gets, but you can’t really short-circuit it. The great thing about computers is that you can make a hundred attempts and it costs virtually nothing other than time.

From your original post the only bit you have to complete is the part where you exclude the minimum and maximum values. If you’re stumped you could write out examples on a piece of paper, e.g. start with something simple like a monotonic sequence: 1, 2, 3, 4, 5 e.g. and figure out what are the minimum and maximum values: 1 and 5. How did you determine that? Once you’ve determined what the minimum and maximum are, how do you exclude them? Then calculating the average of the remainder is straightforward: (2 + 3 + 4) / 3 = 3 in this case. If your program can accept repeated values such as 1, 1, 2, 3, 4, 5, 5 then how would you deal with that? What about 5, 5, 4, 3, 2, 1, 1 or 4, 2, 5, 1, 3, 5, 1, etc.

You really only have two problems: how do you store the data your program receives, and how do you account for minimum and maximum values? The latter is achieved by comparing values, and the former is a design decision you have to make based on the requirements of your program. If you can read values from stdin and write them into an array or vector then you basically have the sequence like in the examples above, and you can then set about figuring out which are the values you need to exclude. The brute force method - usually the first approximation in solving any software problem - would be to compare every value you read into an array with every other value. You can do that in one pass by
doing something like the following, assuming you read data into a vector v:

    float min = POSITIVE_INFINITY; // define some real value outside the expected range
    float max = NEGATIVE_INFINITY; // same in the opposite direction on the number line
    float sum = 0.0f;
    for (size_t i = 0; i < v.size(); ++i) {
        if (v[i] < min)
            min = v[i];
        if (v[i] > max)
            max = v[i];
        sum += v[i];
    }

Then what do you do with min, max and sum? How do you modify the code to handle repeated minimum and maximum values? What if the minimum and maximum values are the same?

Note that comparing floats or doubles can be problematic because decimal values can’t always be exactly represented by single or double precision format binary numbers. This isn’t usually an issue - you might have to compare within an error range that’s usually something like 10^-6 - but it’s something to be aware of depending on your expected input values. min() and max() type comparisons are usually best done on integer numeric values (but any quantity will work - that’s a detail you probably don’t have to be bothered with in such an exercise).

  1. Accept inputs into a data structure (preferably array)
  2. Sort said data structure
  3. Exclude first and last element using for (i=1; i<n-1; i++) (as opposed to the regular for (i=0; i<n; i++) that you are used to)
  4. Present results

This is actually such a source to problems, I have started to advice people to avoid floating points in favor of either fixed decimal numbers, or rational numbers. 99% of the time that is all you need, and you can skip shenanigans like:

double a = 1/3;
double b = 0;

while (b != 1) {
    printf("1");
    b += a;
}

The code above should print 1 three times and then exit. Instead it prints 1 indefinitely. Why? Because 1/3 isn’t quite 1/3, it is 0.333333333333330. Add 0.3333333333330 three times, and what do you get? Correctamundo, 0.999999999999990, which is not the same as 1. Incidentally, the next number will be 1.333333333333320. :slight_smile:

You need to think in terms of error margins which complicates code by an order of maagnitude. Avoid floats until you have to use them, and even then be very selective of when you are using them, is my advice. As always, you do you.

GitHub, learn by example of other software… or find examples on stack overflow.

(n.b. copyright / corporate lawyers might disagree on technicalities and in principle around what I’m suggesting here, … but they can’t teach you to code or solve your problems usually.

If it’s for learning and personal development, you’re good in my book)

1 Like

Lawyers are there to create problems, not solve them :wink:

1 Like