Function to sort array of pointers to an array?

Just as the title suggests. I am absolutely clueless and cannot not get anything to work in my favor. I've been trying for a few hours.

I am supposed to make dynamic parallel arrays when reading the information from my file. I've done that. But the next step is to create a function to sort an array of pointers to the TradeSymbol array. I am to sort only this array of pointers and display all the sorted trading symbols, 3 to a line, using this array of sorted pointers.

The function void ArrSort (string * [], int);
is just based on an example that I saw. However it doesn't even work for me because the program throws an unhandled exception. I do not where to go from here.

Here is also the text file that I am reading from. It might help?

1
2
3
4
5
6
5
MCD McDonald's Corporation# 35 99.25
HD The Home Depot, Inc.# 31 115.54
F Ford Motor Co.# 288 16.49
WMT Wal-Mart Stores Inc.# 10 83.33
BA The Boeing Company# 24 151.46 


So basically I need to somehow use my dynamic array that stores the Trade Symbol (MCD, HD, F, etc)...to create another array I think that will store the alphabetically sorted elements and then display them? I think that's how I am supposed to interpret the directions. Please help! Thanks!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;

//function prototype
void ArrSort (string * [], int);

int main ()
{
	string filename;
	fstream inFile;
	int numOfStocks = 0;
	string *TradeSymbol = nullptr, *CompanyName = nullptr;
	int *numOfShares = nullptr;
	double *CurrentPrice = nullptr;
	char delimiter1 = ' ';
	char delimiter2 = '#';

	cout << "User please enter the name of the file that you would like to read." << endl;
	cout << "Example Format: Products.cpp" << endl;
	cout << "\nEnter: ";
	cin >> filename;

	inFile.open(filename);

	if (inFile.fail())
	{
		cout << "\nFile not found!" << endl;
		exit(-1);
	}
	else 
	{
		cout << "\nFile has opened successfully!" << endl;
		while (!inFile.eof())
	{
		inFile >> numOfStocks;
		break;
	}
	}
		cout << "Number of different stocks found in file: " << numOfStocks;

	TradeSymbol = new string [numOfStocks], CompanyName = new string [numOfStocks]; //dynamically allocated memory for parallel arrays
	numOfShares = new int [numOfStocks], CurrentPrice = new double [numOfStocks];

	for (int x = 0; x < numOfStocks || !inFile.eof(); x++)
	{
		getline (inFile, *(TradeSymbol + x), delimiter1);
		getline (inFile, *(CompanyName + x), delimiter2);
		inFile >> *(numOfShares + x);
		inFile >> *(CurrentPrice + x);
	}

	inFile.close();

	/*for (int x = 0; x < numOfStocks; x++)
	{
		cout << TradeSymbol[x] << endl;
		cout << *(CompanyName + x) << endl;
		cout << *(numOfShares + x) << endl;
		cout << *(CurrentPrice + x) << endl;
		cout << endl;
	}*/

	string *SortedArray = nullptr;
	SortedArray = new string [numOfStocks]; //dynamically create new array of pointers

	for (int count = 0; count < numOfStocks; count++)
		SortedArray[count] = *(TradeSymbol + count);

	ArrSort(TradeSymbol, numOfStocks);

	system("pause");
	return 0;
}

void ArrSort (string *arr, int elements)
{
	int StartScan, minIndex;
	string *minElem;

	for (StartScan = 0; StartScan < (elements - 1); StartScan++)
	{
		minIndex = StartScan;
		*minElem = arr[StartScan];

		for (int index = StartScan + 1; index < elements; index++)
		{
			if (arr[index] < *minElem)
			{
				*minElem = arr[index];
				minIndex = index;
			}
		}

		arr[minIndex] = arr[StartScan];
		arr[StartScan] = *minElem;
	}

	for (int count = 0; count < elements; count++)
	{
		cout << arr[count] << ' '; 

		if (count == 3)
			cout << endl;
	}

}
Last edited on
Normally you would put TradeSymbol, CompanyName, etc. in a struct and then make an array of this struct.

If you insist to have separated array that are related (i.e. the same order) you need a level of indirection. You need another array for the indexes.

The indirect access would look like this: array[index_array[index]]

In your sort function you would compare the passed array [indirect], but instead of changing the content of the array you would change the content of the index_array.

[EDIT]
The program crash due to line 81. It must not be a pointer.
Last edited on
1
2
3
4
5
6
7
for (int x = 0; x < numOfStocks || !inFile.eof(); x++)
{
	getline (inFile, *(TradeSymbol + x), delimiter1);
	getline (inFile, *(CompanyName + x), delimiter2);
	inFile >> *(numOfShares + x);
	inFile >> *(CurrentPrice + x);
}

Before you worry about sorting your data you should read it properly first. You program crashes when x reaches 5 and you access your array out of bounds.

