C++ Sorting Function - c++

So I'm trying to get a sort function to work. It should sort by firstname, but if the first names are the same it should sort by last names. I keep getting an error in mySort() that says "unexpected primary-expression before ')' token" on line where inOrder = arr. What's happening to this and how can I fix it? I need to pass my objects into a function in a seperate class. I'll link them in pastebin.
Here's the driver
#include <iostream>
#include <fstream>
#include <string>
#include "phoneEntry.h"
using namespace std;
void mySort(PhoneEntry& arr, int size)
{
bool inOrder = false;
for (int i = size - 1; i > 0 && !inOrder; i--)
{
inOrder = true;
for (int j = 0; j < i; j++)
{
inOrder = arr.alphaGreater(arr&);
}
}
};
int main()
{
const int MAXNUM = 500;
PhoneEntry entry[MAXNUM];
ifstream filezilla;
filezilla.open("phone.txt");
int count = 0;
if(filezilla)
{
while(count < MAXNUM && entry[count].readEntry(filezilla))
{
count++;
}
mySort(entry&, count);
for(int i = 0; i < count; i++)
{
entry[i].writeEntry(cout) << endl;
}
}
else
{
cout << "Four Oh Four - File Not Found" << endl;
}
return 0;
}
Phone Entry Header
Phone Number Header
Sorting Text (http://pastebin.com/HE8Rsmbg)

You want to pass a reference, so the argument has to be defined as call-by-reference in the function definition/declaration, which is already done:
bool PhoneEntry::alphaGreater(const PhoneEntry& item) const;
As you can see, PhoneEntry::alphaGreater takes a constant PhoneEntry reference. So simply use
inOrder = arr.alphaGreater(arr);

There are several things wrong with your code. The first, the one the
compiler is complaining about, is that there is no postfix operator &
in C++. I don't know exactly what you're trying to do with it, or what
you think it means, but it doesn't exist in C++.
The second is that mySort takes a reference to a single PhoneEntry;
you have an array of PhoneEntry, so you'll have to select one to pass
it. Except that the name of the function and the fact that you pass a
count as well suggest that you really want to pass an array.
And I can't figure out what mySort is supposed to be doing. It
certainly doesn't sort anything; in fact, it seems to be fundamentally
an expensive no-op, since it doesn't return anything, it doesn't modify
arr, and it doesn't access or modify any global state.
For the rest, you need more error checking on the input (did the open
succeed, etc.), and you really should be using std::vector, rather
than a C style array. (There are cases where C style arrays are
appropriate, but this isn't one of them.)
More fundamentally, I'd suggest you get a good book and study it. (I'd
recommend Stroustrup's Programming Principles and Practice Using C++.)
You can't write a program in any language without knowing at least the
most basic fundamentals and basic syntax.

you can pass it as pointers also

Related

Is possible that vector::size() returns a wrong value?

In a c++ programming class, we did an exercise and for the circumstances i decided to use the function "size" of std::vector in a for range instead of iterator. Then my teacher tell me that "sometimes" the function size could return a WRONG value so the for loop could go out of range or not be enough.
I have been writing in c++ for almost 2 years in 4 different compilers and i don't this is true.
May the size() function of vector return a wrong value?
EDIT: i agree that this question needs no code because is a theoretical case but i will ilustrate you with the short version:
#include <iostream>
#include <vector>
using namespace std;
typedef vector<uint64_t> telephone_nums;
int main(int argc, const char * argv[]) {
vector<telephone_nums> telephone_mat;
// adding elements to telephone_mat
for (size_t x = 0; x < telephone_mat.size(); ++x){
for (size_t y = 0, len = telephone_mat[x].size(); y < len; ++y){
//modification in the matriz...
}
}
return 0;
}
May the size() function of vector return a wrong value?
Sure. It may return the "wrong" value when the "correct" value that you need isn't the size of the vector.
what my teacher told me is that "size()" "should never be used under no context"
That's quite silly exaggeration.
In my opinion, it would be more correct to say that there are cases where a loop with indices and size() is going to be wrong, despite appearing correct to a beginner. In most cases, while a particular loop would be correct, there is a better alternative that is arguably more readable and less error prone. But there are still some loops where indices and size() is superior, although such cases may not be common.
A typical example of a way a beginner unknowingly writes a program that has undefined behaviour, even though the program looks correct in the eyes of a beginner:
for (size_t x = 1; x <= telephone_mat.size(); ++x)
Another typical beginner mistake:
for (size_t i = 0; i < vec.size(); ++i)
if (condition)
vec.erase(vec.begin() + i);
An example of a potentially simpler way to write your loops (alghouth whether this applies depends on how the vectors are modified):
for (auto& nums : telephone_mat){
for (auto& element : nums){
//modification in the matriz...
}
}

Using Arrays in functions in C++

I am a student who is doing an assignment for C++ and I have encountered something I am very unfamiliar with. I have an int array with no size but a list of numbers. After it's creation, there is a function call inside a function that has that array as a parameter with an index in it.
For example:
for (int x = 0; x < CAPACITY, x++)
functionCall(array[x]);
Now I am supposed to create a function so the call can work. However when I make my function:
void functionCall(int array[]);
It does not work because it cannot turn an int to an int[].
I guess my question is, how am I supposed to get that list of numbers created originally by the array if I have to call it in my function as if it isn't an array.
Right now if I just put as an int but not an array like it wants me to do it just gives me the number 5 but not any of the numbers in the array. For example:
void functionCall(int array);
Sincere thank you for anything and I apologize if this sounds confusing.
functionCall(array[x]);
This passes the xth element in the array to the function, so a single int.
array[2] = 5;
functionCall(array[2]); // This is the same as functionCall(5);
So in the function, you get the current element of the array. Not the array itself.
You cannot get the list inside the function, because you only give a single element of that list each time you call it.
Taking a wild guess, I suspect you are looking for something like the MCVE below:
#include <iostream>
void functionCall(int v) {
std::cout << v << " ";
}
void func(int array[], size_t CAPACITY) {
for (size_t x = 0; x < CAPACITY; x++)
functionCall(array[x]);
}
int main() {
int list[] = { 1,2,3,4,3,0, 42 };
func(list, std::distance(std::begin(list), std::end(list)));
return 0;
}

C++ Calling Vectors from Function to Main

I'm trying read a large amount of values into a vector in a specific function and then calling it into the main to get the average. My readInput works perfectly. But I believe
my main function returns 0 when I cout << values.size();. Why is this? What can I do to change that?
using namespace std;
//function prototype
int readInput(vector<int> vect);
int main()
{
vector<int> values;
int sum, avg;
sum = readInput(values);
//cout << sum;
avg = sum / values.size();
cout << avg;
return 0;
}
int readInput(vector<int> vect)
{
int count;
int total = 0;
ifstream inputFile("TopicFin.txt"); //open file
if(!inputFile)
{
return 0; // if file is not found, return 0
}
while(inputFile >> count) //read file
vect.push_back(count); //add to file
for (int count = 0; count < vect.size(); count++)
total+=vect[count]; //sum data in vector
return total;
}
You are not passing your vector by reference, so your function only stores the values in a copy of your vector from main.
int readInput(vector<int>& vect);
this tells your program to pass the the vector by reference meaning anything modified in the function directly modifies your vector in main. If you're new to this stuff check out this post explaining the difference between reference and copy.
You need to pass the vector as a reference or as a pointer. The function just creates a copy of the vector currently passed by value, and manipulates that.
Change the function signature to . . .
int readInput(vector<int>& vect)
Or (perhaps more weirdly for this example) . ..
int readInput(vector<int> *vect)
also changing the function call to
sum = readInput(&values);
Although others have already mentioned the possibility of passing the vector by reference, that is not what I think I'd do in this case. I think I'd just return the vector from the function. I'd also pass the file name to the function:
std::vector<int> values = readInput("TopicFin.txt");
At least to me, this seems to reflect the intent far better. Maybe I'm just a little slow, but it doesn't seem at all obvious from the name that the return value from readInput would be the sum of the values it read.
While returning a vector could theoretically cause an efficiency problem with a compiler that supported neither move construction nor return value optimization, any such compiler is pretty much guaranteed to be so ancient that you really want to avoid it for other reasons anyway.
As far as reading the data into the vector goes, I'd use a pair of istream_iterators:
std::vector<int> data{std::istream_iterator<int>(infile),
std::istream_iterator<int>()};
Of course, given how simple this is, I'd tend to wonder whether it's worth having a separate function like readInput at all.
To sum the values, I'd use std::accumulate:
int total = std::accumulate(data.begin(), data.end(), 0);

perform a function on all the objects at once (without a for loop)

Is it possible to perform a function on all the objects of a class at once without using a for loop? For example in the following code:
#include <iostream>
using namespace std;
class CTest {
public:
int X;
void clear() {
X = 0;
}
};
int main() {
CTest A[100];
for (int i = 0; i < 100; ++i) {
A[i].X = 10;
}
for (int i = 0; i < 100; ++i) {
A[i].clear();
}
return 0;
}
is it possible to do something like A.X = 10 to initialize all the objects at once or for example use A.clear() to clear all the objects at once? I think it is possible to use <vector> for this purpose but is there any other way?
You can't. You need to perform some operation N times? Well, at best, that's a linear time operation. You are never going to get constant time out of it, ever. It just doesn't make sense to expect anything else.
You can use std::for_each from STL algorithm header with arrays. Instead of iterators begin()/end() you can pass CTest* pointers 'array' and 'array + size' or better std::begin(A)/std::end(A). The only problem is calling a non static member such as clear(). If you have C++11 use lambdas or else check out STL functional or boost bind.
//C++11 code:
#include <algorithm>
std::for_each(std::begin(A),std::end(A),[](CTest& ct){ct.X = 10;});
std::for_each(std::begin(A),std::end(A),[](CTest& ct){ct.clear();});
edited: use begin/end for arrays instead of pointer arithmetics

C++ for each With a Pointer

I am trying to use a pointer to an array inside of a for each loop in C++. The code below won't work because the "for each statement cannot operate on variables of type 'int *'". I'd prefer to use the new operator so that the array is on the heap and not the stack, but I just can't seem to figure out the syntax here. Any suggestions?
#include <iostream>
using namespace std;
int main() {
int total = 0;
int* array = new int[6];
array[0] = 10; array[1] = 20; array[2] = 30;
array[3] = 40; array[4] = 50; array[5] = 60;
for each(int i in array) {
total += i;
}
cout << total << endl;
}
That for each thing you are using is a Visual C++ extension that's not even recommended by some microsoft employees (I know I've heard STL say bad things about it, I can't remember where).
There are other options, like std::for_each, and range-based for from C++11 (though I don't think Visual C++ supports that yet). However, that's not what you should be using here. You should be using std::accumulate, because this is the job that it was made for:
total = std::accumulate(array, array + 6, 0);
If you're really just interested in how to use this Microsoft for each construct, well, I'm pretty sure you can't if you just have a pointer. You should use a std::vector instead. You should be doing that anyway.
C++0x introduced a ranged-based for loops, which work equal to foreach in other languages. The syntax for them is something like this:
int arr[5]={1,2,3,4,5};
for( int & tmp : arr )
{
//do something
}
These loops work for C-style arrays, initializer lists, and any type that has begin() and end() functions defined for it that return iterators.
I strongly believe that int * doesn't have begin() and end() functions for them that return iterators, because it's just a raw pointer. I also believe that other foreach-equivalents such as foreach in Qt, or what you've posted, work the same way, so you can't use them like this. msdn says that it works for collections:
for each (type identifier in expression) {
statements
}
expression:
A managed array expression or collection. The compiler must be able
to convert the collection element from Object to the identifier type.
expression evaluates to a type that implements IEnumerable, IEnumerable,
or a type that defines a GetEnumerator method. In the
latter case, GetEnumerator should either return a type that implements
IEnumerator or declares all the methods defined in IEnumerator.
Once again, you have a raw pointer, so it will not work.
you can always use for loop like this:
for (int i = 0; i < 6;i++)
{
total += array[i];
}
Although, answer for using "for each" using "gcnew" is already being given so I am omitting that. As an alternative, you can also use vectors as follows:
#include <iostream>
#include <vector>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int total = 0;
vector<int> myarray;
myarray.push_back(10);
myarray.push_back(20);
myarray.push_back(30);
myarray.push_back(40);
myarray.push_back(50);
myarray.push_back(60);
for each(int i in myarray) {
total += i;
}
cout << total << endl;
return 0;
}
Hope this will help...
The only way I can think about is iterating over array of reference types especially if you want your storage on the heap
Here Microsoft shows you how to do so
But for your case, the simplest alternative (if you want your array on the heap) would be as follows:-
array<int>^ arr = gcnew array<int>{10, 20, 30, 40. 50, 60};
int total = 0;
for each (int i in arr){
total+=i;
}
gcnew creates an instance of a managed type (reference or value type) on the garbage collected heap. The result of the evaluation of a gcnew expression is a handle (^) to the type being created.
You have to use an standard library collection such as std::vector or std::arrayto use for each.
Please note that this codee I not standard C++, therefore not portable, because for each is a Visual C++ extension. I recommend to use std::for_each or C++11 auto ranged loops.
VC++ is not different from ISO/ANSI C++. Anybody who tells you that it is, is wrong. Now, to answer your question of the for each statement. There is no such statement in the ISO C++ specification. Microsoft supports the 'foreach' statement in C#, as part of the .Net framework. As a result, there might be a chance that this is supported in Visual Studio, although I would recommend not using it.
Like the user shubhansh answered a few replies back, try using a vector. However, I'm guessing you would like to use a generic size, rather than hard-coding it in. The following for loop would help you in this regard:
for(vector<int>::size_type i =0; i<myarray.size();i++)
{
total+=1;
}
This is the perfect way to iterate through a vector, as defined by the ISO standard.
Hope this helps you in your development.
Cheers!