Bubble sorting in dynamic array of objects in C++ - c++

I have class City with following private data: name of city, width,length and height of the city. I have to make dynamic array, which is inserted by constructor by default- City(),when the programs starts.Then the program uses method output() and prints inserted array of cities.
I should use bubble sort to sort the cities by their length. And when this is done, the program should show the sorted cities in increasing lengths.
The problem is that my data are in private(in public everything works excellent but principle of capsulation is violated!) so I can't do bubble sort.
I tried to do another dynamic array of type double double Lengths[n], which content is lengths of first array. Then I do sorting, but program prints only sorted lengths and this is not my goal.
I should print the names of cities sorted by their lengths.
Code:
class City{
private: char *name;
double width;
double length;
double height;
public:void Output();
City();
~City();
double GetLength()
{
return length;
}
double GetWidth(){ return width; }
double GetHeight(){ return height; }
char GetName(){ return *name; }
};
City::City()
{
char ime[20];
cout << "Name= ";
cin >> ime;
name = new char[strlen(ime) + 1];
for (int i = 0; i <=strlen(ime); i++)
name[i] = ime[i];
cout << "Width= ";
cin >> width;
cout << "Length= ";
cin >> length;
cout << "Height= ";
cin >> height;
}
void City::Output()
{
cout << "Name is: " << name << endl;
cout << " Width is: " << width <<" deg"<< endl;;
cout << " Length is: " << length << " deg"<<endl;
cout << " Height is: " << height <<" m"<<endl;
return;
}
City::~City()
{
cout << " " << endl;
cout << "Destructor of City!" << endl;
delete[] name;
}
int main()
{
//City town;
//town.Input();
//town.Output();
int n;
City *mA;
cout << "Input number of cities: " << endl;
cin >> n;
mA = new City[n];
for (int j = 0; j < n; j++)
{
mA[j].Output();
}
cout << "Cities from west to east, sorted by their length" << endl;
double *Lengths = new double[n];
for (int j = 0; j < n; j++)
{
Lengths[j] = mA[j].GetLength();
}
int k = 0;//counter
double max = Lengths[0];
for (int j = 1; j < n; j++)
{
if (Lengths[j - 1] >Lengths[j])
{
max = Lengths[j - 1];
Lengths[j - 1] = Lengths[j];
Lengths[j] = max;
}
}
for (int j = 0; j < n; j++)//cycle for output
{
mA[j].Output();
}
delete[]mA;
return 0;
}

As I can't quite comment on your response, I will give you a few bits of advice. First in the line of:
Array[j]=mA[j].GetName() ;
You have a random space which may be a copy change and relatively minor but for reading purposes that is wrong.
Second your naming conventions are really something you should work on. I should be able to read a variable and understand what it means but instead I struggle to understand what a variable named mA means.
Third your else clause does nothing literally. Your not moving any parts of the array if that is your intention my saying this:
mA[j+1];
you are simply targeting the element in the array that is above the iteration. I see you stuck with your idea of making something similar to a parallel array for the bubble sort, and that is fine but you lack any action in the first loop.
This is not bubble sort what so ever as you are simply going through each iteration and checking if the element in Lengths is equal in length to the element in mA and then storing that element in array but your else statement does nothing.
Your loop should look similar to something like this but I'm gonna get rid of the character array and the extra array for some reason as it is unnecessary and lets say you start out with an array of your objects:
if(myObjects[i].GetLength() > myObjects[i+1].GetLength()) //Shortest to longest name or vice versa?
{
//Store myObject[i] in temp spot
//myObject[i] = myObject[i+1]
//myObject[i+1] = temp Storage
}
This will give you a bubble sort of the objects on the first round. Of course your going to have to find out how to iterate through the array in loop to verify all of the elements have been sorted correctly as this will of course take many iterations for bubble sort.

I don't see a direct question but I can assume majority of the question by your story. You have multiple options on how to solve this case. One of the simple ways to solve this is create a function within the object that allows you to get the length of a member of an object for example in your case it would be name of city.
Create a method inside the object that you can call to return a private method's length. Create a loop that calls this method and checks each element side by side until you can't refine it any longer. Is there a specific reason your using char instead of string for name?

