-2

I'm practicing C++ on HackerRank and came across this problem. I created the class pretty well but struggled to create n student objects I can work with correctly. I searched for similar problems (this is an example) but could not find help, then I came across this solution. It worked well, but I honestly don't understand what exactly happened in line 37 of the solution. I went to cppinsights.io to see for myself and got the output below.

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

class Student
{
  
  public: 
  inline void input()
  {
    for(int i = 0; i < 5; ++i) {
      std::cin.operator>>(this->scores[i]);
    }
    
  }
  
  inline int total_score()
  {
    int sum = 0;
    for(int i = 0; i < 5; ++i) {
      sum = (sum + this->scores[i]);
    }
    
    return sum;
  }
  
  
  private: 
  int scores[5];
  public: 
  // inline constexpr Student() noexcept = default;
};



int main()
{
  int n;
  std::cin.operator>>(n);
  Student * s = new Student []();
  for(int i = 0; i < n; ++i) {
    s[i].input();
  }
  
  int kristen_score = s[0].total_score();
  int count = 0;
  for(int i = 1; i < n; ++i) {
    if(s[i].total_score() > kristen_score) {
      count++;
    } 
    
  }
  
  std::cout.operator<<(count).operator<<(std::endl);
  return 0;
}

Can someone help me explain Student *s = new Student[n];?

How would I do it if my class has a parameterized constructor taking student name or ID as argument. I'm asking this because this problem assumes Kristen's scores to be the first input all the time, but I'd like to compare any student with his peers. Thank you.

