Unhandled Exception Sort Recursion - c++

I'm having an issue with a recursive sorting assignment in C++. Unfortunately, we've been assigned to do it in a very specific way, but I cannot seem to manage to get it to do what I want, and since I'm not used to recursion, I can't follow it well to trouble shoot. The error that I'm getting is Unhandled exception at 0x77d915fe in SortFinal.exe: 0xC0000005: Access violation. Presumably this is coming somehow from the a[] array used within the sort function. I'm new to this site so forgive me if the organization is terrible, but here's my code as it currently stands:
#include <iostream>
using namespace std;
// prototypes
void sort(int a[], int i, int j);
int main() {
int x[4] = {3, 1, 5, 2};
for (int count = 0; count < 4; count++) {
cout << x[count] << ": ";
}
cout << endl;
sort(x, 0, 4);
for (int count = 0; count < 4; count++) {
cout << x[count] << ": ";
}
cout << endl;
system("pause");
return 0;
}
void sort(int a[], int i, int j) {
int first;
if (j > i) {
int index = i + 1;
bool done = false;
first = a[i];
sort(a, i + 1, j);
for (!done && index <= j; index++;) {
if (first < a[index]) {
a[index - 1] = a[index];
} else {
a[index - 1] = first;
done = true;
}
}
if (!done && index > j) {
a[index - 1] = first;
}
}
}

The line with the problem is: for (!done && index <= j; index++;) { in the for loop the first block is initialization, the second stop condition and the third is increment, in you case you are putting stop condition as initialization and increment as stop condition, changed by for (; !done && index <= j; index++) {. Please take always good look before posting in SO. Any compiler (and I mean ANY) would catch this error with a error message good enough for you to figure out the problem. In GCC 4.9.1 was:
E:\test.cpp: In function 'void sort(int*, int, int)':
E:\test.cpp:34:20: warning: statement has no effect [-Wunused-value]
for (!done && index <= j; index++;) {
^
Compile always with all warnings enable (-Wall in GCC and Clang, select at least level 4 in Visual C++), the compiler would help you to fix a lot (valid code that are bugs).

Related

Selection Sort Implementation with C++ incorrect

really new to C++, trying to instantiate some basic algorithms with it. Having trouble returning the correct result for selection sort. Here is my code
#include <iostream>
#include <array>
#include <vector>
using namespace std;
// Selection Sort :
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
return m;
}
}
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void selectionSort(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); ++i)
{
int min = findMin(arr, i);
swap(arr[i], arr[min]); // Assume a correct swap function
}
}
}
void print(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); i++)
{
cout << arr[i] << "";
cout << endl;
}
}
}
int main()
{
vector<int> sort;
sort.push_back(2);
sort.push_back(1);
sort.push_back(7);
sort.push_back(4);
sort.push_back(5);
sort.push_back(3);
print(sort);
cout << "this was unsorted array";
cout << endl;
cout << findMin(sort, 0);
cout << "this was minimum";
cout << endl;
selectionSort(sort);
print(sort);
}
I am getting the following results:
comparison_sort.cpp:20:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
}
^
1 warning generated.
2
1
7
4
5
3
this was unsorted array
1
this was minimum
1
2
4
5
3
0
My question is: What is causing this control path error? Why is the "7" here being replaced with a "0"?
Thanks in advance! Sorry for the noob question.
I have reviewed all my current functions and nothing seems to explain why the 7 is replaced with a 0. I have tried multiple integers and it looks like the maximum number is always replaced.
The warning is very real, and it alludes to the problem that's breaking your sort as well.
You are currently returning m inside your loop body. What that means is that if the loop is entered, then the function will return m on the very first time around the loop. It only has a chance to check the first element.
And of course, if a is the last index of the array, then the loop will never execute, and you will never explicitly return a value. This is the "control path" which does not return a value.
It's quite clear that you've accidentally put return m; in the wrong place, and even though you have good code indentation, some inexplicable force is preventing you from seeing this. To fix both the warning and the sorting issue, move return m; outside the loop:
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
}
return m;
}

How do I fix this warning - "control reaches end of non-void function [-Wreturn-type]"

