edit. I want to thank the two people who helped me in my code. I fixed my coding as of 7:22 PM PST 9/25/2014. Still having trouble with the sorting though.
So I'm trying to teach myself how to use C++ in order to get ahead of my programming class in school. I've already taken Java so I'm relatively familiar with the structure of the coding but not exactly sure what to be typing. This practice problem is:
1)Ask the user how many people he wants to enter into the list.
2)Read 3 strings, then turn that info into a student class and put the student inside a vector.
3)Sort the list by name. (Extra credit would be to sort the list by Student ID)
4)Print the info of each student in the list.
5)Ask user while answer is 'Y', search the list for a name and print the info correlating to the name
While in Java, this seems pretty easy, I'm having an extremely hard time understanding what is going on in C++.
I currently only have 1, 2, 4 and 5 done. This is what I have so far.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
#include <fstream>
#include <iomanip>
using namespace std;
class Student
{
string myName, myStudentID, myClassID;
public:
Student(string name, string studentID, string classID)
{
myName = name;
myStudentID = studentID;
myClassID = classID;
}
string getName() { return myName; }
string getStudentID() { return myStudentID; }
void printInfo() { cout << myName << setw(15) << myStudentID << setw(10) << myClassID << endl; }
};
int main()
{
int num;
std::vector<Student> studentList;
cout << "How many students do you wish to add to the student list ? " << endl;
cin >> num;
cin.ignore();
for (int a = 0; a < num; a++)
{
string inputName, inputStudentID, inputClassID;
//get name
cout << "Please enter the Student name : ";
getline(cin, inputName);
//get student ID
cout << "Please enter the Student ID number : ";
getline(cin, inputStudentID);
//get class ID
cout << "Please enter the Student class ID : ";
getline(cin, inputClassID);
Student thisStudent(inputName, inputStudentID, inputClassID);
studentList.push_back(thisStudent);
cout << endl;
}
//sort(studentList.begin(), studentList.end());
/*
I never figured out how to sort the list by name.
I do not know how to compare the name of studentList[0] and studentList[1]
to put them in alphabetical order.
*/
cout << endl;; // FORMATTING
cout << "The student list has a size of " << studentList.size() << endl;
cout << endl;; // FORMATTING
cout << "Student Name" << setw(15) << "Student ID" << setw(10) << "Class ID" << endl;
for (int a = 0; a < studentList.size(); a++)
{
studentList[a].printInfo();
}
cout << endl;; // FORMATTING
string searchedName;
char answer;
do
{
cout << endl;; // FORMATTING
cout << "Please type the name of the person you want to search for: ";
getline(cin, searchedName);
for (int a = 0; a < studentList.size(); a++)
{
if (searchedName.compare(studentList[a].getName()) == 0)
{
studentList[a].printInfo();
break;
}
else
if (a == (studentList.size() - 1)) //If went to end of the list, tell them name not found.
cout << "There is no " << searchedName << " in the list. \n";
}
cout << "Would you like to search for another person? \n";
cout << "Y for Yes, N for No. \n";
cin >> answer;
cin.ignore();
} while (answer == 'Y' || answer == 'y');
return 0;
}
You could create a static compare function in class Student to use with std::sort
class Student
{
string myName, myStudentID, myClassID;
// ...
static bool compare_name(const Student & lStudent, const Student & rStudent)
{return (lStudent.myName < rStudent.myName);}
};
// ...
std::sort(studentList.begin(), studentList.end(), Student::compare_name);
or if your compiler supports lambda functions:
std::sort(studentList.begin(), studentList.end(),
[studentList](const Student & lStudent, const Student & rStudent)
{return (lStudent.myName < rStudent.myName);});
Related
i got confused about the structure when i need to to pass the value in a function
#include <iostream>
using namespace std;
struct student
{
int studentID;
char studentName[30];
char nickname[10];
};
void read_student(struct student *);
void display_student(struct student *);
int main()
{
student *s;
//struct student *ps;
read_student(s);
display_student(s);
}
void read_student(struct student *ps)
{
int i;
for (i = 0; i <= 2; i++)
{
cout << "Enter the studentID : ";
cin >> ps->studentID;
cout << "Enter the full name :";
cin.ignore();
cin >> ps->studentName;
cout << "Enter the nickname : ";
cin.ignore();
cin >> ps->nickname;
cout << endl;
}
}
void display_student(struct student *ps)
{
int i;
cout << "student details :" << endl;
for (i = 0; i <= 2; i++)
{
cout << "student name : " << *ps ->studentName << " (" << &ps ->studentID << ")" << endl;
ps++;
}
}
its only problem at the variable at line 19 and when i try to edit it will became more problem
student *s;
//struct student *ps;
//struct student *ps;
read_student(s);
display_student(s);
also can someone explain how to transfer pointer value of structure to the function and return it back to the main function
You are suffering from some leftovers from your C-Language time. And, you have still not understood, how pointer work.
A pointer (as its name says) points to something. In your main, you define a student pointer. But it is not initialized. It points to somewhere. If you read data from somewhere, then it is undefined behavior. For writing, it is the same, plus that the system will most likely crash.
So, define a student. And if you want to give it to a sub-function, take its address with th &-operator (this address will point to the student) and then it will work.
You need also to learn abaout dereferencing. Your output statement is wrong.
Last but not least, if you want to store 3 students, then you need an array or some other storage where to put them . . .
In your read function you always overwrite the previously read student and in your display function you show undetermined data.
Please have a look at your minimal corrected code:
#include <iostream>
using namespace std;
struct student
{
int studentID;
char studentName[30];
char nickname[10];
};
void read_student( student*);
void display_student( student*);
int main()
{
student s;
//struct student *ps;
read_student(&s);
display_student(&s);
}
void read_student( student* ps)
{
cout << "Enter the studentID : ";
cin >> ps->studentID;
cout << "Enter the full name :";
cin.ignore();
cin >> ps->studentName;
cout << "Enter the nickname : ";
cin.ignore();
cin >> ps->nickname;
cout << endl;
}
void display_student( student* ps)
{
cout << "student details :" << endl;
cout << "student name : " << ps->studentName << " (" << ps->studentID << ")" << endl;
ps++;
}
And, the commenters are right. You must read a book.
This is what it's suppose to look like
Am I doing this correctly? and what another coding I need to do to display like this. I have to simulate a database to store animal types and animal type count. I have to use parallel arrays for data storage. It would be better if I make this dynamically allocated array of no mroe than 5 elements.
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
const int MAX_RECORDS = 5;
const int ADD = 1, DISPLAY = 2, EXIT = 3;
void addAnimal();
void displayAnimal();
int main()
{
int choice, animal;
int a = 0;
do
{
cout << "How many animal records would you like to store (5 max): ";
cin >> animal;
cout << endl;
cout << "1. Add animal(s)" << endl;
cout << "2. Display animals" << endl;
cout << "3. Quit" << endl;
cout << endl;
do
{
cout << "Please enter a menu number: ";
cin >> choice;
if (choice <= 0 || choice > EXIT)
{
cout << "Error. Please try again.\n";
cout << endl;
}
} while (choice <= 0 || choice > EXIT);
// Create a muliway branch statement.
switch (choice)
{
case ADD:
addAnimal();
break;
case DISPLAY:
displayAnimal();
break;
case EXIT:
break;
}
} while (choice != EXIT);
cout << endl;
system("pause");
return 0;
}
void addAnimal()
{
string str;
do
{
cout << "Please enter an animal type (none to stop): " << endl;
getline(cin, str);
cout << "Enter the animal type's count: " << endl;
getline(cin, str);
} while (str != "goodbye");
}
void displayAnimal()
{
}
Another good way to achieve what you want is to inculcate Object-Oriented programming into this. Here is a simple structure of Animals that can be used to create an array of 5 objects.
Take this short example
#include<iostream>
struct Animal{
std::string name;
int value;
int weight;
}animals[5]; // creates an animal object array of size 5
int main(){
for (int i = 0;i < 5;i++){
std::cout << "Name of animal number " << i+1 << ": ";
std::cin >> animals[i].name;
}
std::cout << animals[0].name;
}
Output:
Name of animal number 1: Tiger
Name of animal number 2: Lion
Name of animal number 3: Kangaroo
Name of animal number 4: Cheetah
Name of animal number 5: Dog
Tiger
Process returned 0 (0x0) execution time : 23.463 s
Press any key to continue.
Information on what is going on in this program.
When I say struct Animal I am creating a structure. Animals all have similar features like weight, color, name etc. Those are the variables that will be present inside the body of the structure.
`animals[5]'. Think of this as an array of animals. Animals that have common attributes like weight, color, name etc. Assume the user wants to create a new animal and enter it's features. I can use one element from the array to do this. Let's use the first one.
std::cout << "Enter name: ";
std::cin >> animals[0].name;
std::cout << "Enter weight: ";
std::cin >> animals[0].weight;
std::cout << "Enter value: ";
std::cin >> animals[0].value;
Now the first element of animals has been initialised. You can access it by animals[0].attribute
This approach will work effeciently for this kind of a program. Refer to this.
In my example I have taken input of all 5 elements using a loop. You can do the same when the user wants.
For your purpose, I would suggest you use std::vector<>.Below is a basic implementation of using vectors in C++.
Note: You need to mention #include<vector> at the top.
#include<vector>
#include<iostream>
int main(){
std::vector<int> my_vec; // initializing a vector of integers
// To add anything to a vector, you can use
my_vec.push_back(5); // Adds 5 to my_vec
my_vec.push_back(6); // Adds 6 to my_vec
std::cout << my_vec[0] << std::endl; // Slicing from a vector
for(auto it:my_vec) std::cout << it << std::endl; // display contents
return 1;
}
I cannot show you everything about vectors in this answer, it's another huge topic. The main idea is that they are dynamic and can change size during run-time. compared to traditional static arrays.
vectors in C++
Perhaps consider using an std::map. You can add as many animals as you want. Each animal name, in this case, will have an associated count. In the example below, when the program exits, it will print out everything that you added to the map.
#include <iostream>
#include <map>
#include <string>
int main()
{
std::map<std::string, int> animal_database;
std::string animal_name;
std::string animal_count;
std::string in_val;
while (1)
{
std::cout << "Enter an animal name: ";
std::cin >> animal_name;
std::cout << "Enter animal count: ";
std::cin >> animal_count;
animal_database.insert(std::pair<std::string, int>(animal_name, std::stoi(animal_count)));
std::cout << "Would you like to to add another animal?: [Y] or [N] ";
std::cin >> in_val;
if (in_val == "N" || in_val == "n")
break;
}
for (std::map<std::string, int>::iterator it = animal_database.begin(); it != animal_database.end(); ++it)
{
std::cout << it->first << " " << it->second << std::endl;
}
}
Structure and DMA. I want to retrieve all the inserted record in decreasing order of cgpa.
Without sorting it give the result as shown below image.
#include<iostream>
#include<string>
using namespace std;
struct student {
string name;
int age;
float cgpa;
};
void main()
{
student *ptr;
int size;
cout << "enter size \n";
cin >> size;
ptr = new student[size];
for (int i = 0; i < size; i++)
{
cout << "enter student " << i + 1 << " name\n";
cin >> ptr[i].name;
cout << "enter student " << i + 1 << " age\n";
cin >> ptr[i].age;
cout << "enter student " << i + 1 << " cgpa\n";
cin >> ptr[i].cgpa;
}
cout << "with out sorting \n";
for (int i = 0; i < size; i++)
{
cout << " NAME\tAGE\tCGPA\n";
cout << ptr[i].name << "\t" << ptr[i].age << "\t" << ptr[i].cgpa << endl;
}
system("pause");
}
[1]: https://i.stack.imgur.com/whP8d.png
"Without sorting" is a bit unclear, but I take that to mean you cannot call std::sort directly or use another explicit sorting routine. That leaves you with choosing a container that stores object in sort order based on a compare function (or overload) you provide. Looking at the Microsoft C++ language conformance table for VS2015, it shows all core language features for C++11 supported -- which would include std::set.
std::set allows you to store a sorted set of unique objects. This means you can take input and store the results in a std::set based a Compare function you provide. Providing a Compare function that will compare the cgpa of each student will then automatically store your student objects based cgpa.
To make std::set available, you simply need to #include<set>. Writing the compare function that can be used to store students based on cgpa simply requires providing an overload for the < operator that takes two of your student objects as arguments and then returns true when the first argument sorts before the second, false otherwise. That can be as simple as:
/* overload of < comparing student by cgpa */
bool operator <(const student& a, const student& b) {
return a.cgpa < b.cgpa;
}
A note: unless you are compiling for a micro-controller or embedded system with no Operating System (called a freestanding environment), void main() is wrong. A standard conforming invocation of main() is either int main(void) or int main (int argc, char **argv) where argc is the argument count and argv your argument vector (technically an array of pointers to null-terminated strings where the next pointer after the last argument is set to NULL as a sentinel) There are other non-standard extensions added by some compilers like char **envp providing a pointer to each of the environment variables.
To declare your set of student you need to provide the type student and the compare function to be used when inserting students into your set. Since you provide an overload for the less-than operator, you can use std::less<> providing one template argument, e.g.
int main(void)
{
/* create std::set of students using std::less for compare */
std::set<student, std::less<const student&>> students {};
And since you are using a container that provides automatic memory management for you, there is no need to know the size (or number of students to enter) before hand. You can simply enter as many students as you need and then press Ctrl+d on Linux or Ctrl+z on Windows to generate a manual EOF signifying your end of input. However you do need to validate every user input by checking the return (stream state) following each input. At minimum you can use:
std::cout << "enter student " << i + 1 << " name\n";
if (!(std::cin >> s.name)) /* validate all input, ctrl + z to end input */
break;
(note: the variable i is only needed to show the student number when you prompt for input, all containers provides the .size() member function that tell you how many objects are contained within.)
When done taking input, you can use a Range-based for loop to iterate over each student in your set outputting the desired information. For example:
std::cout << "\nwith out sorting \n";
for (auto& s : students) { /* output in order of cgpa w/o sorting */
std::cout << " NAME\tAGE\tCGPA\n"
<< s.name << "\t" << s.age << "\t" << s.cgpa << '\n';
}
Putting it altogether, you could do:
#include <iostream>
#include <string>
#include <set>
struct student { /* struct student */
std::string name;
int age;
float cgpa;
};
/* overload of < comparing student by cgpa */
bool operator <(const student& a, const student& b) {
return a.cgpa < b.cgpa;
}
int main(void)
{
/* create std::set of students using std::less for compare */
std::set<student, std::less<const student&>> students {};
for (int i = 0; ; i++) {
student s {}; /* temporary struct to add to set */
std::cout << "enter student " << i + 1 << " name\n";
if (!(std::cin >> s.name)) /* validate all input, ctrl + z to end input */
break;
std::cout << "enter student " << i + 1 << " age\n";
if (!(std::cin >> s.age))
break;
std::cout << "enter student " << i + 1 << " cgpa\n";
if (!(std::cin >> s.cgpa))
break;
students.insert(s); /* insert student in set */
}
std::cout << "\nwith out sorting \n";
for (auto& s : students) { /* output in order of cgpa w/o sorting */
std::cout << " NAME\tAGE\tCGPA\n"
<< s.name << "\t" << s.age << "\t" << s.cgpa << '\n';
}
}
(note: Look at Why is “using namespace std;” considered bad practice?. Developing good habits early is a lot easier that trying to break bad ones later...)
(note 2: you might consider using getline(std::cin, s.name) to take input for the student name so you can handle names with spaces, like Firstname Lastname, e.g. Mickey Mouse, up to you)
Add system("pause"); back in to hold your terminal window open as needed.
Example Use/Output
Now just enter the student data for as many students as you like and then terminate input by generating a manual EOF as described above, e.g.
$ ./bin/set_student_grades
enter student 1 name
gates
enter student 1 age
20
enter student 1 cgpa
2.12
enter student 2 name
della
enter student 2 age
21
enter student 2 cgpa
2.00
enter student 3 name
jim
enter student 3 age
30
enter student 3 cgpa
3.12
enter student 4 name
with out sorting
NAME AGE CGPA
della 21 2
NAME AGE CGPA
gates 20 2.12
NAME AGE CGPA
jim 30 3.12
This provides a way to store and provide the student data in order of cgpa without an explicit sort. Of course std::set does that for you, but if avoiding an explicit sort was the intent of your program, this is very good option. Let me know if you have further questions.
#include<iostream>
#include<string>
using namespace std;
struct student {
string name;
int age;
float cgpa;
};
void main() {
student *ptr;
int size;
cout << "enter size \n"; cin >> size;
ptr = new student[size];
for (int i = 0; i < size; i++)
{
cout << "enter student " << i + 1 << " name\n";
cin >> ptr[i].name;
cout << "enter student " << i + 1 << " age\n";
cin >> ptr[i].age;
cout << "enter student " << i + 1 << " cgpa\n";
cin >> ptr[i].cgpa;
}
string temp1; int temp2; float temp3;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
if (ptr[i].cgpa < ptr[j].cgpa)
{
temp1 = ptr[j].name;
ptr[j].name = ptr[i].name;
ptr[i].name = temp1;
temp2 = ptr[j].age;
ptr[j].age = ptr[i].age;
ptr[i].age = temp2;
temp3 = ptr[j].cgpa;
ptr[j].cgpa = ptr[i].cgpa;
ptr[i].cgpa = temp3;
}
}
}
for (int i = 0; i < size; i++) {
cout << " NAME\tAGE\tCGPA\n";
cout << ptr[i].name << "\t" << ptr[i].age << "\t" << ptr[i].cgpa << endl;
}
delete[] ptr;
system("pause");
}
Alrighty, the goal of what I am trying to do right now is call the function getSingleStudentInfo, which contains the student's number, last name, and age. In the end this program is designed to do two things, the first being the single student info, the second, printing out an array of 20 students. Disregard the second part, as I have not really gotten into that part yet, so ignore anything involving vectors.
The problem that I am having is that in main the first thing that the program will do is ask you to press 1 for the single info or 2 for the full 20 peoples info. The program compiles fine, but what happens is, no matter what number you enter, the program will say "process returned 0 (0x0)" and be done, I'm having a hard time figuring out why it is doing that instead of printing out the single students info, being "student's ID number is 400" "student's last name is: Simmons" "student's age is: 20"
#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct Student {
int studentNumber = 400;
string lastName = "Simmons";
int age = 20;
};
Student s;
int selection;
vector<int> studentNumber (20);
vector<string> lastName;
vector<int> age (20);
void getSingleStudentInfo (int studentNumber, string lastName, int age) {
cout << "Student's ID number is: ";
cout << s.studentNumber << endl;
cout << "Student's last name is: ";
cout << s.lastName << endl;
cout << "Student's age is: ";
cout << s.age << endl;
return;
};
int main()
{
cout << "Press '1' to see a single student data entry" << endl;
cout << "Press '2' to see all 20 student records" << endl;
cin >> selection;
if (selection == 1) {
getSingleStudentInfo;
};
/*for (vector<int>::size_type i = 0; i <= 20; i++)
{
cout << "Student's ID number is: " << 400 + i << endl;
}
return 0;*/
}
You need to call the function, e.g.
if (selection == 1)
{
getSingleStudentInfo(7, "Johnson", 20);
}
However, it seems like by the implementation, this should be a method off of the student itself
struct Student {
int studentNumber = 400;
string lastName = "Simmons";
int age = 20;
void getSingleStudentInfo() const;
};
Then you'd call it off a Student instance
Student s{400, "Simmons", 20};
s.getSingleStudentInfo();
Then if you had a vector of Student you could do
std::vector<Student> students; // assume this has been populated
std::for_each(begin(students),
end(students),
[](const Student& s){s.getSingleStudentInfo();});
To print in columns, you could change your function to something like
void Student::getSingleStudentInfo()
{
cout << s.studentNumber << '\t'
<< s.lastName << '\t'
<< s.age << endl;
};
I'm new to c++ and I'm trying to make a simple class roster program that accepts new students storing the student data in an array that then be sorted and display the contents of the array. However when running the program and entering the menu selection, two of the three functions do not work. Any help or guidance is much appreciated. My code is here.
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
using namespace std;
//Create Students class
class Students
{
public:
char sFirstName[256];
char sLastName[256];
int sStudentID;
double sGrade;
double sGPA;
double nCreditHours;
};
//functions
Students addStudent();
//void displayRoster();
//void sortRoster();
void showMenu();
void showWelcome();
//Welcome function
void showWelcome()
{
cout << "Welcome to my class roster program. \n"
<< "This program can be used to add students to the roster, \n"
<< "which can then be sorted by either name or I.D. number. \n"
<< endl;
}
//Menu function
void showMenu()
{
cout << " Student Roster: \n"
<< "MAIN MENU PLEASE SELECT AN OPTION" << endl;
cout << "1) Add student to roster: " << endl;
cout << "2) Display current roster: " << endl;
cout << "3) Sort roster: " << endl;
cout << "4) Exit program: " << endl;
//cout << "5) Display roster sorted by 'student I.D.': " << endl;
//cout << "6) Display roster sorted by 'Grade': " << endl;
//cout << "7) Display roster sorted by 'GPA': \n" << endl;
cout << " Make your selection: \n" << endl;
}
//Add student function
Students addStudent()
{
Students student;
cout << "Add student to roster. \n"
<< "Enter first name: " << endl;
cin >> student.sFirstName;
cout << "Enter last name: " << endl;
cin >> student.sLastName;
cout << "Enter student I.D.: " << endl;
cin >> student.sStudentID;
return student;
}
void displayStudent(Students student)
{
cout << "Student name: " << student.sFirstName << " "
<< student.sLastName << endl;
cout << "I.D. # " << student.sStudentID << endl;
}
void displayRoster()
{
Students student[256];
int nCount;
for (int index = 0; index < nCount; index++)
{
displayStudent(student[index]);
}
}
int getStudents(Students student[], int nMaxSize)
{
int index;
for (index = 0; index < nMaxSize; index++)
{
char uInput;
cout << "Enter another student to the roster? (Y/N): ";
cin >> uInput;
if (uInput != 'y' && uInput != 'Y')
{
break;
}
student[index] = addStudent();
}
return index;
}
void sortRoster()
{
Students student[256];
int nCount;
//bubble swap
int nSwaps = 1;
while (nSwaps != 0)
{
nSwaps = 0;
for (int n = 0; n < (nCount - 1); n++)
{
if (student[n].sStudentID > student[n+1].sStudentID)
{
Students temp = student[n+1];
student[n+1] = student[n];
student[n] = temp;
nSwaps++;
}
}
}
}
int main()
{
int selection; //menu selection variable
//constants for menu selection
const int ADD_STUDENT = 1,
DISPLAY_ROSTER = 2,
SORT_ROSTER = 3,
QUIT_PROGRAM = 4;
Students student[256];
//int nCount = getStudents(student, 256);
do
{
showWelcome(); //Show welcome message
showMenu(); //Show menu options
cin >> selection;
while (selection < ADD_STUDENT || selection > QUIT_PROGRAM)
{
cout << "Enter a valid selection: ";
cin >> selection;
}
if (selection != QUIT_PROGRAM)
{
switch (selection)
{
case ADD_STUDENT:
addStudent();
break;
case DISPLAY_ROSTER:
displayRoster();
break;
case SORT_ROSTER:
sortRoster();
break;
}
}
}
while (selection != QUIT_PROGRAM);
return 0;
}
The problem is not in the switch.
The addStudent() is not adding the student into any list or array. Also since it return type is Students you should add it into the any array of Students. Since you have not stored any data display won't display anything.
The another problem is of nCount. You are using it in for comparison without initializing it. Also to keep nCount synchronized either make it global, use as pointer or handle it with return.
Also the problem is in displayRoster(). You are declaring Students array as Students student[256]; and you are using it without initializing. Also if initialized, it won't have the data which was given as input.
NOTE: Sit and read your code again, there are many more mistakes. Try visualizing how your data should be stored and how your code is to behave and then start writing code.
Your nCount is not initialised. Since this variable is used in those two functions (and assuming that it refers to the total count), you can declare it as a global variable:
nCount=0;
Everytime you add a new entry, you can increment the counter as:
nCount++;
Another suggestion to make your code actually work:
student[i++]=addStudent();
where i is a counter initialised to 0. Your addStudent() function returns an object, and you discard it. Store it in the array of objects you created:
Students student[256];
Also, since you use the above in almost all functions, it is best to declare it as global rather than redeclaring in each function.