yusah
  • 9
  • 1
  • 2
    What does "help me explain" mean? Funny, but there was an article today on Slashdot that appears to [explain what's going on here](https://it.slashdot.org/story/22/06/25/1745219/). Trying to learn C++ by becoming a Google programmer will eventually end in tears. The only practical way to learn the most complicated and the hardest general purpose programming language in use today is by following a guided curriculum in a good C++ textbook, that explains each concept (like the one asked about here) step by step, and not by trying to learn it from Google. – Sam Varshavchik Jun 26 '22 at 01:03
  • The solution you found is less than ideal, to say the least. BY DEFAULT, `` is included and they don't bother. That's the most egregious offense, anyway. But if you don't understand that code, hackerrank is not for you right now. It's not a learning resource, as much as it tries to say it is. – sweenish Jun 26 '22 at 01:10
  • I think you need to focus on understanding C++ classes, more than just trying to solve this question. This is allocating memory on the heap"new Student []()", are you deleting that memory, why is there no size to this array? Why not use a std container so you can have infinite students, etc – Natio2 Jun 26 '22 at 01:12
  • The total score function should be a one-liner, because `` is included, but your solution source, again, doesn't bother. Posting cppinsights.io output as the code is also a bad idea. I'm seeing that hackerrank sets the `main()` function, and you're just supposed to write the class. – sweenish Jun 26 '22 at 01:13
  • I myself am a little confused: why is `new Student[]()` valid syntax? It seems wrong to omit the number of elements in the array unless providing an initializer list. I expect `new int[] { 1, 2, 3 }` to be fine, and to create an array of three ints. But what does it mean to omit the array bounds, and to just provide empty bananas after the square brackets `()`? Does it create an array of 0 elements? What can go inside the bananas? Putting a number in there like `new Student [](3)` gives an error like *parenthesized initializer in array new*. – Wyck Jun 26 '22 at 02:03
  • @Wyck Hey apologies, I think it was wrong to post the cppinsights.io output (I do make reference to it to understand things better), but I made reference to the original code in the question. it's actually just `new Student[3]` . – yusah Jun 26 '22 at 02:21
  • `new Student[3]` creates 3 `Student`s in a row (also known as an _array_) on the heap and gives you the address of the first one. If you store that address in a pointer variable like `Student *students = new Student[3];` then the three student objects can be accessed with `students[0]`, `students[1]` and `students[2]`. – Wyck Jun 26 '22 at 02:49
  • @Wyck Thanks, I read more about it and I think I now understand better. – yusah Jun 26 '22 at 02:57
  • 1
    Note: if you are using `new` to allocate an array, you should remember to `delete []` it. – Chris Jun 26 '22 at 07:49

2 Answers2

0

I figured I should write some code to give you an example of how to use a std container.

class Student
{
    std::vector<int> scores;
    std::string name;
    int id;

public:
    Student():name("No name"),id(0){}
    
    Student(std::string studentName, int identifier)
    : name(studentName), id(identifier) {}


    const char* getName() const {return name.c_str(); }
    int getId() const { return id; }

    int getTotalScore() const{
        int total = 0;
        for(auto& score : scores){
            total += score;
        }
        return total;
    }

    void addScore(int score)
    {
        scores.emplace_back(score);
    }

};

int main()
{
    std::vector<Student> students;
    //Lets not reallocate 5 times
    students.reserve(5);

    for(int i = 0; i < 5; i++)
    {
        std::string name = "Student";
        name += std::to_string(i);

        students.emplace_back(name, i);
        for (int j = 0; j < 3; j++) {
            students[i].addScore((i + 1) * 5);
        }
    }

    for(auto& student : students)
    {
        std::cout << "Name: " << student.getName() << " id: " << student.getId() << " Total score: " << student.getTotalScore() << std::endl;
    }
}

You can see the student class has two constructors one with and without arguments, so you can make either of these.

I don't recommend allocating on the heap (using the "new" keyword), until you are a bit more experienced in C++. Try learn the standard containers first std::string, std::vector, std::Array, etc.

In this example I use standard vector. emplace_back calls the constructor for student and places it in the vector, who will manage that memory for me.

Note I reserve 5 before I place students into it because every time the vector needs to get longer it will copy every element, so is best to avoid this. I.e. When I place the 6th element it would have to create 5 copies and 1 new object.

The other things can can be seen in this code that you should learn on your C++ journey are:

  • Initalizer lists: https://www.geeksforgeeks.org/when-do-we-use-initializer-list-in-c/
  • "const" keyword
  • Lastly you notice I don't put std::cin into the Student class. Student class should not know about the input method. This is called encapsulation. This is one of the most important things to learn as a software developer (Which might be ignoring the question, but that just means the architect was poor)

You can link this into the input function.

Bonus questions what if I type "afdasf" into the console, will your application crash? what if I type no characters, and just press enter?

Natio2
  • 235
  • 1
  • 9
  • thank you for the detailed example and suggestions. I think I now understand the concept better. I'm still a student, believe I still have time to grow. About the bonus question, I think the console won't let you type anything. You already assigned the scores in he nested for loop of the main function. – yusah Jun 26 '22 at 02:32
  • I'm noticing that this code is missing one of the required functions of the problem and contains extra data members are aren't needed. The initialization section is used by one constructor but not the other, however the default constructor could be defaulted if you utilized default member initialization. I'm also not a fan of recommending geeksforgeeks as a reference to a beginner as the information is usually incorrect; I will say that I didn't look at the specific page you linked to see if it happens to be correct. – sweenish Jun 26 '22 at 19:07
  • @sweenish Uh yeah, I wasn't answering providing a full solution just giving them a demonstration on better ways to use containers, and constructors with arguments, which hopefully they could use to solve there problem. Key to learning is having to do some yourself. But you have valid points, it was more laziness on my part just banging out some code and looking for a webpage that looked like it described things somewhat correctly. Fixed the first constructor. Really this should be split out into a header and cpp too, many things not to follow in my code here – Natio2 Jun 27 '22 at 01:05
  • @Justin that’s well and good, but OP cited a specific problem and your code is missing a required function to solve that problem. – sweenish Jun 27 '22 at 03:19
  • I also don't think it needs to be split out. It's a toy program totaling ~100 LOC. Going through the hassle of creating 3 separate files for *this* program is a waste of time. If that's something OP wants to learn, they should implement a project just big enough to justify it. The principle will feel more natural in action when it's justified. And it's not as if the project has to be a lot larger. – sweenish Jun 27 '22 at 03:34
0

Here's my solution that passes all test cases:

#include <array>
#include <numeric>
// Write your Student class here
class Student {
public:
    Student() = default;
    
    void input() {
        for (int i = 0; i < 5; ++i) {
            std::cin >> m_scores[i];
        }
    }
    
    int calculateTotalScore() const {
        return std::accumulate(m_scores.begin(), m_scores.end(), 0);
    }
    
private:
    std::array<int, 5> m_scores{0};
};

It's known ahead of time how many scores there are, so an array makes more sense. The total is calculated using a Standard Library function, std::accumulate().

Line 37 is part of the problem, not the solution, because you didn't write it and can't change it. But all it does is allocate an array on the heap. If that line is throwing you, I highly recommend using a good book to learn, and not one of these competitive coding sites. Hackerrank (and pretty much all sites of this kind) problems are rife with issues and poor practices and poor requirements. What it might teach you is not good to learn. These sites are meant to be used for fun after you know what you're doing.

Caring about anything beyond meeting the requirements is over-engineering. Apply YAGNI when solving a problem, especially from these sites.

sweenish
  • 4,793
  • 3
  • 12
  • 23
  • 1
    Hey, thanks for this. Honestly after few comments I realized that I was too quick to ask dumb (too basic) question, had I been more patient I'd have figured it out myself. I even thought of deleting it but then I thought maybe I'll learn one or two things from it. And Yes! I did, the Google programmer thing from Sam Varshavchik in the comments, the YAGNI you mentioned, coding style, and the need to pay more attention to details from good books. Note: I use these sites to practice what I learn because I think the flood of concepts I learn won't do me any good without practice. – yusah Jun 26 '22 at 23:41
  • "Caring about anything beyond meeting the requirements is over-engineering" - maybe for an interview question, but if you want to do it for a career, writing readable, maintainable, and scalable code is hugely important. Quick code that technically works will kill your efficiency in the long run – Natio2 Jun 27 '22 at 01:15
  • @Justin you are describing something completely different that I don’t see as being in conflict with what I stated. This is my career. – sweenish Jun 27 '22 at 03:17