During compiling, it shows this warning - control reaches end of non-void function [-Wreturn-type]. I googled and found that this warning shows when you don't return anything in the function. But I couldn't figure out where's the error in my code.
Here's my code:
#include <iostream>
#include <algorithm>
using namespace std;
int findUnique(int *a, int n){
sort(a, a+n);
int i=0;
while(i<n){
if(a[i]==a[i+1]){
i += 2;
}
else{
return a[i];
}
}
}
int main(){
int t;
cin >> t;
while (t--){
int size;
cin >> size;
int *input = new int[size];
for (int i = 0; i < size; ++i)
{
cin >> input[i];
}
cout << findUnique(input, size) << endl;
}
return 0;
}
You have to know why this warning is shown to understand what to do about it, this warning is shown when your function has a return type but you haven't returned value from one or more exit points of a function. Now see in your function, you return a[i] but consider a situation where your code doesn't go in the else block at all. So after coming out of the while block. There is no return statement therefore compiler is throwing control reaches the end of non-void function [-Wreturn-type].
The function returns nothing in case when the array does not contain a unique number or when the parameter n is equal to 0.
So the compiler issues the warning message.
Moreover the while loop can invoke undefined behavior when i is equal to n-1 due to using a non-existent element with the index n in this if statement
if(a[i]==a[i+1]){
Also there is a logical error. The if statement
if(a[i]==a[i+1]){
i += 2;
}
else{
return a[i];
}
does not guarantee that indeed a unique number will be returned.
Using your approach when it is allowed to change the original array by calling the algorithm std::sort the function can be defined for example the following way
size_t findUnique( int *a, size_t n )
{
std::sort( a, a + n );
size_t i = 0;
bool unique = false;
while ( !unique && i != n )
{
size_t j = i++;
while ( i != n && a[i] == a[j] ) i++;
unique = i - j == 1;
}
return unique ? i - 1 : i;
}
And in main the function can be called like
size_t pos = findUnique(input, size);
if ( pos != size )
{
cout << input[pos] << endl;
}
else
{
// output a message that there is no unique number
}
Pay attention to that your program produces multiple memory leaks. You need to free the allocated memory in each iteration of the while loop.
The problem is in the function findUnique This function is supposed to return int no matter what although in your code you are returning an integer only under certain conditions
Here is a possible fix:
// return true if unique number found
// return false otherwise
bool findUnique(int *a, int n, int *unique){
sort(a, a+n);
int i=0;
while(i<n){
if(a[i]==a[i+1]){
i += 2;
}
else{
*unique = a[i];
return true;
}
}
return false;
}
Then in the main something like that:
int unique;
bool uniqueFound = findUnique(input, size &unique);
if (uniqueFound == true)
cout << unique << endl;
else
cout << "No unique number found" << endl;

Randomly Shuffle an array and using quick sort algorithm

I have been trying to write a code to randomly shuffle the array elements, and then use the quick sort algorithm on the array elements. This is the code I wrote:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void randomise(int arr[], int s, int e)
{
int j;
srand(time(NULL));
for (int i = e; i >= s; i--)
{
int j = rand() % (i + 1);
swap(&arr[i], &arr[j]);
}
}
int Partition(int arr[], int s, int e)
{
int pivot = arr[e];
int i = s - 1;
int j;
for (j = s; j <= e; j++)
{
if (arr[j] <= pivot)
{
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[e]);
return i + 1;
}
void QuickSort(int arr[], int s, int e)
{
if (s >= e)
return;
int x = Partition(arr, s, e);
QuickSort(arr, s, x - 1);
QuickSort(arr, x + 1, e);
}
int main()
{
int b[] = {1, 2, 3, 4, 5};
randomise(b, 0, 4);
cout << "Elements of randomised array are:";
for (int i = 0; i <= 4; i++)
{
cout << b[i] << endl;
}
QuickSort(b, 0, 4);
cout << "Elements after quick sort are:";
for (int i = 0; i <= 4; i++)
{
cout << b[i] << endl;
}
return 0;
}
However, on debugging on GDB, I found out that this program gives segmentation fault. On execution, this program gives the output as:
Elements of randomised array are:4
5
2
3
1
Can someone tell me what is the bug in this code (I have tried debugging it on GDB, but I am still clueless).
Basically, when the error is segmentation fault, you should be looking for a bug which you will feel like crashing your head into wall, after finding it. On line 26. change <=, to < . It's in your partition function. for (j = s; j < e; j++)
A little explanation about quick sort; After each time quickSort function runs on a partiotion, the last element of the partition, called pivot, will reach its' real place in array. The partition function, returns the real place of the pivot in the array. Then the main array will be split into two more partitions, before the pivot place, and after that. Your bug is returning real-pivot-place + 1, as the output of partition function. So you will run quickSort on wrong partition; the partition that is already sorted but the program will keep trying to sort it over and over because of wrong partitioning. As you may know, each time you run a function, its' variables will be saved into a stack in computer. Since your calling a recursive function over and over(that isn't supposed to stop), this stack will get full and will overflow. After that, computer will represent some undefined behavior and maybe throw an exception that can not describe the problem correctly. This is why your getting segmentation fault. But why you return real-pivot-place + 1? Because in your for loop in partition function, you will visit the pivot too, which you shouldn't. Because pivot isn't supposed to be compared with itself. So you will increase i variable unnecessarily. https://en.wikipedia.org/wiki/Call_stack Check this link for additional information about stack and how a function runs in computer.

Codeblocks c++ code doesn't run in VS 19 (vector subscript out of range)

I ran a few tests of a simple problem in both VS 19 and CodeBlocks after an error that keeps popping in a lot of my coding problems. Surprisingly in Codeblocks everything runs fine and i get the expected result while in VS i always get the "vector subscript out of range" error.
The problem is quite simple, get the least number of stops until the destination. (just count them)
The error appears at the second while loop where i compare i to the size of the vector.
I am wondering why it actually works in codeblocks and also would like to know how to fix it in VS
#include <iostream>
#include <vector>
using namespace std;
int compute_min_refills(int dist, int tank, vector<int>& stations) {
int distanceTraversed = 0;
int i = 0;
int stops = 0;
bool impossible = false;
while (distanceTraversed<=dist)
{
if((distanceTraversed + tank)> dist)
{
distanceTraversed = dist;
return stops;
}
while ((distanceTraversed + tank) > stations[i] && i< stations.size())
{
i++;
impossible = false;
}
if ((distanceTraversed + tank) <= stations[i] || i == stations.size())
{
if (impossible == true)
{
return -1;
}
else
{
distanceTraversed += stations[i - 1];
stops++;
impossible = true;
}
}
}
return stops;
}
int main() {
int d = 0;
cin >> d;
int m = 0;
cin >> m;
int n = 0;
cin >> n;
vector<int> stations;
int a;
for (int i = 0; i < n; ++i)
{
cin>>a;
stations.push_back(a);
}
cout << compute_min_refills(d, m, stations) << "\n";
return 0;
}
Here are some imputs if you want to test this out:
Input:
500
200
4
100 200 300 400
You're bound checking your vector accesses too late.
Because of short-circuit evaluation, (distanceTraversed + tank) > stations[i] && i< stations.size() doesn't work the way you think it does, 1st you access the array, and only if the condition was true, you check if the access was inside bounds, which is UB if it was not.
Later on (distanceTraversed + tank) <= stations[i] || i == stations.size() doesn't check for bounds either.
And as a final note, distanceTraversed += stations[i - 1]; if i==0, you will try to access element -1, but std::vector is indexed using std::size_t which is unsigned, causing an implicit conversion, an assigning very large value to it.

Not able to find the reason for undefined behavior

In the following program, I declare a global variable (adj_matrix) for the purpose of using it in different functions. It is defined in another function (init_matrix).
I tested the program with the test case 3 1 2 and received a segmentation fault.
3 1 2
YES
Segmentation fault: 11
The surprising part is, that when I uncomment the cout line in the construct_matrix function, the segmentation fault disappears.
This looks like the case of undefined behavior to me but I'm unable to figure out why and where it occurs. Please help.
Following is the program:
#include <iostream>
#include <vector>
using namespace std;
vector<vector<int> > adj_matrix;
void init_matrix(int size, int val)
{
adj_matrix.reserve(size);
for (int i = 0; i < size; ++i)
{
adj_matrix[i].reserve(size);
for (int j = 0; j < size; ++j)
{
if(i == j)
adj_matrix[i][i] = 0;
else
adj_matrix[i][j] = val;
}
}
}
void construct_matrix(int size, int k, int val)
{
// k denotes how many components we want
for (int i = k - 1; i < size - 1; ++i)
{
adj_matrix[i][i + 1] = val;
adj_matrix[i + 1][i] = val;
// Uncommenting the following line resolves the seg-fault error
// cout << i << endl;
}
}
void print_matrix(int size)
{
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
cout << adj_matrix[i][j];
cout << endl;
}
}
int main()
{
int n, a, b;
cin >> n >> a >> b;
/*
The solution uses the fact that atleast one of G or G complement is always connected.
In cases where we have to show both are connected (not possible when n is 2 or 3),
we draw a simple graph connected v1 v2 v3...vn. The complement will be also connected (n != 2 and 3)
*/
if(a == 1 && b == 1)
{
if(n == 2 || n == 3)
cout << "NO" << endl;
else
{
cout << "YES" << endl;
init_matrix(n, 0);
construct_matrix(n, 1, 1);
print_matrix(n);
}
}
else if(a == 1)
{
cout << "YES" << endl;
init_matrix(n, 1);
construct_matrix(n, b, 0);
print_matrix(n);
}
else if(b == 1)
{
cout << "YES" << endl;
init_matrix(n, 0);
construct_matrix(n, a, 1);
print_matrix(n);
}
else
cout << "NO" << endl;
return 0;
}
For ones interested in the problem this is a solution to, visit here.
PS: I've checked the bounds in the for loop in my functions, and they are correct. If this wasn't the case, the program will throw a segmentation fault regardless of the cout line.
The reason / one of reasons of undefined behavior in this code is using operator[] to access elements of vector that are not yet created.
From http://www.cplusplus.com/reference/vector/vector/operator[]/:
A similar member function, vector::at, has the same behavior as this operator function, except that vector::at is bound-checked and signals if the requested position is out of range by throwing an out_of_range exception.
Portable programs should never call this function with an argument n that is out of range, since this causes undefined behavior.
reserve doesn't create new elements of the vector. It just ensures that the vector has allocated enough memory for them. If you want to create new elements which you can access, use resize. (https://stackoverflow.com/a/7397862/3052438)
I also recommend to double check all you vector accesses for out of bound indexes, after you fix the first problem.
adj_matrix.reserve(size); Does not create any elements, but just reserves the size of the vector. As such adj_matrix[i].reserve(size); is undefined behaviour when i is greater than adj_matrix.size()