I'm not entirely sure of what you're asking.
However, from what I can tell your main issue is that you can't sort because you're trying to compare two private variables from two objects.
If the objects are placed into an Array of type city, you can bubblesort by length however you would be required to use the getters in order to reference the variables that are private during sorting.
For example (not exact syntax)
if(cityArray[0].getLength() < cityArray[1].getLength())
{
//Do Something
}

Related

How to write a code where user can give the elements of the array?

I wanted to write a code where user will give input the element of the array and then the elements will be print as an array. Here is my code but the code do not give the array as output.
#include<iostream>
using namespace std;
int main(){
int arr[100] , size , i , num ; //Here we are defining the maximum size of array is 100. So user can choose the size of array by him/her but cannot choose more than 100
cout << "Enter the size of array (Maximum array size you can take is 100) : ";
cin >> size;
if (size > 100)
{
cout << "You cannot take the size more than 100" << endl;
}else{
cout << "Inter the elements using space : ";
for (int i = 0; i < size; i++)
{
cin >> arr[i];
}
cout << "Enter data you want to insert : ";
cin >> num;
for (int i = size - 1 ; i >= 0 ; i--)
{
arr[i+1] = arr[i];
}
arr[0] = num;
size++;
}
cout << arr[i] << endl;
return 0;
}
Your question isn't entirely clear, but I see two basic problems.
First, you define variable i at the top of your code. That's fine, although there are arguments for variable names being longer than a single character. Think about searching for uses of that variable -- you're going to get it in all sorts of places that have nothing to do with the variable. while has an i. if has an i. Be that as it may.
But here's a real problem. You have some for loops like this:
for (int i = 0; ....)
There's nothing wrong with that, not exactly. It works. HOWEVER, it's considered bad form to reuse a variable inside an inner block that matches a variable from an outer block. It's legal, but it's a common source of bugs. I recommend you don't do it.
Then, at the bottom, you do this:
cout << arr[i] << endl;
At this point, we're back to the original variable i that you declare at the top. But you never actually initialize it, so it's some random value. And you're not doing any sort of loop.
I suspect if you wrap this inside another of your for-loops, you'd get the results you want.
And get rid of declaring i at the top.

How to print all values in a dynamically resizing struct? C++

