I have a huge array of ints that I need to sort. The catch here is that each entry in the list has a number of other associated elements in it that need to follow that int around as it gets sorted. I've kind of solved this problem by changing the sorting to sort doubles instead of ints. I've tagged each number before it was sorted with a fractional part denoting that value's original location before the sort, thus allowing me to reference it's associated data and allowing me to efficiently rebuild the sorted list with all the associated elements.
My problem is that I want to sort the double values by ints using the function stable_sort().
I'm referring to this web page: http://www.cplusplus.com/reference/algorithm/stable_sort/
However, since I'm a new programmer, i don't quite understand how they managed to get the sort by ints to work. What exactly am i supposed to put into that third argument to make the function work? (i know i can just copy and paste it and make it work, but i want to learn and understand this too).
Thanks,
-Faken
Edit: Please note that I'm a new programmer who has had no formal programming training. I'm learning as i go so please keep your explanations as simple and as rudimentary as possible.
In short, please treat me as if i have never seen c++ code before.
Since you say you're not familiar with vectors (you really should learn STL containers ASAP, though), I assume you're playing with arrays. Something along these lines:
int a[] = { 3, 1, 2 };
std::stable_sort(&a[0], &a[3]);
The third optional argument f of stable_sort is a function object - that is, anything which can be called like a function by following it with parentheses - f(a, b). A function (or rather a pointer to one) is a function object; other kinds include classes with overloaded operator(), but for your purposes a plain function would probably do.
Now you have your data type with int field on which you want to sort, and some additional data:
struct foo {
int n;
// data
...
};
foo a[] = { ... };
To sort this (or anything, really), stable_sort needs to have some way of comparing any two elements to see which one is greater. By default it simply uses operator < to compare; if the element type supports it directly, that is. Obviously, int does; it is also possible to overload operator< for your struct, and it will be picked up as well, but you asked about a different approach.
This is what the third argument is for - when it is provided, stable_sort calls it every time it needs to make a comparison, passing two elements as the arguments to the call. The called function (or function object, in general) must return true if first argument is less than second for the purpose of sorting, or false if it is greater or equal - in other words, it must work like operator < itself does (except that you define the way you want things to be compared). For foo, you just want to compare n, and leave the rest alone. So:
bool compare_foo_n(const foo& l, const foo& r) {
return l.n < r.n;
}
And now you use it by passing the pointer to this function (represented simply by its name) to stable_sort:
std::stable_sort(&a[0], &a[3], compare_foo_n);
You need to pass the comparison function. Something like this:
bool intCompare(double first, double second)
{
return static_cast<int>(first) < static_cast<int>(second);
}
int main()
{
std::vector<double> v;
v.push_back(1.4);
v.push_back(1.3);
v.push_back(2.1);
v.push_back(1.5);
std::stable_sort(v.begin(), v.end(), intCompare);
return 0;
}
Inside the sort algorithm, to compare the values the comparison function passed by you is used. If you have a more complex data structure and want to sort on a particular attribute of the data structure then you can use this user-defined function to compare the values.
I believe you are talking about this function:
bool compare_as_ints (double i,double j)
{
return (int(i)<int(j));
}
And the function call:
stable_sort (myvector.begin(), myvector.end(), compare_as_ints);
The function compare_as_ints is a normal function but this is being passed to the stable_sort as a function pointer. i.e., the address of the function is being passed which would be used by stable_sort internally to compare the values.
Look at this function pointer tutorial if you are unclear about this.
Related
I have been given an assignment and I'm struggling to figure out how I'm supposed to implement it.
I've pasted the parts of the assignment that puzzled me below
Write a deque class to hold a list of integers which is implemented internally with a circular array The size of the array can be passed in the constructor, or you can decide on a default value. The class will maintain data members which hold the index position of the head and tail of the list
The class should have member functions:
• bool isEmpty();
• bool isFull();
• bool insertFront(int)
• bool removeFront(int&)
• bool insertBack(int)
• bool removeBack(int&)
prints all items in the array by removing them one at a time from the front.
So I've written all my function and have the deque working, the things I struggled with are:
"The size of the array can be passed in the constructor"
so to accomplish this I declared a pointer called array in my class and then array = new int[size] in my constructor, is this the only way to do this, I'm happy enough it works but not sure if there's a better solution. I was thinking vector, but think that would have been too easy. I also could have declared a const for the size and initialized the array in my class, but again to easy.
The bool removeFront(int&) and bool removeBack(int&) functions really confused me, what reference am I supposed to be passing in? also the return type is bool, but later in the assignment I'm asked to "prints all items in the array by removing them one at a time from the front" how can I do this with a return type of bool, rather than int?
I have changed my functions to remove the reference and have a return type of int to get the code to work, but would like to know how to implement it the way the assignment asks for?
Based on the requirements listed, the intent of the function arguments is unambiguous. Here is why:
Take
bool removeFront(int& );
This not only removes an element at the front of the buffer and stores it in the argument being passed by reference. But, the function returns a "bool" indicating whether it was able to successfully remove or not.
An example usage would be like this:
int elem;
while (removeFront(elem)) {
printf("element : %d ", elem);
}
Here the variable "elem" is passed in by reference. Hence, upon a successful execution of removeFront() you will have elem filled in with the value of the element just removed.
The same reasoning applies to other similar methods. Please go back to using a reference mode parameter as given in the original specification.
The int& argument is not for a count of elements as other answer suggested.
Answer to Part-1:
Your solution is pretty decent. You could also
std::array for storing the elements. There is an advanced trick to do in-place allocation of a variable length array - but, that is beyond the scope of this question.
"The size of the array can be passed in the constructor"
Unless you were told otherwise, use a vector. Using old school arrays is just asking for trouble.
The "bool removeFront(int&)" and "bool removeBack(int&)" functions really confused me, what reference am I supposed to be passing in?
It's a matter of personal preference, but passing in a single int as a reference might be rather unnecessary, what the functions do (if I understood your problem correctly) is remove the element of the array that is at the position of the int you are passing as argument. If said element is correctly removed, you might want to return a true value, otherwise return a false one.
EDIT: Upon re reading the post, what the functions might do is simply remove the 'int' amount of elements from the front or back of the array. Return values should work as previously stated
but later in the assignment I'm asked to "prints all items in the array by removing them one at a time from the front" how can I do this with a return type of bool, rather than int?
The return type of the function has nothing to do with this (unless you were asked to do it recursively). Simply do a loop that starts at the beginning of the array and outputs its content, deletes that same element, then jumps to the next and repeats the process until its out of elements. Again, this is much safer to do with any of the STL containers since you can use iterators.
I'm currently writing a function which will take a variable number of arguments. I pass the number of arguments into the function and then will iterate through the arguments list.
Each of the passed arguments should be an integer. I will be adding this integer to a vector of integers which will be used later.
I would like to make sure that some joker doesn't attempt to pass this function something other then an integer in the future. I recognize that I can check the current argument from va_arg to ensure it is not NULL and I can use something like isanum(va_arg()) to determine if it is a valid integer. I suppose I could even check the sizeof(va_arg) and compare it against the sizeof(int) and ensure they are equal.
Are there any other checks which I can run to verify I have been passed a valid integer?
Thanks in advance for assistance
There is no sensible way you can do this. Variable-argument functions work by concatenating all the raw binary representations of the arguments into one big chunk of data on the stack. So it relies on both the caller and the callee agreeing on what the number and type of arguments are (otherwise you'll end up reading e.g. an int as if it were a float).
As to your specific ideas:
va_arg() is a macro that simply interprets some number of bytes of the raw stack data as whatever type you specify. So invoking sizeof() on it will simply tell you the size of the data type you asked for.
In general, there are no patterns of raw binary data that form an invalid integer. So the hypothetical isanum() could not work.
Each of the passed arguments should be an integer.
If you have a C++0x compiler, I suggest an initializer_list<int> instead of varargs:
#include <initializer_list>
void foo(std::initializer_list<int> numbers)
{
my_vector.insert(my_vector.end(), numbers.begin(), numbers.end());
}
int main()
{
foo( {2, 3, 5, 7} );
}
This is straight-forward and completely type-safe.
Each of the passed arguments should be
an integer. I will be adding this
integer to a vector of integers which
will be used later.
Then why not just accept a vector of integers?
void AddIntegers(const std::vector<int>& vec);
You can then always concatenate vectors together using iterators.
Or make an interface like this:
void AddInteger(int newInt);
Or even this:
void AddIntegers(const int* integers, unsigned int numIntegers);
template <unsigned int Size>
void AddIntegers(int (&integers)[Size])
{
AddIntegers(integers, Size);
}
int main()
{
int i[] = {1, 2, 3, 4};
AddIntegers(i);
}
These will work if you need to work with a C++03 compiler. If you have a C++0x compiler, there are far superior solutions available.
Variable arguments are unsafe by design. You cannot check that the user passed correct type in any way. C++0x comes to the rescue with variadic templates but not many compilers support it nowadays (only GCC afaik).
Unfortunately, there really isn't a way to do this. Functions like printf() can easily be fowled up by passing invalid or the wrong number of arguments.
In C++, this is an advanced feature that requires the programming using such code to ensure the correct arguments are passed.
You can't do any sort of type checking with varargs. I'd suggest using an iterator range instead (like standard library functions) or possibly a std::vector<int>. This way the types can't be subverted.
Since you are using C++, how about overloading some operator and pass the arguments one-by-one? For example
class MyFunction {
std::vector<int> param;
public:
MyFunction() { /* some initialisation? */ }
MyFunction &operator,(int eatMe) {
param.push_back(eatMe);
return *this;
}
~MyFunction() {
//the implementation of your function goes here
}
}
Then you can call it like this:
MyFunction(),2,3,5,7;
Note, the use of comma operator may look scary, but it is actually very helpful in this case. It is the lowest possible, left-associative operator.
If your function takes some extra parameters, not only the unknown-length of int-s, you can pass them in the constructor.
If someone uses something else than int, the default comma operator will be used (evaluate left side, discard, evaluate right side). If you don't like that - pick a different operator, e.g. stream-like << or boost-like %.
If you are restricted to C++03 and all your arguments should be integers, one solution would be to simply hide the variable argument function (in a 'detail' namespace for example) and make a series of overloaded functions for 1 to N amount of arguments. Those functions would be simple inline functions that forward the call to the vararg version of the real function. This way, you have one real implementation, no run-time overhead, and you expose a type-safe interface to the caller (and the caller can always use the vararg version if he needs more than N arguments).
Boost.PP can also help to generate these types of repetitive patterns.
Of course, if you have some level of C++0x support, than the problem can be solved in many ways, including initializer_list or variadic templates.
Just to illustrate my comment on CygnusX1's answer, you could do it like:
class MyFunction {
std::vector<int> params;
public:
MyFunction() { (*this)(); }
MyFunction(int eatMe) { (*this)(eatMe); }
MyFunction& operator()(int eatMe) {
params.push_back(eatMe);
return *this;
}
void operator()() {
// use params to do something interesting
}
}
MyFunction(2)(3)(5)(7)();
I have to write a method within already-written code that passes me an array directly. However once inside my method that array has become a pointer to the first object in the array. So now I have done some calculations and want to sort the array. But since it's now not considered an array, I can't perform the sort() function.
What's the best way to sort an array when I only have the pointer to work with?
You either need to know the number of elements in the array, passed as a separate parameter or have a pointer to one past the last element.
void my_sort(int* p, unsigned n) {
std::sort(p, p+n);
}
or
void my_sort2(int* p, int* p_end) {
std::sort(p, p_end);
}
and you would call them
int a[] = { 3, 1, 2 };
my_sort(a, sizeof a / sizeof a[0]); // or 3...
my_sort2(a, &a[2] + 1); // one past the last element! i.e. a+3
In c there is essentially no difference between an "array" and a "pointer to the first object in the array". Arrays are referred to using their base pointer, that is, pointer to first object.
Technically precise explanation at Array base pointer and its address are same. Why?
So, just sort the array as you would anywhere else. Got an example sort or sample code in mind or is that sufficient?
Sort it exactly as you would sort it before you passed it in. If your sort() function requires a length, then pass the length as an additional parameter.
The best would be if you could start using std::array from C++11 on:
http://en.cppreference.com/w/cpp/container/array
This way, you would also have the size known and accessible by the corresponding size method. You could also consider other std container types rather than raw array. In general, it is better to avoid raw arrays as much as possible.
Failing that, you would need to know the size of the array either through function parameter, or other means like class member variable if it is happening inside a class, and so on.
Then, you could use different type of sorting algorithms based on your complexity desire; let it be quick sort, bubble sort, heap sort, stable sort, etc... it depends on what kind of data, the array represents, etc.
One sorting algorithm is to use std::sort. Therefore, you would be writing something like this:
std::sort (mystdarray.begin(), mystdarray.end());
or
std::sort (myrawarray, myrawarray+size);
I'm currently writing a function which will take a variable number of arguments. I pass the number of arguments into the function and then will iterate through the arguments list.
Each of the passed arguments should be an integer. I will be adding this integer to a vector of integers which will be used later.
I would like to make sure that some joker doesn't attempt to pass this function something other then an integer in the future. I recognize that I can check the current argument from va_arg to ensure it is not NULL and I can use something like isanum(va_arg()) to determine if it is a valid integer. I suppose I could even check the sizeof(va_arg) and compare it against the sizeof(int) and ensure they are equal.
Are there any other checks which I can run to verify I have been passed a valid integer?
Thanks in advance for assistance
There is no sensible way you can do this. Variable-argument functions work by concatenating all the raw binary representations of the arguments into one big chunk of data on the stack. So it relies on both the caller and the callee agreeing on what the number and type of arguments are (otherwise you'll end up reading e.g. an int as if it were a float).
As to your specific ideas:
va_arg() is a macro that simply interprets some number of bytes of the raw stack data as whatever type you specify. So invoking sizeof() on it will simply tell you the size of the data type you asked for.
In general, there are no patterns of raw binary data that form an invalid integer. So the hypothetical isanum() could not work.
Each of the passed arguments should be an integer.
If you have a C++0x compiler, I suggest an initializer_list<int> instead of varargs:
#include <initializer_list>
void foo(std::initializer_list<int> numbers)
{
my_vector.insert(my_vector.end(), numbers.begin(), numbers.end());
}
int main()
{
foo( {2, 3, 5, 7} );
}
This is straight-forward and completely type-safe.
Each of the passed arguments should be
an integer. I will be adding this
integer to a vector of integers which
will be used later.
Then why not just accept a vector of integers?
void AddIntegers(const std::vector<int>& vec);
You can then always concatenate vectors together using iterators.
Or make an interface like this:
void AddInteger(int newInt);
Or even this:
void AddIntegers(const int* integers, unsigned int numIntegers);
template <unsigned int Size>
void AddIntegers(int (&integers)[Size])
{
AddIntegers(integers, Size);
}
int main()
{
int i[] = {1, 2, 3, 4};
AddIntegers(i);
}
These will work if you need to work with a C++03 compiler. If you have a C++0x compiler, there are far superior solutions available.
Variable arguments are unsafe by design. You cannot check that the user passed correct type in any way. C++0x comes to the rescue with variadic templates but not many compilers support it nowadays (only GCC afaik).
Unfortunately, there really isn't a way to do this. Functions like printf() can easily be fowled up by passing invalid or the wrong number of arguments.
In C++, this is an advanced feature that requires the programming using such code to ensure the correct arguments are passed.
You can't do any sort of type checking with varargs. I'd suggest using an iterator range instead (like standard library functions) or possibly a std::vector<int>. This way the types can't be subverted.
Since you are using C++, how about overloading some operator and pass the arguments one-by-one? For example
class MyFunction {
std::vector<int> param;
public:
MyFunction() { /* some initialisation? */ }
MyFunction &operator,(int eatMe) {
param.push_back(eatMe);
return *this;
}
~MyFunction() {
//the implementation of your function goes here
}
}
Then you can call it like this:
MyFunction(),2,3,5,7;
Note, the use of comma operator may look scary, but it is actually very helpful in this case. It is the lowest possible, left-associative operator.
If your function takes some extra parameters, not only the unknown-length of int-s, you can pass them in the constructor.
If someone uses something else than int, the default comma operator will be used (evaluate left side, discard, evaluate right side). If you don't like that - pick a different operator, e.g. stream-like << or boost-like %.
If you are restricted to C++03 and all your arguments should be integers, one solution would be to simply hide the variable argument function (in a 'detail' namespace for example) and make a series of overloaded functions for 1 to N amount of arguments. Those functions would be simple inline functions that forward the call to the vararg version of the real function. This way, you have one real implementation, no run-time overhead, and you expose a type-safe interface to the caller (and the caller can always use the vararg version if he needs more than N arguments).
Boost.PP can also help to generate these types of repetitive patterns.
Of course, if you have some level of C++0x support, than the problem can be solved in many ways, including initializer_list or variadic templates.
Just to illustrate my comment on CygnusX1's answer, you could do it like:
class MyFunction {
std::vector<int> params;
public:
MyFunction() { (*this)(); }
MyFunction(int eatMe) { (*this)(eatMe); }
MyFunction& operator()(int eatMe) {
params.push_back(eatMe);
return *this;
}
void operator()() {
// use params to do something interesting
}
}
MyFunction(2)(3)(5)(7)();
I have written a function that searches a text file for names. It returns vector, where each element of the vector is a different name.
Now I would like to search the same text file for numbers and return the numbers in a vector.
This is probably a dumb question, but I'm wondering what the best approach would be. Overload the function by writing a second function that returns a vector or turning the function I have already written into a template by replacing the type with T, as in vector.
The reason I'm confused about the template option is that I'm not sure if strings and numerical types like double and int are compatible in a template. Any tips would be appreciated! Thanks.
As a function signature does not include its return type, you can't overload a function only on its return type.
Also, as the two functions returns different kind of data (one could return person names, the other could return the persons ages), having the same name for both seems a semantic error.
But anyway...
Move the return type part back into the signature
void retrieveData(std::vector<std::string> & data) ;
void retrieveData(std::vector<double> & data) ;
void foo()
{
std::vector<std::string> strings ;
std::vector<double> doubles ;
// retrieve the strings
retrieveData(strings) ;
// retrieve the numbers
retrieveData(doubles) ;
}
This solution is best both because the overload work "as is", and because it avoids a copy of the vector (I am using C++03, here... In C++0x, one would use move semantics to avoid the potential extra copy).
Make the return type part of the signature (non-template version)
std::vector<std::string> retrieveData(std::string * dummy) ;
std::vector<double> retrieveData(double * dummy) ;
void foo()
{
// retrieve the strings
std::vector<std::string> strings = retrieveData((std::string *) NULL) ;
// retrieve the numbers
std::vector<double> doubles = retrieveData((double *) NULL) ;
}
Here, the dummy parameter's pointer value is not used in the function body. It's use is to enable the compiler to find the right overload.
This is ugly (not mentioning the part on returning by copy a vector in C++03 but this is out of topic), but it does the work and is a viable answer to your question.
Make the return type part of the signature (template version)
// declared, but not defined
template<typename T>
std::vector<T> retrieveData() ;
// defined
template<>
std::vector<std::string> retrieveData<std::string>() ;
// defined
template<>
std::vector<double> retrieveData<double>() ;
void foo()
{
// retrieve the strings
std::vector<std::string> strings = retrieveData<std::string>() ;
// retrieve the numbers
std::vector<double> doubles = retrieveData<double>() ;
}
Here, the template parameter is given by the user, thus giving the compiler enough information to choose the right overload
P.S.: This answer is quite similar to the one I gave here: Overload a C++ function according to the return value
I'd just make two different functions with different names like findStrings() and findNumbers(). Overloading by return type doesn't work, templates make no sense here, and, most importantly, these functions just do different things.
However, if overloading is desired, I would do it like this:
bool findInFile(const std::string &fileName, std::vector<int> &result);
bool findInFile(const std::string &fileName, std::vector<std::string> &result);
This way overloading will work, and it also has a nice property of returning success or failure indicator if you want to avoid throwing exceptions in case of failure. Just replace it with void otherwise. But this approach has the disadvantage of being awkward to use if you need not to store the result in a variable, but pass it to some function for example.
Since you have only 1 overload to do, I would go with function overload instead of templates. I think that in this case it doesn't justify adding a bunch of code just to overload a function once.
There is maybe a case for a template function as follows:
template <typename T, typename OutputIterator>
void readTokens<T>(OutputIterator oi) {
for each token in the file {
std::stringstream ss(token);
T t;
if (ss >> t) {
*oi++ = t;
}
}
}
Then you can do readTokens<string>, readTokens<int>, readTokens<double>, or any other type you care to invent in future that has a stream extraction operator (and whose string representation doesn't contain spaces, or whatever else it is you use to delimit items in your text file).
This only applies if the means of splitting up the file into tokens/items is the same regardless of the type that they're going to be read as. The reason I say "maybe" is that it might be better to first read the file into strings in a non-template function, then have a separate template function that tries to convert them to int/double/whatever, filtering out the ones that fail to convert. You'll note that the above code isn't terribly efficient with T = string, and frankly having written it you're unlikely to test it with any types other than the two you're currently interested in (int and string), so you could be storing up trouble for later.
I've made a second change to your function interface, which is to write the results to an iterator rather than returning a vector by value. This is an independent change, but it's a common trick with template functions because it means the caller can have the results written to a vector, or any other container they prefer, or perhaps process them without storing them all at once (for example if all that's needed is to write them to a stream). To get the original behavior, with the results in a vector, you'd call it like this:
std::vector<int> v;
readTokens<int>(std::back_inserter(v));
Templates would make no sense here, because the code for the function (presumably) depends on its argument type. So you would have to specialise the template anyway, and you might as well just use overloading for this.