trouble making c++ student class [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
For my assignment I have to make a program to read student data from standard input, sort it by last name / first name, and print out the result to standard output. Students consists of a last name, first name, and a grade point average. It says to there are no more than 50 students.
It also says you should not rely on an external library function to do the sort.
Here is the example:
Ware Henry 87.2
Dantes Edmond 91.4
Earhart Amelia 92.6
Here is how it should be sorted:
Dantes Edmond 91.4
Earhart Amelia 92.6
Ware Henry 87.2
Here is the code I have so far that is not working properly:
#include <iostream>
#include <string>
using namespace std;
class student
{
public:
student();
void input();
void output();
void sort();
private:
string Fname;
string Lname;
float gpa;
}
student::student()
{
Fname = "";
Lname = "";
gpa = 0;
}
void student::input()
{
cout << "Enter first name, last name, and gpa"<<endl;
cin >> Fname >> Lname >> gpa;
}
void student::sort()
{
char temp;
int count = 0;
int i = 1;
while (i < word.size()) {
if (word[i - 1] > word[i]) {
temp = word[i];
word[i] = word[i + 1];
word[i + 1] = temp;
i++;
if (i >= word.size())
{
alpha(word);
}
}
else
{
count++;
}
}
return word;
}
void main()
{
student.input();
}
Any advice on where I went wrong and any possible solutions?

your student class has member variables to hold only one student, you need 50 instances of class student.
then you should hold these instances in an array/vector (whatever for container you are allowed to use) I assume you need to use a raw array so something like this will do.
student* students = new student[50];
what you then need is a compare function in your class to be able to sort the array, the compare function knows the internals of your class and you can decide how you want to sort the list e.g. after surname.
the sort function could be inside your class declared as a static function or maybe more logically an external function since student is not a container of student instances.
don't forget to delete the array when done
delete [] students;
in real world problems you would use std containers and e.g. algorithm sort for this kind of work.

Your compiler must have told you that word and alpha used in sort method are undeclared identifiers and count is assigned but never used.
Solution: Never ever steal code from wild wild web without understanding what it does. You may take others' code as inspiration, but blind copy-paste is a big no-no.
To give you a next step: you haven't even stored your students, you just input one, how would you sort just one entry? Think (and code) what you should use to store them and start working from there on how to sort them.
Good luck.

There are several reasons why your code is not working, first reason is that your class definition needs semicolon ';' at the end to close it.
class student
{
public:
student();
void input();
void output();
void sort();
private:
string Fname;
string Lname;
float gpa;
}; //semicolon here
In your sort() method the variable word is used but never declared, coding is not magic, the variable must declared and initialized before it is used like in your code.
while (i < word.size()) { //word must be declared somewhere
Also, in the sort method, you call a function alpha(word), this function does not exist in your program.
The sort method is of type void, which means it will not return anything, yet you are trying to return a string.
Another problem with the sort method is that it is never called from anywhere and will never be run.
There is also a big problem here with the way you are trying to use your class. To use the methods of the class you first have to instantiate an object of that class, you can then access the methods of the class through the object like this:
int main()
{
student theStudent;
theStudent;
theStudent.input();
return 0;
}
Another fundamental problem is that you are only going to get data for one object like this, you need to store several objects in something like an array and then sort the objects in the array:
int main()
{
student students[5];
for (int i = 0; i < 5; i++)
{
student newStudent;
students[i] = newStudent;
newStudent.input();
}
sort(students);
delete[] students;
return 0;
}
Which brings us to the sort method. It would be wise to not do the sorting as a method of the student class, but as a function called from main instead (like in the example above), that way it is easy to sort the array of student objects from main.
These are a few advice to start with, i am not going to do your complete homework for you though, if you use google and some of your precious energy, i believe that you will succeed.

Related

Static class variable initializing to 100 by itself

This is my first question on here, so excuse me if I've formatted everything in a wrong way.
So, to get to the problem - this is s university assignment of mine. The goal is to create a class called Student, which has a few fields, and store the instances in an array of Student objects. One of the tasks is to have a static variable inside the class that keeps track of how many Student instances have been created. To clarify, I have a getData() method that asks the user for the values, and then sets the current object's values to those entered (basically just like a constructor, which makes the constructors obsolete, but they want us to do it that way for some reason). In the getData() function, the static count variable gets raised by 1, as well as in the constructors, and gets decremented in the destructor.
The issue is that for some reason, Student::amount variable sets itself to 100. Every time that i try to access it from the main() function, its 100 plus the amount of students created, so if we have created 2 students, Student::amount will be equal to 102. I've nowhere explicitly set it to that number, which also matches the size of the array, by the way.
I'm still rather new to C++, I've read and watched some material on how OOP works here, but I've barely even scratched the surface.
Sorry again if my question is badly formulated or/and badly formatted, and I hope you can help me with this!
#include <iostream>
#include <string>
using namespace std;
class Date {
...
};
class Student {
// Fields
private:
string name = "";
string PID = "";
int marks[5]{ 0 };
short course = 0;
public:
// Count of all students
static int amount;
// Getters
...
// Setters
...
// Constructors
Student(); // Default one, Student::amount gets raised by 1 there
Student(string name, string PID, int marks[5], short course);
// Destructor
~Student();
// Methods
void getData();
void display(); // Display the information of a student
};
// Array of students
Student students[100];
// Student::Count
int Student::amount; // Initializes with 0 if not explicitly initialized
void Student::getData() {
cin.ignore();
cout << "\nName: "; getline(cin, name);
cout << "PID: "; getline(cin, PID);
cout << "Marks:\n";
for (int i = 0; i < 5; i++)
{
cin >> marks[i];
}
cout << "Course: "; cin >> course;
Student::amount++;
}
Student::Student(string name, string PID, int marks[5], short course) {
this->setName(name);
this->setPID(PID);
this->setMarks(marks);
this->setCourse(course);
Student::amount++;
}
The global declaration Student students[100]; calls the default Student constructor 100 times, before main is reached. According to your comment (you don't supply the constructor implementation), that constructor increases amount by 1.
A solution here is to remove Student::amount and instead use
std::vector<Student> students;
students.size() will give you the number of students in that container. Use push_back to put students into the vector.
A very crude alternative that at least is broadly compliant with the question constraints is to remove the amount increment from the default constructor, and all other places apart from the four argument constructor.

Parsing Data from Unknown Class

I'm doing some testing on an idea that I have. However, I am at loss.
I have declared a class as such :
class Course {
private:
char *name;
int ID;
public:
void printCourses();
}
Where printCourses() is defined as
void Course::printCourses() {
cout << name;
}
This makes sense. Each class has a data member called name. So, say that I have declared an array of 10 class objects, that means 10 potential names will correspond with to a course...OK.
My problem lies here.
What if object 6 and 9 have those values filled at some point during runtime, and I want to KNOW that. For instance, say course 6's name is "Psychology" and course 9's name is "History". I want to be able to print these values in a sort of "Course List" function... Some class objects are not yet filled here but I want to be able to parse through and find the objects that do have the name variable filled.
I have tried a for loop for testing this but no logic is helping... I tried this.
for (int i=0; i<10; i++) {
course[i]->printCourses();
}
In my head, this should still iterate through all 10 objects (I have already allocated memory for all 10 of them), but it doesnt. However, if I just call the one I know is filled like this:
course[6]->printCourses();
It returns properly "Psychology".
TLDR: Help, How can I iterate through class objects to find certain variables that are filled ?
disclaimer
I am using -> operators for classes because I declared the array as an array of pointers to the class objects.
Course *course[10];
Like so..
Before I answer, a side note. You say: "I have already allocated memory for all 10 of them." This is bad. You've wasted space on names that will never be used. Instead let's use a string to allocate as necessary, and to allocate any number of characters as desired.
Now, you need to use optional to solve this. Specifically your name shouldn't be definied as char* name but a optional<string> name. To use optional you'll just need to change your printCourses method:
void Course::printCourses() const { cout << name.value_or(""); }
Live Example
You could make a additional method that returns your name. If the name is a nullptr, you ignore it. Your method could look like:
char* Course::GetName()
{
return name;
}
And then you iterate with:
for (int i = 0; i < 10; i++) {
if (course[i]->GetName())
course[i]->printCourses();
}
An alternative way is to combine the functions:
void Course::printCourses() {
if (name)
std::cout << name;
}
Iterate with the following and it will only print the name if it exist:
for (int i = 0; i < 10; i++) {
course[i]->printCourses();
}
It would be good to initialize the name in the constructor:
Course::Course() : name(nullptr), ID (0) {}
Little side note: Use std::string instead of char*. I provided you a solution for your case but you can do pretty much the same with a solid c++ string.

Passing pointer of vector of objects as arguments but a lot more different

This question does look like a copy and paste of an old one (which it sort of is) but I assure you the situation is a lot more different and very hard to explain so please hear me out before you murder my miniscule reputation.
I am having issues with taking vectors holding objects into function parameters, then scanning them and putting a specific object into another function's parameters which would then use all the values of that specific object.
For instance if there were a player class and enemy class:
class player{
public:
int id;
string name;
};
class enemy{
public:
int eid;
string name;
};
And there were some objects of those classes stored in their own vectors:
player example;
example.id = 1;
example.name = "example";
enemy badEnemy;
badEnemy.eid = 1;
badEnemy.name = "badEnemy";
vector<player> allPlayers;
vector<enemy> allEnemys; //I know the spellings wrong but am to reluctant to change it
allPlayers.push_back(example);
allEnemys.push_back(badEnemy);
And then there was a function that printed out the objects names:
int fightEnemy(player player, enemy enemy) {
cout << player.name << endl;
cout << enemy.name << endl;
return 0;
}
After that there would be a function that scans for specific objects in the vector and inserts them into the fightEnemy function
int enemyComboCheck(int id1, int id2, vector<Player>* allPlayers, vector<enemy>* allEnemys){
int iteratorForPlayer = 0;
id1 -= 1;
id2 -= 1;
for(int i = 0; i < 18; ++i){
if(id1 == allPayers[iteratorForPlayer].id && id2 == allEnemys[i].id) fightEnemy(allPlayers[iteratorForPlayer], allEnemys[i]);
//how do I pass the scanned object into the other function
}
return 0;
}
I guess my main question is how do I pass the scanned object into the other function through a vector? Would I have to use a vector in the other function?
Sorry for all the bad formatting, anyways thanks!
You pass it exactly the same way you're referencing them in your if statement.
fightEnemy(allPlayers[iteratorForPlayer], allEnemies[i]);
And fix the spelling. That's what global find and replace is for.
I would suggest changing the signature of fightEnemy to take references so you don't have to copy objects, and you can change things like hitpoints if you need to. This will not change the way you call it:
int fightEnemy(player &player, enemy &enemy)

How to solve this print output in C++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I had the below C++ question in the recent interview but could not do. Please help.
Given a company structure where every employee reports to a superior, all the way up to the CEO, how would you print out all the employees that a particular individual oversees?
Write a method that implements this, given the below:
// Employee object contains a string denoting the.
// employee name, and an array containing
// employees who report to this employee
Employee {
String name;
Employee[] employees;
}
I have seen and understand the recursive function. But I have not encounter such a recursive object/structure like this one.
My new question is how can an object is created and initialized from this class/structure since it is recursive?
Thank you very much again.
With the information given it is very hard to answer (and question should probably be set on hold). Anyway...
I think a recursive approach is the answer. You need a function that can take a name, search the full employee list for that name and then call the function again for every employee in the local array. Something like:
void doit(Employee& e)
{
// Print e.name
// For each employee tmp in e.employees (i.e. local array)
doit(tmp);
}
Note - this requires that there are no loops in manager-employee arrays. If there is this will be an endless loop. So this is a dangerous approach.
EDIT:
This is added due to the comment from OP.
As indicated above the question is vague and doesn't really give sufficient information to provide a good answer. The struct given in the question is not valid C++ and there is no description of how the company wide list of employees are maintained.
However to keep it simple, the printing could look like this:
struct Employee
{
void PrintAllReportingEmployee(int level)
{
cout << string(4*level, ' ') << name << endl;
level++;
for (auto& e : employeesDirectlyReportingToThisEmployee)
{
e.PrintAllReportingEmployee(level);
}
}
string name;
vector<Employee> employeesDirectlyReportingToThisEmployee;
};
// Code in some print function:
// Step 1 - find the relevant employee
Employee tmp = SomeFunctionReturningAnEmployeeBasedOnName("NameOfPerson");
// Step 2 - print all employees reporting directly and indirectly
tmp.PrintAllReportingEmployee(0);
This assumes a single top-level Employee (e.g. director) with a vector of employees directly reporting to the director. Each of these would then have a vector of employees reporting to them and so. So it is kind of an tree structure.
Note, if I should design a employee db, I would not go with such a solution.
Who ever asked the question was looking for an answer with something to do with class inheritance. So a class Persion is extended by Employee where Person is also extended by Manager etc etc where they all share some similar properties but not everything.
This means that your code can be expanded upon by other programmers and one change can fix many different classes!
Although this code does not demonstrate class inheritance, it will work.
/*
THE OUTPUT:
Jacobs-MacBook-Pro:~ jacob$ ./employee
Foo McGoo
Bar Too
Jacobs-MacBook-Pro:~ jacob$
*/
#include <iostream>
#include <string>
#include <vector>
using std::string;
using std::vector;
using std::cout;
using std::endl;
/* define class (this should be in a header file) */
class Employee{
public:
//Variables
string Name;
//Functions
Employee(const string&); //constructor
void AddCoWorker(const Employee&);
void ShowCoWorkers();
private:
vector<Employee> employees;
}; //Note the semicolon
//Entry point
int main(int argc, char **argv){
Employee foo("Foo McGoo");
Employee bar("Bar Too");
Employee me("Bevis");
me.AddCoWorker(foo);
me.AddCoWorker(bar);
me.ShowCoWorkers();
return 0;
}
//Class functions (should be in a separate cpp file)
Employee::Employee(const string& name){
this->Name = name;
}
void Employee::AddCoWorker(const Employee &e){
this->employees.push_back(e);
}
void Employee::ShowCoWorkers(){
int count = this->employees.size();
for(int i = 0; i < count; i++){
//Print the names of each co worker on separate lines
cout << this->employees[i].Name << endl;
}
}

Instantiating a New Object in C++

I'm a Java/PHP programmer learning C++.
I've created a class called UserAccount and a class called Database.
I have an input file with five names:
Bob
Sam
Jane
Mark
Ann
I have the following (pseudo)code:
UserAccount *ua;
while (reading through the list of names, line by line) {
ua = new UserAccount(name); // Create a new user based on this name
Database->add(ua); // Add the user to the database
}
Database->listAllUsers();
The output should mirror the input file. Instead, I get:
Ann
Ann
Ann
Ann
Ann
I assume this has something to do with pointers, but I can't figure it out. I think I've provided enough information to identify the problem, but if the (pseudo)code above looks correct, I can provide more.
Could you provide an example of the correct implementation?
This would be a start:
#include <string>
#include <vector>
class UserAccount {
public:
UserAccount(const std::string& name) : d_name(name) {}
...
private:
std::string d_name;
};
class Database {
public:
Database() : d_accounts() {}
void add(const UserAccount& account) {
this->d_accounts.push_back(account);
}
...
private:
std::vector<UserAccount> d_accounts;
};
void zb() {
Database db;
db.add(UserAccount("Bob"));
...
}
It's different from what you posted because the vector's storing values of UserAccounts. At any rate -- more code would help. I'll eventually delete this because it's not a real answer(well, maybe update once the problem's defined better).
To follow up from my comments. You are likely running afoul of pointers, the std::string class will give you behaviour much more similar to that of Java.
The simplest solution will be to use the string strdup() call.
#include <cstring> // provides C string interface
UserAccount::UserAccount(char *n) {
name = strdup(n);
}
UserAccount::~UserAcount() {
// This is older C style, cleanup. Need or the memory will "leak".
free(name);
// You could also use: delete[] name;
}
Alternatively you could use std::string, but I'll leave that to your learning process. There is a lot of information on pointers out there, it will help your learning to understand pointers intimately.
// e.g.
char *str1 = "ann";
char *str2 = "bob";
str1 = str2;
// Both equal "bob".
str1 = "carol";
// Both equal "carol"!
Good luck.
In C++, unlike other languages, you must explicitly think about where things are stored in memory. A pointer tells you where to look in memory to find something. An analogy would be to tell you to look at at the third letter in the 5th row on page 124 of a book. If my book is written in pencil, I could erase the words on that page and replace them with other words, and while the pointer would stay the same (that is, I look at the same location in the book), what is being pointed to would change.
This is what is happening in your code. Each time you read in a name, you are erasing the previous name and writing the new name in the same memory location. Thus, when you pass in a pointer in your constructor, you are in danger of the memory you are pointing to changing.
To fix this, you need to make a local copy of the name. This can be done by using the string class, as in the response by #Justin. But, for teaching purposes (this code is a bit more complicated), this is how you could allocate new memory internally (the string class just does it for you):
class UserAccount {
public:
UserAccount(const char *name)
{
m_name = new char[strlen(name)+1];
strcpy(m_name, name);
}
~UserAccount()
{
delete [] m_name;
}
private:
char * m_name;
};
Note that we are now using the destructor, because we've allocated memory and need to free it again when the class is deleted. Also note that I haven't checked to see if the name being passed in is null, which should be done. A final note is that strings are implicitly null terminated to tell you when you've hit the end of the string. This is why we must allocate a large size -- to hold the null at the end of the string.
As #Marc pointed out, you can also use strdup, but I thought a longer explanation and showing the explicit allocation of memory would be useful to give a better sense of what is going on.
Menu driven program using STL & Algorithm
U need a useraccount class to store the details of an individual user and database class to store the details of all useraccount s.
use string, stl, algorithms for efficiency.
A sample menu driven program for your need:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
class useraccount
{
string name;
//other details
public:
void get(string str)
{
name=str;
}
void display()
{
cout<<name<<endl;
}
};
void display_db(useraccount & e)
{
e.display();
}
void main()
{
vector<useraccount> database;
useraccount *ptr;
int choice;
string name;
do
{
cout<<"\n\n1.Insert \n2.Delete\n3.Display\n4.Exit \nEnter your choice: \n";
cin>>choice;
switch(choice)
{
case 1:
ptr=new useraccount;
cout<<"Enter name:\n";
cin>>name;
ptr->get(name);
database.push_back(*ptr);
break;
case 2:
database.pop_back();
break;
case 3:
for_each(database.begin(),database.end(),display_db);
break;
case 4:
cout<<"Quiting";
break;
default:
cout<<"wrong choice";
}
}while(choice!=4);
}