0

I am doing a practice problem in HackerRank, and I am having trouble implementing the final task for this one issue I am having with classes.

It is a pretty simple program, it just uses a Student class with setter and getter functions to take in a student's information (age, firstname, lastname, and academic standard), and uses an stringstream to output that data.

However, at the very end is where I am having trouble. I am supposed to create a to_string() function which returns a string consisting of the above elements, separated by a comma (,). I think I am just mis-understanding how to use ostringstream.

#include <iostream>
#include <sstream>
#include <string>

class Student{
    private:
        int age;
        std::string first_name;
        std::string last_name;
        int standard;
    public:
        void set_age(int age){
            age = age;
        }
        int get_age(){
            return age;
        }
        void set_standard(int standard){
            standard = standard;
        }
        int get_standard(){
            return standard;
        }
        void set_first_name(std::string first_name){
            first_name = first_name;
        }
        std::string get_first_name(){
            return first_name;
        }
        void set_last_name(std::string last_name){
            last_name = last_name;
        }
        std::string get_last_name(){
            return last_name;
        }
        std::string to_string(){
            std::stringstream os;
            os << age << "," << first_name << "," << last_name << "," << standard << std::endl;
            return os.str();
        }
};

int main() {
    int age, standard;
    std::string first_name, last_name;
    
    std::cin >> age >> first_name >> last_name >> standard;
    
    Student st;
    st.set_age(age);
    st.set_standard(standard);
    st.set_first_name(first_name);
    st.set_last_name(last_name);
    
    std::cout << st.get_age() << "\n";
    std::cout << st.get_last_name() << ", " << st.get_first_name() << "\n";
    std::cout << st.get_standard() << "\n";
    std::cout << "\n";
    std::cout << st.to_string();
    
    return 0;
}

Input Example:

15
john
carmack
10

Expected output:

15
carmack, john
10

15,john,carmack,10

My output:

2
, 
0
2,,,0
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Parke
  • 13
  • 1
  • 3
    Be careful reusing names. `age = age;` is assigning which `age` variable to which `age` variable? Hint: It's the same one both times. – user4581301 Jan 12 '23 at 21:40
  • you should always pay attention to warnings. The only exception is when there is a bug in your code, then you need to pay triple attention to warnings. https://godbolt.org/z/8MdsaMz73 – 463035818_is_not_an_ai Jan 12 '23 at 21:43
  • Design note: A `private` variable with a `public` setter that only sets the variable and performs no additional behaviour effectively makes the variable `public`. Any fool can set any value at any time and the object can do nothing to protect itself. It makes a great place to hang a breakpoint though and should you add additional value to the setter in the future you won't have to change as much code, but encapsulation has been weakened. Rather than reading into intermediary variables and then setting the class, consider overloading [`operator>>`](https://stackoverflow.com/q/4421706/4581301) – user4581301 Jan 12 '23 at 21:48
  • John Carmack. I know that name from somewhere. Wasn't that the name of the doctor in the movie DOOM? – user4581301 Jan 12 '23 at 21:50
  • 1
    @user4581301 [quite possible](https://en.wikipedia.org/wiki/John_Carmack). I had forgotten about that movie, and it was better like that :D – 463035818_is_not_an_ai Jan 12 '23 at 21:56
  • 1
    Just like it's a shame they never made any sequels to The Matrix, eh @463035818_is_not_a_number ? – user4581301 Jan 12 '23 at 22:01
  • 1
    A class object should be built with a constructor, not with setters. – n. m. could be an AI Jan 12 '23 at 22:14

1 Answers1

0

All of your class setters suffer from the same problem - each input parameter has the same name as its corresponding class member. As such, each parameter is shadowing the class member, so you end up assigning the input value back to the parameter, rather than to the class member.

Thus, none of your class members are actually being assigned any input values at all, which is why you are getting garbage in your output.

Once you fix the shadowing issue, you will get your expected output:

void set_age(int /*age*/value){
    age = /*age*/value;
}
...
void set_standard(int /*standard*/value){
    standard = /*standard*/value;
}
...
void set_first_name(std::string /*first_name*/value){
    first_name = /*first_name*/value;
}
...
void set_last_name(std::string /*last_name*/value){
    last_name = /*last_name*/value;
}
...

On a side note: to_string() should use std::ostringstream instead of std::stringstream. And to_string(), and all of the getters, should be marked as const, since they aren't modifying the Student object.

Online Demo

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thank you friend! Much appreciated, I knew it would be something simple which is why I always wait until I am about to go off the deep end to post to stack. I have only been doing C++ about 6 months and am starting classes/OOP heavily now/within the last month, so I really can't thank you enough. You are the goat :) – Parke Jan 12 '23 at 22:40