I have a dynamically resizing struct[]. I ask the user for how many records he wants then make that many struct.Then I store the name and age info in the struct. The problem is when printing out that data i am only printing the last name and age the user input. I would like to print all the values.
struct Records
{
char name [32] ;
int age;
};
void program2()
{
Records rec;
int size;
cout << "How many record would you like?";
cin >> size;
cout << "\n" << size;
Records* a = new Records[size];
for (int i = 0; i < size; i++)
{
cout << "Whats the name for the Record: ";
cin >> rec.name;
cout << rec.name;
cout << "What is the age for this record: ";
cin >> rec.age;
}
for (int i = 0; i < size; i++)
{
cout << "\n" << rec.name << rec.age;
}
}
In your code, the variable rec has nothing to do with the array. To access the element at position i of your array, you'll need to use a[i].
For example:
cin >> a[i].name;
or
cout << "\n" << a[i].name << " " << a[i].age;
No surprise - you are actually printing repeatedly the last record that you created (rec). Your last loop is not actually traversing the array.
Also, the first loop only creates a struct, but does not actually add it to the array.
What you are trying to do is actually easier and cleaner if you use vectors instead of arrays, adding each record to the vector using push_back(). This is the closest thing to the "dynamically resized array" that you are referring to (such a thing does not actually exist in C++, that's what vectors are for, amongst other things).
Have a look into doing it this way, and if you get stuck feel free to ask again, happy to help.

Having trouble using iterators erase a vector item every M number of passes

I have been having some issues with implementing a vector. The program that I'm attempting to make does as follows: takes a user defined "size" value and creates a "circular" vector of that size. Then it takes in another integer variable that represents how many iterations of the loop must happen before an item gets deleted from the vector. In my code, I am attempting to iterate through this vector of "Person" objects (a basic class whose only private data member is an integer representing a position). The class that this "runProgram" function is declared in has a private data member of a vector of person objects, then three integers representing the circle size, the number of passes before elimination, and the amount of items in the vector. I have made a while loop to carry-out this procedure. However, every time I run this program, the program seems to make only one pass through the loop, and then delete everything... or just not continue. Here is some of my code:
The main loop:
enter cod int VectorMyJosephus::runProgram(){
int n = 0;
int m = 0;
cout << "How many people would you like in the circle?" << endl;
cin >> n;
cout << "How many passes would you like ther to be before someone is eliminated?" << endl;
cin >> m;
init(n, m);
vector<Person>::iterator iter;
iter = circ.begin();
int count = 0;
while (circ.size() > 1)
{
//count the current person
count += 1;
iter->print();
//remove every "M" person
if (count == M)
{
iter = circ.erase(iter);
count = 0;
size -= 1;
/*printAll();
system("PAUSE");*/
}
else
{
//contine through the list once someone was removed
++iter;
}
if (iter == circ.end())
{
iter = circ.begin();
}
cout << "The position of the only remaining person is: " << iter->getPosition() << "\n" << endl;
cout << circ.size() << endl;
return 0;
}
}e here
Here is my initialization function that is supposed to populate the vector with person objects:
void VectorMyJosephus::init(int N, int M)
{
this->setN(N);
this->setM(M);
this->setSize(N);
for (int i = 0; i < N; i++)
{
Person pers;
pers.setPosition(i);
circ.push_back(pers);
}
}
I'm a beginner, so any help whatsoever is greatly appreciated
You have return 0 inside your while loop, which breaks loop execution immediately.

struct + functions code breaks

There is a problem with the code and i could not find it.
i was asked to write a money struct and use functions to manipulate it.
but the code did not work for any function. i tried couting
the array of structers and it came out nicely, for any missing info
please leave a comment and i'll reply shortly.
Money.txt
2
12 20
13 40
#include <iostream>
#include <fstream>
using namespace std;
struct Money { //declaring structure
int dollars;
int cents;
};
Money addMoney(Money *p[], int n) { //adds money data
Money cash{ 0,0 };
int i;
for (int j = 0; j < n; j++) {
cash.dollars = cash.dollars + p[j]->dollars;
cash.cents = cash.cents + p[j]->cents;
}
if (cash.cents >= 100) //100cents = 1 dollar
{
i = (cash.cents) / 100;
cash.dollars = cash.dollars + i;
i = (cash.cents) % 100;
cash.cents = i;
}
return cash;
}
void printMoney(Money *p[], int n) { //printing money data
for (int i = 0; i < n; i++) {
cout << "Dollars: " << p[i]->dollars << endl;
cout << "Cents: " << p[i]->cents << endl;
}
}
Money maxMoney(Money *p[], int n) {
Money cash;
cash.dollars = p[0]->dollars;
cash.cents = p[0]->cents;
for (int i = 0; i < n; i++)
{
if ((p[i]->dollars)>=(cash.dollars))
if ((p[i]->cents)>(cash.cents))
{
cash.dollars = p[i]->dollars;
cash.cents = p[i]->cents;
}
}
return cash;
}
void main() {
Money cash;
ifstream mycin("money.txt");
if (mycin.fail())
cout << "Enable to open file";
int x;
mycin >> x;
Money *arr = new Money[x];
for (int i = 0; i < x; i++)
{
mycin >> arr[i].dollars;
mycin >> arr[i].cents;
}
cout << "The values in money.txt are: ";
printMoney(&arr, x);
cash = addMoney(&arr, x);
cout << "These values added are :";
cout << cash.dollars << " Dollars and " << cash.cents << " cents" << endl;
cash = maxMoney(&arr, x);
cout << "Maximum value is :";
cout << cash.dollars << " Dollars and " << cash.cents << " cents" << endl;
}
These functions appear to accept an array of pointers to Money, but you're trying to use them with an array of Money.
I suggest you play with arrays of pointers to simpler types (like int) until you're comfortable with the concept, before you attempt it with Money.
This sounds a lot like homework so I'm not posting a full solution, but I will explain what appears to be the misunderstanding and give you some pointers.
First you declare your data structure as an array of Money structures, e.g. a continuous series of blocks of memory containing the Money struct, the first of which is pointed to by "arr" in your main program.
But then, in the rest of the program (functions) you seem to expect the data structure being used to be an array of Money pointers. See the difference? They're not the same and this will not work as is. You have to be consistent.
Either you're dealing with an array of structs, in which case you pass effectively a single, simple Money* to your functions everywhere (and you dereference with . not ->)
Or you're dealing with an array of pointers, in which case you pass effectively a pointer to a (Money pointer) and you dereference with -> as you've done. But then you also have to allocate each Money struct individually when you're reading them in in the main program. That is to say, allocating memory for the array of pointers does not automatically allocate memory for each Money pointer reference in the array of pointers and so you need to do this for each entry you're reading in.
So, as you should hopefully now realise, there's multiple ways to fix your program.
As per your later comment, given that the function signatures need to stay as-is, I would suggest you work with an array of Money pointers.
Money** arr = new Money*[x]
Then you need to add a line to your loop during reading, to actually make each Money * point to a Money struct:
for (int i = 0; i < x; i++)
{
arr[i] = new Money
...
Finally then, because "arr" is now a pointer to a pointer to Money, you can directly pass it to your functions, so calling them are just for example:
printMoney(arr, x);

C++:array functions

How can I write a program that reads in, a collection of characters from the key board and outputs them to the console. Data is input at random, but output selectively. Only unique characters are displayed at the console. Therefore, every character should be displayed once, no matter how many times it appears in the array.
For example, if an array
Char letterArray[ ] = {B,C,C,X,Y,U,U,U};
The output should be:
B,C,X,Y,U
This is what I have done so far...
char myArray [500];
int count = 0;
int entered = 0;
char num;
while (entered < 8)
{
cout << "\nEnter a Character:";
cin >> num;
bool duplicate = false;
entered++;
for (int i = 0; i < 8; i++)
{
if (myArray[i] == num)
duplicate=true;
}
if (!duplicate)
{
myArray[count] = num;
count++;
} // end if
else
cout << num << " character has already been entered\n\n";
// prints the list of values
cout<<"The final Array Contains:\n";
for (int i = 0; i < count; i++)
{
cout << myArray[i] << " ";
}
}
I believe you could make use of std::set<>.
"Sets are a kind of associative container that stores unique elements <...> elements in a set are always sorted from lower to higher following a specific strict weak ordering criterion set"
Looking through your code...
char myArray [500];
Why 500? You never use more than 8.
char num;
Confusing naming. Most programmers would expect a variable named num to be a numeric type (e.g. int or float).
while (entered < 8)
Consider replacing 8 with a constant (e.g. const int kMaxEntered = 8;).
cin >> num;
cin might be line-buffered; i.e. it does nothing until a whole line is entered.
for (int i = 0; i < 8; i++)
{
if (myArray[i] == num)
duplicate=true;
}
You're accessing uninitialized elements of myArray. Hint: your loop size should not be 8.
Consider using continue; if you find a duplicate.
if (!duplicate)
{
myArray[count] = num;
count++;
} // end if
else
cout << num << " character has already been entered\n\n";
Your // end if comment is incorrect. The if isn't ended until the else is done.
You may want to add braces around the else clause, or remove the braces from the if clause by combining its two lines into the one-line myArray[count++] = num;.
// prints the list of values
cout<<"The final Array Contains:\n";
for (int i = 0; i < count; i++)
{
cout << myArray[i] << " ";
}
You're printing the list every time you get a single input?
Don't use \n in text to cout unless you specifically want to micromanage buffering. Instead, use endl. Also, always put spaces around binary operators like << and don't randomly capitalize words:
cout << "The final array contains:" << endl;
for (int i = 0; i < count; i++)
cout << myArray[i] << " ";
cout << endl;
It would be much more efficient to create an array of size 128 (assuming you are dealing with ASCII) that is initialized with false. Every time you get a character, check its ASCII value and if the array is true on that value you don't print it. After that, update the value of the array on the character value to true. Something like:
bool *seenArray = new bool[128]();
void onkey(char input) {
if(((int)input) < 0) return;
if (!seenArray[(int)input]) {
myArray[count] = input;
count++;
seenArray[(int)input] = true;
}
}