I would read the file like this:
1
2
3
4
5
6
7
8
9
int x = 0;
while(inFile && x < numOfStocks)
{
    getline(inFile, TradeSymbol[x], delimiter1);
    getline(inFile, CompanyName[x], delimiter2);
    inFile >> numOfShares[x];
    inFile >> CurrentPrice[x];
    x++;
}


What kind of crappy C++ course do you do? Dynamic arrays are sth. for library writers, but not so much for application programmers.
Normally in modern C++ you would use a struct and a vector for this kind of task.

First things first, you have fix the way you're reading the stocks. Each trade symbol currently starts with the newline that comes before it, so you have to skip that before reading the tradeSymbol:
inFile.ignore(100000, '\n'); // skip the previous newline
This will skip up to 100,000 characters. To be really correct, you want to tell it to skip until you reach a newline, no matter what:
1
2
3
#include <limits>
...
inFile.ignore(numeric_limits<streamsize>::max(), '\n');  // skip the previous newline 


Your SortedArray is an array of strings, not an array of pointers. Lines 66 & 67 should be
1
2
    string **SortedArray = nullptr;
    SortedArray = new string*[numOfStocks];      //dynamically create new array of pointers 

Then line 70 should fill it with the addresses of the strings in TradeSymbol:
SortedArray[count] = TradeSymbol + count;

Line 72 is passing the wrong array to ArrSort. It should pass SortedArray

Line 78, ArrSort should be defined the way it's declared at line 8

I wouldn't keep track of both minElem and minIndex because it's too easy to get them out of sync. Just track minIndex and the minElement is *arr[minIndex]. To handle the swap at lines 97 & 98, just use std::swap()

