I am trying to sort a class array that has 5 values inside of it. 3 strings and 2 ints. I would like to sort the array from highest to lowest on the int values but can't figure out how to do so. My though process is to send the array into the class and then pull out the correct int value and sort for each array location without changing the other values of that location.
How can I pull out these values so that I can sort them accordingly? If I could then I would know how to finish my code.
If there is an easier way to do this then I am open to any suggestions.
In the code below I have a template of what I would do if I could pull that number out:
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
class Thing
{
public:
Thing();
void setvariables(string s, string g, string a, int y, int l);
void get();
void print();
void sort_time(Thing data[], int datasize);
private:
string name;
string genre;
string artist;
int year;
int length;
};
Thing::Thing()
{
name = "";
genre = "";
artist = "";
year = 13;
length = 15;
}
void Thing::setvariables(string n, string g, string a, int y, int l)
{
name = n;
genre = g;
artist = a;
year = y;
length = l;
}
/* void Thing::sort_time(Thing data[], int datasize)
{
int lar_pos, pos, lar_val;
for (int index = 0; index < datasize; index++)
{
lar_pos = index;
lar_val = data[index].get();
for (pos = index; pos < datasize; pos++)
{
if (data[pos] > data[lar_pos])
{
lar_pos = pos;
lar_val = data[lar_pos];
}
}
data[lar_pos] = data[index];
data[index] = lar_val;
}
}
void Thing::get()
{
l = length;
}
*/
void Thing ::print()
{
cout << setw(25) << name << setw(10) << genre << setw(5) << year
<< setw(30) << artist << setw(5) << length << endl;
}
int main()
{
// Create array of things
int size = 9;
Thing array[9];
// Initialize array of things
for (int i = 0; i<size; i++)
{
string name, genre, artist, junk;
int year, length;
getline(cin, name);
getline(cin, genre);
getline(cin, artist);
cin >> year;
cin >> length;
array[i].setvariables(name, genre, artist, year, length);
cin.ignore(256, '\n');
}
// Print array of things
cout << setw(25) << "TITLE" << setw(10) << "GENRE" << setw(5) << "YEAR"
<< setw(30) << "ARTIST" << setw(5) << "TIME" << endl;
cout << setw(25) << "=====" << setw(10) << "=====" << setw(5) << "===="
<< setw(30) << "======" << setw(5) << "====" << endl;
for (int i = 0; i<size; i++)
array[i].print();
return 0;
}
Use std::sort with a custom comparator or define operator< for your type.
Example:
#include <algorithm>
class Thing
{
// ...
};
class ThingComparator
{
bool operator()(const Thing& a, const Thing& b)
{
// Define your logic here and return true if a is considered lesser than b.
}
};
int main()
{
const int size = 9; // Make it constant!!
Thing array[size];
// Fill the array ...
// Then sort it
std::sort(array, array + size, ThingComparator());
}
Related
In my class we recently got introduced to STL vectors. My professor has given us a program that uses arrays, and we are to convert it to use std::vectors instead. He would like us to use iterators, so we're not allowed to use square brackets, the push_back member function, or the at member function. Here's one of the for loops from the program I have to convert:
void readData(Highscore highScores[], int size)
{
for(int index = 0; index < size; index++)
{
cout << "Enter the name for score #" << (index + 1) << ": ";
cin.getline(highScores[index].name, MAX_NAME_SIZE, '\n');
cout << "Enter the score for score #" << (index + 1) << ": ";
cin >> highScores[index].score;
cin.ignore();
}
cout << endl;
}
`
I'm just not quite understanding how to convert them. so far, I was kind of able to get this: for (vector <Highscore> :: iterator num = scores.begin(); num < scores.end(); num++)for the for loop. It doesn't quite make sense to me so I was hoping I can get some more tips or even more information on how to convert them. I don't want an answer, simply just a tip. Thank you! (if its of any help, this is the program I am having to convert and these are the four headers we have to use
void getVectorSize(int& size);
void readData(vector<Highscore>& scores);
void sortData(vector<Highscore>& scores);
vector<Highscore>::iterator findLocationOfLargest(
const vector<Highscore>::iterator startingLocation,
const vector<Highscore>::iterator endingLocation);
void displayData(const vector<Highscore>& scores);
above are the headers that have to be used (having to use these instead of the programs headers)
#include <iostream>
using namespace std;
const int MAX_NAME_SIZE = 24;
struct Highscore{
char name[MAX_NAME_SIZE];
int score;
};
void getArraySize(int& size);
void readData(Highscore highScores[], int size);
void sortData(Highscore highScores[], int size);
int findIndexOfLargest(const Highscore highScores[], int startingIndex, int size);
void displayData(const Highscore highScores[], int size);
int main()
{
Highscore* highScores;
int size;
getArraySize(size);
highScores = new Highscore[size];
readData(highScores, size);
sortData(highScores, size);
displayData(highScores, size);
delete [] highScores;
}
void getArraySize(int& size){
cout << "How many scores will you enter?: ";
cin >> size;
cin.ignore();
}
void readData(Highscore highScores[], int size)
{
for(int index = 0; index < size; index++)
{
cout << "Enter the name for score #" << (index + 1) << ": ";
cin.getline(highScores[index].name, MAX_NAME_SIZE, '\n');
cout << "Enter the score for score #" << (index + 1) << ": ";
cin >> highScores[index].score;
cin.ignore();
}
cout << endl;
}
void sortData(Highscore highScores[], int numItems) {
for (int count = 0; count < numItems - 1; count++){
swap(highScores[findIndexOfLargest(highScores, count, numItems)],
highScores[count]);
}
}
int findIndexOfLargest(const Highscore highScores[], int startingIndex, int numItems){
int indexOfLargest = startingIndex;
for (int count = startingIndex + 1; count < numItems; count++){
if (highScores[count].score > highScores[indexOfLargest].score){
indexOfLargest = count;
}
}
return indexOfLargest;
}
void displayData(const Highscore highScores[], int size)
{
cout << "Top Scorers: " << endl;
for(int index = 0; index < size; index++)
{
cout << highScores[index].name << ": " << highScores[index].score << endl;
}
}
You maybe looking for one of two things.
If you want to add something to a vector, the function is push_back
vecScores.push_back(value) ; //in a for loop.
https://www.cplusplus.com/reference/vector/vector/push_back/
If you want to add something to a map, you could just use the form of
mapScore[index]=value ; // in a for loop.
https://www.cplusplus.com/reference/map/map/operator[]/
Probably your professor wants you to write something like this:
void readData(std::vector<Highscore>& highScores)
{
for (auto it = highScores.begin(); it != highScores.end(); ++it) {
cout << "Enter the name for score #" << std::distance(highScores.begin(), it) << ": ";
cin.getline(it->name, MAX_NAME_SIZE, '\n');
cout << "Enter the score for score #" << std::distance(highScores.begin(), it) << ": ";
cin >> it->score;
cin.ignore();
}
cout << endl;
}
where it is the iterator that's incremented via ++it from highScores.begin() to just before highScores.end(); then you access the members of the highScores's element "pointed by" it via it->member.
Here's a complete demo.
By the way, considering how much your professor likes void(some_type&) functions (and using namespace std;, if that was not your own idea), I would doubt you have much to learn from him. You better buy a good book.
I would do it like this, also get used to typing std::
Why is "using namespace std;" considered bad practice?
Also be careful with signed/unsigned, be precise about it.
If something can't have a negative value use unsigned types (or size_t)
#include <iostream>
#include <string>
#include <vector>
struct HighScore
{
std::string name;
unsigned int score;
};
// use size_t for sizes (value will always >0)
std::vector<HighScore> GetHighScores(size_t size)
{
std::vector<HighScore> highScores;
std::string points;
for (size_t index = 0; index < size; index++)
{
HighScore score;
std::cout << "Enter the name for score #" << (index + 1) << ": ";
std::cin >> score.name;
std::cout << "Enter the score for score #" << (index + 1) << ": ";
std::cin >> points;
// convert string to int
score.score = static_cast<unsigned int>(std::atoi(points.c_str()));
highScores.push_back(score);
}
std::cout << std::endl;
return highScores;
}
int main()
{
auto highScores = GetHighScores(3);
return 1;
}
I have to create an array of pointer to class objects.
Then I have with function AddStudent I have to change/create a new student (add his data to pointer address).
In last step function ShowAllStudents has to show all students. But I shows only the last added student.
Every new object is beeing created in array index of 0. I don't know why.
There is my code:
index.html:
#include <iostream>
#include "student.h"
void AddStudent(Student* pointer_array[], int n)
{
int IndexNr{}, id{};
std::string name{}, surname{};
std::cout << "Write IndexNr:";
std::cin >> IndexNr;
for(int i = 0; i < n; i++){
if (IndexNr != pointer_array[i]->Student::IndexNr && pointer_array[i]->Student::name == "none")
{
i = id;
pointer_array[i]->Student::IndexNr = IndexNr;
break;
}
else if (IndexNr == pointer_array[i]->Student::IndexNr) {
i = id;
break;
}
}
std::cout << "Student's name: ";
std::cin >> name;
pointer_array[id]->Student::name = name;
std::cout << "Student's surname ";
std::cin >> surname;
pointer_array[id]->Student::surname = surname;
}
void ShowAllStudents(Student* pointer_array[], int n)
{
for (int i = 0; i < n; i++) {
if (pointer_array[i]->Student::name != "none")
{
std::cout << "<id>: " << pointer_array[i]->Student::IndexNr << " <Name>: " << pointer_array[i]->Student::name << " <Surname>: " << pointer_array[i]->Student::surname << std::endl;
}
else if (pointer_array[i]->Student::name != "none" && i == (n - 1))
std::cout << "<id>: no data" << std::endl;
}
}
int main()
{
int n{10};
Student* pointer_array[10];
for (int i = 0; i < n; i++)
pointer_array[i] = new Student;
AddStudent(pointer_array, n);
AddStudent(pointer_array, n);
AddStudent(pointer_array, n);
ShowAllStudents(pointer_array, n);
return 0;
}
student.h
#include <iostream>
#ifndef STUDENT_H_
#define STUDENT_H_
class Student {
public:
int IndexNr;
std::string name;
std::string surname;
Student() {
IndexNr = 0;
name = "none";
surname = "none";
}
};
#endif
It shows only the last edited student.
C++:
I'm trying to sort some students that are stored in a class by average media.
Only qsort, don't advice me of std::sort, thank you!
Qsort compare function:
int cmp(Student *a, Student *b) {
return (int)(((Student *)b)->get_media() - ((Student *)a)->get_media());
}
qsort call:
qsort(&tab, (size_t)n, sizeof(tab), (int(*)(const void*, const void*))cmp);
There's no compiler error, but it won't sort.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Student {
private:
char name[20];
char surname[20];
int *marks;
int group;
float avg_mark;
public:
Student()
{
char na[20], sur[20];
int group;
cout << "\nEnter name: ";
cin >> na;
cout << "\nEnter surname: ";
cin >> sur;
cout << "\nEnter group: ";
cin >> group;
init(na, sur, group);
}
~Student()
{
cout << "\ndestructor";
delete []marks;
}
void init(char *n, char *p, int gr)
{
strcpy(name, n);
strcpy(surname, p);
group = gr;
marks = new int[6];
for (int i = 0; i < 6; i++)
{
cout << "\nEnter mark " << i + 1 << ": ";
cin >> *(marks + i);
}
avg_mark = media();
}
float media()
{
int s = 0;
for (int i = 0; i < 6; i++)
s += marks[i];
return ((float)s / 6);
}
void set_name(char *n)
{
strcpy(name, n);
}
char* get_name()
{
return name;
}
void set_surname(char *p)
{
strcpy(name, p);
}
char* get_surname()
{
return surname;
}
int get_group()
{
return group;
}
float get_media()
{
return avg_mark;
}
};
int cmp(Student *a, Student *b);
int comparator(void *a, void *b) {
return (int)(((Student *)b)->get_media() - ((Student *)a)->get_media());
}
void main(void)
{
int n;
cout << "\nEnter n: ";
cin >> n;
Student *tab = new Student[n];
for (int i = 0; i < n; i++)
cout << i + 1 << ". " << tab[i].get_name() << " " << tab[i].get_surname() << " Group:" << tab[i].get_group() << " Average mark: " << tab[i].get_media() << endl;
//qsort(&tab[0], (size_t)n, sizeof(tab), (int*)cmp);
cout << endl;
qsort(&tab, (size_t)n, sizeof(tab), (int(*)(const void*, const void*))cmp);
for (int i = 0; i < n; i++)
cout << i + 1 << ". " << tab[i].get_name() << " " << tab[i].get_surname() << " Group:" << tab[i].get_group() << " Average mark: " << tab[i].get_media() << endl;
cin.ignore();
cin.get();
}
int cmp(Student *a, Student *b) {
return (int)(((Student *)b)->get_media() - ((Student *)a)->get_media());
}
qsort(&tab, (size_t)n, sizeof(tab), (int(*)(const void*, const void*))cmp);
&tab is the address of the pointer tab. You want to pass the address of the first element of your array. That's &tab[0] or simply tab.
Also, you need to pass the size of a Student object, not the size of a pointer. So change sizeof(tab) to sizeof(Student) or sizeof(*tab). So the call should look like this:
qsort(tab, (size_t)n, sizeof(*tab), (int(*)(const void*, const void*))cmp);
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 6 years ago.
Improve this question
I'm writing a program that calculates the batting averages of a user defined number of players. The program displays the name of a player, their number of times at bat, number of hits, and their batting average. Finally, it displays the total number of times the players were at bat, the total number of hits, and the overall average. For some reason, the functions that calculate the individual player average and overall average are returning 0. It's probably something small, but I'm stumped as to how to try and fix it.
//Batting Average Calculator
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
//Create Structure
struct Record
{
string name;
int AB;
int hit;
double avg;
};
int getSize(int);
void getData(Record[], int );
int calculateTotalAB(Record[], int, int);
int calculateTotalHit(Record[], int, int);
double calculateTotalAvg(Record[], int, double);
void calculateAvg(Record[], int);
void display(Record[], int, int , int, double);
int main()
{
const int MaxSize = 50;
Record players[MaxSize];
int size = 0;
int totalAB = 0;
int totalHit = 0;
double totalAvg = 0;
size = getSize(size);
getData(players, size);
totalAB = calculateTotalAB(players, size, totalAB);
totalHit = calculateTotalHit(players, size, totalHit);
calculateAvg(players,size);
totalAvg = calculateTotalAvg(players, size, totalAvg);
display(players, size, totalHit, totalAB, totalAvg);
}
//get number of players to be calculated
int getSize(int size)
{
cout << "Please enter the number of players on the team: ";
cin >> size;
return size;
}
//get Player name, AB, and hit
void getData(Record players[], int size)
{
string dummy;
getline(cin, dummy);
for (int i = 0; i < size; i++)
{
cout << "Please input the name of student " << i + 1 << ": ";
getline(cin, players[i].name);
cout << "Please input the number of times "<< players[i].name << " was at bat: ";
cin >> players[i].AB;
cout << "Please input the number of hits for " << players[i].name << ": ";
cin >> players[i].hit;
cout << " " << endl;
getline(cin, dummy);
}
}
int calculateTotalAB(Record players[], int size, int totalAB)
{
for (int i = 0; i < size; i++)
{
totalAB = totalAB + players[i].AB;
}
return totalAB;
}
int calculateTotalHit(Record players[], int size, int totalHit)
{
for (int i = 0; i < size; i++)
{
totalHit = totalHit + players[i].hit;
}
return totalHit;
}
void calculateAvg(Record players[], int size)
{
for (int i = 0; i < size; i++)
{
players[i].avg = players[i].hit / players[i].AB;
}
}
double calculateTotalAvg(Record players[], int size, double totalAvg)
{
double j = 0;
for (int i = 0; i < size; i++)
{
j = j + players[i].avg;
}
totalAvg = j / size;
return totalAvg;
}
void display(Record players[], int size, int totalHit, int totalAB, double totalAvg)
{
cout << fixed << showpoint << setprecision(3);
cout << "Player AB Hit Avg" << endl;
cout << " " << endl;
for (int i = 0; i < size; i++)
{
cout << players[i].name << setw(8) << players[i].AB << setw(5) << players[i].hit << setw(5) << players[i].avg;
}
cout << " " << endl;
cout << "Totals " << totalAB << " " << totalHit << " " << totalAvg << endl;
}
You are dividing an int by an int, which is calculated as an int, and storing it in a double. What you have to do is explicitly cast at least one of your int values to a double first, like this:
void calculateAvg(Record players[], int size)
{
for (int i = 0; i < size; i++)
{
players[i].avg = players[i].hit / (double) players[i].AB;
}
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
.....................HEY GUYS,I GOT THE ANSWER.PLEASE CHECK OUT AT BOTTOM.....................
ThAnKs FoR aLl ThOsE wHo TrYiNg tO hElP mE!
How to print all the character outside the for-loop that input inside for-loop? It only prints the last character entered in for-loop
input all 4 names of items and price in void shop::getdata()
output of this only prints the name of item that entered last in void shop::getdata() for 4 times in void shop::putdata()
output of price is correct,it prints orderly.
what's the problem with the name of item?
Question:WAP to store pricelist of 5 items & print the largest price as well as the sum of all prices & pricelist also.
#include<iostream.h>
#include<conio.h>
#include<string.h>
class shop
{
int i;
char item[50];
float price[50];
public:
void getdata();
void putdata();
float sum();
float lar();
};
void shop::getdata()
{
for(i = 0; i <= 4; i++)
{
cout << "Enter the item name:" << "\n";
cin >> item;
cout << "Enter price:" << "\n";
cin >> price[i];
}
}
void shop::putdata()
{
cout << "\t\tPRICE LIST" << "\n";
cout << "\t\t**********" << "\n";
cout << "ITEM NAME\t\t\tPRICE" << "\n";
cout << "*********\t\t\t*****" << "\n";
for(i = 0; i <= 4; i++)
{
cout << item << "\t\t\t\t";
cout << price[i] << "\n";
}
}
float shop::sum()
{
float sum = 0;
for( i= 0; i <= 4; i++)
{
sum = sum + price[i];
}
cout << "\t\t\t\tsum is:" << sum << "\n";
return sum;
}
float shop::lar()
{
float lar;
lar = price[0];
for(i = 0; i <= 4; i++)
{
if (price[i] > lar)
lar = price[i];
}
cout << "\t\t\tlargest is:" << lar;
return lar;
}
void main()
{
shop x;
int c;
clrscr();
x.getdata();
do
{
cout << "\n\n1.PRICE LIST\n";
cout << "2.SUM\n";
cout << "3.LARGEST\n";
cout << "4.EXIT\n";
cout << "Enter your choice\n";
cin >> c;
switch (c)
{
case 1:
x.putdata();
break;
case 2:
x.sum();
break;
case 3:
x.lar();
break;
default:
cout << "PRESS ANY KEY TO EXIT\n";
break;
}
}
while(c >= 1 && c <= 3);
getch();
}
ANSWER
#include<iostream.h>
#include<conio.h>
#include<string.h>
class shop
{
int i;
char item[50];
float price;
float e[10];
public:
void getdata();
void putdata();
float sum();
float lar();
};
void shop::getdata()
{
cout << "Enter the item name:" << "\n";
cin >> item;
cout << "Enter price:" << "\n";
cin >> price;
}
void shop::putdata()
{
cout << item << "\t\t\t\t";
cout << price << "\n";
}
float shop::sum()
{
float sum = 0;
for( i= 0; i <= 4; i++)
{
cout<<"Enter prices"<<"\n";
cin>>e[i];
sum = sum + e[i];
}
cout << "\t\t\t\tsum is:" << sum << "\n";
return sum;
}
float shop::lar()
{
float lar;
lar = e[0];
for(i = 0; i <= 4; i++)
{
if (e[i] > lar)
lar = e[i];
}
cout << "\t\t\tlargest is:" << lar;
return lar;
}
void main()
{
shop x[10];
int c,i;
clrscr();
for(i=0;i<=4;i++)
x[i].getdata();
do
{
cout << "\n\n1.PRICE LIST\n";
cout << "2.SUM\n";
cout << "3.LARGEST\n";
cout << "4.EXIT\n";
cout << "Enter your choice\n";
cin >> c;
switch (c)
{
case 1:
for(i=0;i<=4;i++)
x[i].putdata();
break;
case 2:
x[i].sum();
break;
case 3:
x[i].lar();
break;
default:
cout << "PRESS ANY KEY TO EXIT\n";
break;
}
}
while(c >= 1 && c <= 3);
getch();
}
It's a little hard to tell what you're asking (you would do well to indent your code and ask a clearer question), but I think your problem (well, the main one you're referring to!) is how you're handling item names.
You've declared your shop to contain an array of 50 chars - that is, 50 single characters. Since you have an array of 50 prices, you almost certainly wanted an array of 50 strings. In basic C, that would be char *item[50], an array of 50 dynamically-allocated char arrays. Since you've tagged this as C++, though, you're better off using a string.
A slightly more modern shop would look like this:
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::ostream;
using std::string;
using std::vector;
class Item {
string m_name;
double m_price;
public:
Item(const string &name, double price)
: m_name(name), m_price(price) {
};
string name() const { return m_name; }
double price() const { return m_price; }
};
class Shop {
vector<Item> m_items;
public:
void readData();
void writeData() const;
double getPriceSum() const;
double getMaxPrice() const;
};
void Shop::readData() {
for (;;) {
string name, end_of_line;
double price;
cout << "Enter the item name (or nothing to finish input): ";
getline(cin, name);
if (name == "") {
break;
}
cout << "Enter the price: ";
cin >> price;
// the previous ">>" left the end-of-line in the stream,
// so read it now.
getline(cin, end_of_line);
m_items.push_back(Item(name, price));
}
}
void Shop::writeData() const {
for (size_t i = 0; i < m_items.size(); i++) {
const Item &item = m_items[i];
cout << item.name() << "\t" << item.price() << "\n";
}
}
double Shop::getPriceSum() const {
double sum = 0.0;
for (size_t i = 0; i < m_items.size(); i++) {
sum += m_items[i].price();
}
return sum;
}
double Shop::getMaxPrice() const {
double max = 0.0; // assume that all prices are positive
for (size_t i = 0; i < m_items.size(); i++) {
max = std::max(max, m_items[i].price());
}
return max;
}
int main() {
Shop shop;
shop.readData();
shop.writeData();
cout << "sum: " << shop.getPriceSum() << "\n";
cout << "max: " << shop.getMaxPrice() << "\n";
return 0;
}
It is not perfect C++ style, but still makes the code easy to read.