Error code with sorting program - c++

I am currently trying to write a program that alphabetizes strings. I have one error. It's that minLocation does not take 2 arguments. I am fairly new to programming could anyone give me a hint as to why this part of my code is wrong?
int minLocation(string list[], int first, int last)
{
int mIndex=first;
int loc = 0;
for (loc = first+1; loc <= last; loc++)
if (list[loc] < list [mIndex])
mIndex = loc;
return mIndex;
void Sort(string slist[],int length)
{
int mIndex;
for (int loc = 0; loc < length-1; loc++)
{
mIndex = minLocation (loc,length-1);
swap (loc, minIndex);
}
}

Without seeing the definition of minLocation, we can't tell. But it's a safe bet that it doesn't take two arguments - compilers don't lie to you just for the fun of it, you can usually assume that what they're saying is true :-)
You need to find the definition, something like:
int minLocation (int loc) { ...
and figure out how you're actually meant to call it. Given that it looks like it's trying to find which of two indexes has the lower value, it may be that it needs more than two arguments.
And, on top of that, you need to decide whether you want that variable called mIndex or minIndex. Most compilers aren't quite smart enough to figure that out for you.
Based on your edits that muinFunction is defined as:
int minLocation (string list[], int first, int last) { ...
it seems evident that it also needs the string array as well as the two indexes. You will need to change the call to:
mIndex = minLocation (slist, loc, length-1);
And keep an eye on the swap call as well. It may have a similar requirement, based on the coding style.

Related

c++: how to determine if a variable is a vector element

I have a method, which i want to execute differently depending on if the passed variable is an element of a vector or not, like for example:
void method(int a){
if (/*a is an element of a vector*/) //do one thing
else //do another thing
}
and then in main:
vector<int> a;
a.pushback(1);
int b = 1;
method(a[0]); // does one thing
method(b); // does the other thing
What is the simplest way to do that?
Well, for all cases this is impossible, because it actually requires your function to look at how it is executed, and there is no such thing in C++. The hated eval() comes to mind.
But in a certain case, when your vector is a global entity, you could pass your variable by link instead of value. Then, you can check if it fits the space between the start and end of the desired vector. This is how it is done(not tested though, but should work)
vector<int> v;
//fill it somewhere somehow
void method(int& a)
{
int* beg = v.data();
int* end = beg + v.size();
int* val = &a;
if ((val >= beg) && (val < end))
{
//it is a part of vector
}
else
{
//it is not a part of vector
{
}
Problem is that you really shouldn't do it this way... As people in the comments said, it DOES look like an XY problem.
An int is an int. An int does not wear a label around its neck, telling everyone where it came from. When an int is passed to a function, there is nothing that specifies where the int originates.
You should take this as an opportunity to learn about iterators, and implement an overloaded method that takes either an
void method(int);
for a parameter, or a
void method(std::vector<int>::iterator iter);
for a parameter (or, perhaps, a const_iterator), and invoke the alternative method() by passing it an iterator to the int in your vector.

Advantage of function taking a pointer to a collection, to avoid copying on return?

Suppose I have the following C++ function:
// Returns a set containing {1!, 2!, ..., n!}.
set<int> GetFactorials(int n) {
set<int> ret;
int curr = 1;
for (int i = 1; i < n; i++) {
curr *= i;
ret.insert(curr);
}
return ret;
}
set<int> fs = GetFactorials(5);
(This is just a dummy example. The key is that the function creates the set itself and returns it.)
One of my friends tells me that instead of writing the function the way I did, I should write it so that the function takes in a pointer to a set, in order to avoid copying the set on return. I'm guessing he meant something like:
void GetFactorials2(int n, set<int>* fs) {
int curr = 1;
for (int i = 1; i < n; i++) {
curr *= i;
fs->insert(curr);
}
}
set<int> fs;
GetFactorials2(5, &fs);
My question: is this second way really a big advantage? It seems pretty weird to me. I'm new to C++, and don't know much about compilers, but I would assume that through some compiler magic, my original function wouldn't be that much more expensive. (And I'd get to avoid having to initialize the set myself.) Am I wrong? What should I know about pointers and copying-on-return to understand this?
No, it is generally not advantageous at all. Just about any reasonable compiler these days will utilize named return value optimization (see here). This effectively removes any performance penalty from the former example.
If you really want to get into the nitty gritty, read this article by Dave Abrahams (one of the big contributors to boost). Long story short, however, just return the value. It's probably faster.
Yes it can be expensive. Especially when the set gets bigger. There is no reason not to use pointers or reference here. It will save you a lot and you don't sacrifice much regarding readability.
And why rely on compiler optimizations when you can optimize it yourself. The compiler knows your code but not always understands your algorithm.
I would do this
void GetFactorials2(int n, set<int>& fs) {
// ^^
int curr = 1;
for (int i = 1; i < n; i++) {
curr *= i;
fs->insert(curr);
}
}
and the call will stay normal.
set<int> fs;
GetFactorials2(5, fs);
^^

Heap Sorting not producing a correct output

I am writing a function to sort an array using heap sorting. So far I have:
template <typename Item, typename SizeType>
void heap_sort(Item data[], SizeType size) {
vector<int> v(data,data+size);
SizeType unsorted = size;
make_heap(v.begin(),v.end());
while(unsorted > 1) {
--unsorted;
swap(data[0], data[unsorted]);
reheapify_down(data,unsorted);
}
}
and:
template <typename Item, typename SizeType>
void reheapify_down(Item data[], SizeType size) {
SizeType current(0), big_child;
bool heap_ok = false;
while(!heap_ok && 2*current+1 < size) {
if(2*current+2 > size)
big_child = 2*current + 1;
else if(data[2*current+1] > data[2*current+2])
big_child = 2*current+1;
else
big_child = 2*current + 2;
if(data[current] < data[big_child]) {
swap(data[current],data[big_child]);
current = big_child;
}
else
heap_ok = true;
}
}
When I run the program, it outputs an incorrectly sorted array though. Is there something that I am just missing or some error that I overlooked?
Just a few suggestions.
First, I'd write a small proxy class that does nothing but let you use 1-based indexing on your collection. All the index math used in heaps assumes 1-based indexing, and it's a lot easier to compensate for 0-based indexing in one place than throughout all the code. As it stands right now, I have a hard enough time following the indexing to be sure your reheapify_down is correct. It's certainly the right general idea, but it would take a lot of work to be certain all the math is right.
Second, I'd write a check_heap (or whatever) that you can use to verify both your make_heap and your reheapify_down (as an aside, I'd decide on either "make_heap" or "heapify", so the names would be either "make_heap" and "remake_heap", or else "heapify" and "reheapify").
Beyond that, however, it's hard to be certain of the problem, especially since you haven't included the code for your make_heap in the question. If it isn't working correctly, the rest has no hope.

C++ Sorting Function

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

quicksort debug

Can anyone point out why this implementation of quick sort is not working, i have gone through it several times and can't seem to find the error
int quickPartition ( int data[], int p, int r)
{
int x=data[r];
int i=p-1;
for (int j=p; j<r; j++)
{
if(data[j]<x)
{
i++;
int temp=data[i];
data[i]=data[j];
data[j]=temp;
}
int temp=data[i+1];
data[i+1]=data[r];
data[r]=temp;
}
i++;
cout<<"i:"<<i<<endl;
return i;
}
void myQuickSort(int data[], int left, int right)
{
if(left<right)
{
int q=quickPartition(data,left,right);
myQuickSort(data,left,q-1);
myQuickSort(data,q+1,right);
}
}
the call to quicksort is simply
myQuickSort(anArray,0,size-1);
Methinks
int temp=data[i+1];
data[i+1]=data[r];
data[r]=temp;
should go outside the for loop.
Your implementation of partition looks entirely bogus. What you want is iterate from both ends and on each end find an object which belongs to the opposite part. If the iterators meet, you are done. Otherwise you swap the two objects and find the next pair.
Personally, I can't think properly in the abstractions you are using: I have a much easier time to think in terms of iterators pointing to the respective objects and finding the next object to swap should be functions as well. Also, I need to factor things into small, comprehensible bits. You swap objects at some point. This should be a separate function. With this partition() would look something like this:
int* partition(int* left, int* right, int value) {
while (left != right)
{
left = find_forward(left, right, value);
right = find_backward(left, right, value);
if (left != right)
{
swap(left, right);
}
}
return left;
}
I haven't tested this but something along those lines should work. Obviously, I would just use std::swap() to swap elements and std::find_if() to find suitable locations (for the backward case using std::reverse_iterator). Well, if this weren't a homework assignment you would just use std::sort() anyway: it doesn't use a vanilla quick-sort but a variation which detects that it is running into a bad case and uses std::heap_sort() in this case to guarantee that it stays O(n log n).