Other suggestions:
Lines 36-40 are equivalent to infile >> numOfStocks;
Line 47: Since there's no provision for handling less than numOfStocks in the file, I'd just change this to for (int x = 0; x < numOfStocks; x++) {
You could check for errors at the end of the for loop.
Lines 44 & 45: it's bad form to use the comma operator to separate statements.
Ok so I got the problem fixed when reading the stocks. It now doesn't read the \n at the beginning of the trade symbol. Updated Code Below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;

//function prototype
void ArrSort(string *, int);
int findStock(string *, int);

int main()
{
	string filename;
	fstream inFile;
	int numOfStocks = 0;
	string *TradeSymbol = nullptr, *CompanyName = nullptr;
	int *numOfShares = nullptr;
	double *CurrentPrice = nullptr;
	char delimiter1 = ' ';
	char delimiter2 = '#';
	int index = 0;

	cout << "User please enter the name of the file that you would like to read." << endl;
	cout << "Example Format: Products.cpp" << endl;
	cout << "\nEnter: ";
	cin >> filename;

	inFile.open(filename);

	if (inFile.fail())
	{
		cout << "\nFile not found!" << endl;
		exit(-1);
	}
	else
	{
		cout << "\nFile has opened successfully!" << endl;
			inFile >> numOfStocks; //reading the first integer at top of text file
	}
	cout << "Number of different stocks found in file: " << numOfStocks << endl;

	TradeSymbol = new string[numOfStocks], CompanyName = new string[numOfStocks]; //dynamically allocated memory for parallel arrays
	numOfShares = new int[numOfStocks], CurrentPrice = new double[numOfStocks];

	for ( int x = 0; x < numOfStocks; x++)
	{
		inFile.ignore(100000, '\n'); // skip the previous newline 
		getline (inFile, TradeSymbol[x], delimiter1);
		getline(inFile, CompanyName[x], delimiter2);
		inFile >> numOfShares[x];
		inFile >> CurrentPrice[x];
	}

	inFile.close();

	/*for (int x = 0; x < numOfStocks; x++)
	{
	cout << TradeSymbol[x] << endl;
	cout << *(CompanyName + x) << endl;
	cout << *(numOfShares + x) << endl;
	cout << *(CurrentPrice + x) << endl;
	cout << endl;
	}*/

	string *SortedArray = nullptr;
	SortedArray = new string [numOfStocks]; //dynamically create new array of pointers

	for (int count = 0; count < numOfStocks; count++)
	SortedArray[count] = *(TradeSymbol + count);

	ArrSort(SortedArray, numOfStocks);

	index = findStock(TradeSymbol, numOfStocks);

	cout << "\nCompany Name: " << right << setw(42) << CompanyName[index] << endl;
	cout << "Number of Shares: " << right << setw(38) << numOfShares[index] << endl;
	cout << "Current Price (per share): " << right << setw(29) << CurrentPrice[index] << endl;
	double totalValue = *(numOfShares + index) * *(CurrentPrice + index);
	cout << fixed << setprecision(2);
	cout << "Current Value: " << right << setw(41) << totalValue << endl;

	system("pause");
	return 0;
}

void ArrSort (string *arr, int elements)
{
	cout << "\nIn function ArrSort now!" << endl;
	cout << "Contents of passed array." << endl;
	
	for (int x = 0; x < elements; x++) 
		cout << arr[x] << ' ';

	int StartScan, minIndex;
	string *minElem = nullptr;

	for (StartScan = 0; StartScan < elements; StartScan++)
	{
		minIndex = StartScan;
		*minElem = arr[StartScan];

		for (int index = StartScan; index < elements; index++)
		{
			if (arr[index] < *minElem)
			{
				*minElem = arr[index];
				minIndex = index;
			}
		}

		arr[minIndex] = arr[StartScan];
		arr[StartScan] = *minElem;
	}

	for (int count = 0; count < elements; count++)
	{
		cout << arr[count] << ' '; 

		if (count == 3)
			cout << endl;
	}

}

int findStock(string *TradeName, int index)
{
	string symbol;
	cout << endl;
	cout << "Enter the symbol: ";
	cin >> symbol;
	bool found = false;

	for (int i = 0; i < index; i++)
	{
		if (symbol == TradeName[i])
		{						
			found = true;
			return i;
		}
	}

	if (found == false)
	{
		cout << "Symbol not found!" << endl;
		exit(-2); //error message, exit with an error code of -2
	}
}


I also added a function, findStock that searches for the stock information by user input entering the trade symbol. It returns the index of the found trade symbol and then I display that information back in main.

I still need help with the function that sorts the array. I still do not understand. I tried your guys' input but I am still having problems. I do not even fully understand the function that I created for that purpose. My instructor told us to read an example out of the book. That function is based on that example but it makes no sense to me why the book shows to create string *minElem. I also do not understand why the for loops in the sorting function would have the following conditions.

for (StartScan = 0; StartScan < (elements - 1); StartScan++)

I do not know why the bounds would have StartScan go from 0 to 3. ^^^

and

for (int index = StartScan + 1; index < elements; index++)

I do not understand this part either. ^^^^^

Can someone create a function that sorts the Trade Symbol alphabetically? Please! Also explain each step through comments in the code! Thanks.

edit:
As for the vector, array, structs suggestions, I would agree that it would probably be more proper do it that way. However I will not get credit. I have to explicitly use dynamic parallel arrays for this.
Last edited on
Judging from this: ArrSort (string * [], int);, I think I know what they want:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
...
	string **SortedArray = new string *[numOfStocks]; // Create an array of pointer. Note the additinal *

	for (int count = 0; count < numOfStocks; count++)
	SortedArray[count] = TradeSymbol + count; // The pointers are copied. Note: NO dereference

	ArrSort(SortedArray, numOfStocks);
...

ArrSort (string * arr[], int elements) // Note: The same as string **arr
{
	cout << "\nIn function ArrSort now!" << endl;
	cout << "Contents of passed array." << endl;
	
	for (int x = 0; x < elements; x++) 
		cout << *(arr[x]) << ' '; // Note: dereference here

	int StartScan, minIndex;
	string *minElem = nullptr;

	for (StartScan = 0; StartScan < (elements - 1); StartScan++) // Note: (elements - 1) because of the comparison (StartScan + 1)
	{
		minIndex = StartScan;
		minElem = arr[StartScan]; // Note: NO dereference

		for (int index = StartScan + 1; index < elements; index++) // All following elements will be compared
		{
			if (*(arr[index]) < *minElem) // Note: Additional dereference for arr[index]
			{
				minElem = arr[index]; // Note: NO dereference
				minIndex = index;
			}
		}

		arr[minIndex] = arr[StartScan]; // This swaps the current element to the found minimum. Note: NO dereference
		arr[StartScan] = minElem; // This swaps the found minium to the current element. Note: NO dereference
	}

	for (int count = 0; count < elements; count++)
	{
		cout << *(arr[count]) << ' ';  // Note: dereference here

		if (count == 3)
			cout << endl;
	}

}
Not tested!

I do not know why the bounds would have StartScan go from 0 to 3. ^^^
The algorithm compares all elements with the following (i.e. + 1...) elements. Since we have + 1 in the comparison, we need - 1 for the number of elements to compare.
I do not understand this part either. ^^^^^
The current element will be compared with all following [+ 1...] elements whether there is a smaller one. If so: Assign the smaller element to the current.
The algorithm compares all elements with the following (i.e. + 1...) elements.

No, it's a little different. The idea of the algorithm is to find the smallest value and put it in position 0 by swapping the smallest value with the one in position 0. Then it finds the smallest value from positions 1 to N-1 and puts it in position 1 by swapping. Then it finds the smallest in positions 2 to N-1, etc.

Topic archived. No new replies allowed.