I'm trying to create a program which allows for a dynamically allocated array to store some integers, increase the maximum size if need be, and then display both the unsorted and sorted array in that order.
Link to my full code is at the bottom.
The first issue I have is the dynamically allocated array going haywire after the size needs to be increase the first time. The relevant code is below.
while (counter <= arraySize)
{
cout <<"Please enter an integer number. Use 999999 (six 9's) to stop\n";
if (counter == arraySize) //If the counter is equal to the size of the array
{ //the array must be resized
arraySize +=2;
int *temp = new int[arraySize];
for (counter = 0; counter < arraySize; counter++)
{
temp[counter] = arrayPtr[counter];
}
delete [] arrayPtr;
arrayPtr = temp;
counter ++; //the counter has to be reset to it's original position
} //which should be +1 of the end of the old array
cin >> arrayPtr[counter];
if (arrayPtr[counter] == sentinel)
{
cout << "Sentinel Value given, data entry ending.\n";
break;
}
counter ++;
}
This produces the unintended operation where instead of waiting for the sentinel value, it just begins to list the integers in memory past that point (because no bounds checking).
The next issue is that my sorting function refuses to run. I tried testing this on 5 values and the program just crashes upon reaching that particular part of code.
The function is called using
sorting (arrayPtr);
but the function itself looks like this:
void sorting (int *arr)
{
int count = 0, countTwo = 0, tempVal;
for (count = 0; arr[count] != 999999; count++) //I figured arr[count] != 999999 is easier and looks better
{ //A bunch of if statements
for (countTwo = 0; arr[countTwo] != 99999; countTwo++)
{
if (arr[countTwo] > arr[countTwo+1])
{
tempVal = arr[countTwo];
arr[countTwo] = arr[countTwo+1];
arr[countTwo+1] = tempVal;
}
}
}
}
Any help on this issue is appreciated.
Link to my source code:
http://www.mediafire.com/file/w08su2hap57fkwo/Lab1_2336.cpp
Due to community feedback, this link will remain active as long as possible.
The link below is to my corrected source code. It is annotated in order to better highlight the mistakes I made and the answers to fixing them.
http://www.mediafire.com/file/1z7hd4w8smnwn29/Lab1_2336_corrected.cpp
The first problem I can spot in your code is in the for loop where counter goes from 0 to arraySize-1, the last two iteration of the loop will access arrrayPtr out of bounds.
Next, at the end of the if (counter == arraySize) there is a counter++; This is not required since at this moment counter is already indexing the array out of bound.
Finally in your sorting function the inner loop looks for the wrong value (99999 instead of 999999), so it never stop and goes out of bounds. To prevent this kind of error, you should define your sentinel as a const in an unnamed namespace and use it through the code instead of typing 999999 (which is error prone...).
Related
I have to write a function which accepts an int array parameter and checks to see if it is a
permutation.
I tried this so far:
bool permutationChecker(int arr[], int n){
for (int i = 0; i < n; i++){
//Check if the array is the size of n
if (i == n){
return true;
}
if (i == arr[n]){
return true;
}
}
return false;
}
but the output says some arrays are permutations even though they are not.
When you write i == arr[n], that doesn't check whether i is in the array; that checks whether the element at position n is i. Now, that's even worse here, as the array size is n, so there's no valid element at position n: it's UB, array is overindexed.
If you'd like to check whether i is in the array, you need to scan each element of the array. You can do this using std::find(). Either that, or you might sort (a copy of) the array, then check if i is at position i:
bool isPermutation(int arr[], int n){
int* arr2 = new int[n]; // consider using std::array<> / std::vector<> if allowed
std::copy(arr, arr + n, arr2);
std::sort(arr2, arr2 + n);
for (int i = 0; i < n; i++){
if (i != arr2[i]){
delete[] arr2;
return false;
}
}
delete[] arr2;
return true;
}
One approach to checking that the input contains one of each value is to create an array of flags (acting like a set), and for each value in your input you set the flag to true for the corresponding index. If that flag is already set, then it's not unique. And if the value is out of range then you instantly know it's not a permutation.
Now, you would normally expect to allocate additional data for this temporary set. But, since your function accepts the input as non-constant data, we can use a trick where you use the same array but store extra information by making values negative.
It will even work for all positive int values, since as of C++20 the standard now guarantees 2's complement representation. That means for every positive integer, a negative integer exists (but not the other way around).
bool isPermutation(int arr[], int n)
{
// Ensure everything is within the valid range.
for (int i = 0; i < n; i++)
{
if (arr[i] < 1 || arr[i] > n) return false;
}
// Check for uniqueness. For each value, use it to index back into the array and then
// negate the value stored there. If already negative, the value is not unique.
int count = 0;
while (count < n)
{
int index = std::abs(arr[count]) - 1;
if (arr[index] < 0)
{
break;
}
arr[index] = -arr[index];
count++;
}
// Undo any negations done by the step above
for (int i = 0; i < count; i++)
{
int index = std::abs(arr[i]) - 1;
arr[index] = std::abs(arr[index]);
}
return count == n;
}
Let me be clear that using tricky magic is usually not the kind of solution you should go for because it's inevitably harder to understand and maintain code like this. That should be evident simply by looking at the code above. But let's say, hypothetically, you want to avoid any additional memory allocation, your data type is signed, and you want to do the operation in linear time... Well, then this might be useful.
A permutation p of id=[0,...,n-1] a bijection into id. Therefore, no value in p may repeat and no value may be >=n. To check for permutations you somehow have to verify these properties. One option is to sort p and compare it for equality to id. Another is to count the number of individual values set.
Your approach would almost work if you checked (i == arr[i]) instead of (i == arr[n]) but then you would need to sort the array beforehand, otherwise only id will pass your check. Furthermore the check (i == arr[n]) exhibits undefined behaviour because it accesses one element past the end of the array. Lastly the check (i == n) doesn't do anything because i goes from 0 to n-1 so it will never be == n.
With this information you can repair your code, but beware that this approach will destroy the original input.
If you are forced to play with arrays, perhaps your array has fixed size. For example: int arr[3] = {0,1,2};
If this were the case you could use the fact that the size is known at compile time and use an std::bitset. [If not use your approach or one of the others given here.]
template <std::size_t N>
bool isPermutation(int const (&arr)[N]) {
std::bitset<N> bits;
for (int a: arr) {
if (static_cast<std::size_t>(a) < N)
bits.set(a);
}
return bits.all();
}
(live demo)
You don't have to pass the size because C++ can infer it at compile time. This solution also does not allocate additional dynamic memory but it will get into problems for large arrays (sat > 1 million entries) because std::bitset lives on automatic memory and therefore on the stack.
im trying to let the user input a number for each person. the console then outputs the maximum value in the array. everything works fine but the max always outputs as -858993460. i tried multiple combinations but i cant seem to figure it out
im new to arrays so any help would be appreciated as well as an feedback on how to improve my code
#include <iostream>
int main()
{
int people[10];
int max = people[0];
std::cout << "please enter number of pancakes eaten by each person.\n";
//lets the user input values for each element
for (int i = 0; i < 10; ++i) {
std::cin >> people[i];
}
//outputs all the elements of the array
for (int i = 0; i < 10; ++i) {
std::cout << people[i] << " ";
}
//finds the largest element in the array
for (int i = 0; i > 10; ++i) {
if (people[i] > max) {
max = people[i];
}
}
std::cout << "\nmax: " << max;
return 0;
}
also i keep getting a warning saying: ill-defined for-loop. loop body not executed. i tried looking this warning up but the warning seems very broad and i couldnt find anything that helped
int people[10];
This declares an array of ten int values. None of the values are explicitly initialized. This is how plain values that get declared in automatic scope work in C++, they are not initialized to any values. It is the code's responsibility to initialize them.
int max = people[0];
This sets the value of max to the first value of the array. Which has not been initialized to any value. This is undefined behavior. From this point on the program's behavior is undefined.
Furthermore, even if peoples values were initialized this will still be broken. The intent of the program is clear: read values into the people array, and then find their maximum value.
However, at this point, nothing has been read from anywhere.
The attempted goal here is to set max, initially, to the first value in the array, the first read value.
But in order for this to make sense, max should be set after the values in the array get read from input, and not before. This should be done after all the values are read in, and not before.
in the line int max = people[0] you are dereferencing the first element of the array. But dereferencing to what? at that point in the program you have not initialised any of the 10 elements in the people array. So taking the value at people[0] at that point in the program and copying it into another int for later comparison is undefined behaviour. Best solution is to simply move int max = people[0] to after you take the user input, and for the comparison loop start with i = 1, because max is already equivalent to the first inputted value.
So, I tried to make an array using input first, then sorting it out from smallest to biggest, then display the array to monitor.
So I come up with this code :
#include <iostream>
using namespace std;
void pancakeSort(int sortArray[], int sortSize);
int main()
{
// Input The Array Element Value
int pancake[10];
for(int i=0; i<10; i++)
{
cout << "Person " << i+1 << " eat pancakes = ";
cin >> pancake[i];
}
// call pancake sorting function
pancakeSort(pancake, 10);
}
void pancakeSort(int sortArray[], int sortSize)
{
int length = 10;
int temp;
int stop = 10;
// this is where the array get sorting out from smallest to biggest number
for(int counter = length-1; counter>=0; counter--)
{
for(int j=0; j<stop; j++)
{
if(sortArray[j]>sortArray[j+1])
{
temp = sortArray[j+1];
sortArray[j+1] = sortArray[j];
sortArray[j]=temp;
}
}
stop--;
}
// after that, the array get display here
for(int x=0; x<sortSize; x++)
{
cout << sortArray[x] << " ";
}
}
but the output is weird :
enter image description here
the function is successfully sorting the array from smallest to biggest,
but there is 2 weird things :
1. The biggest value element (which is 96 from what I input and it's the 10th element after got sorted out), disappear from the display.
2. For some reason, there is value 10 , which I didn't input on the array.
So, what happened?
In the loop
for(int j=0; j<stop; j++)
{
if(sortArray[j]>sortArray[j+1])
{
temp = sortArray[j+1];
sortArray[j+1] = sortArray[j];
sortArray[j]=temp;
}
}
stop is the length of the array, and you are iterating through values of j = 0 to stop - 1. When j reaches stop - 1, the next element that is j+1 becomes stop (10 in this case). But since your array has a length of 10, sortArray[10] is not part of the array, but is referring to some other object in memory which is usually a garbage value. The garbage value is 10 in this case. When you swap sortArray[10] and sortArray[9], the garbage value becomes part of the array and the value at index 9 leaves the array. This keeps on happening till the outer loop ends.
The end result is that unless the garbage value < largest element in the array, the garbage value is pushed in the array and the greatest value of the array is put at sortArray[10] which is not part of the array. If the garbage value is greater than all the values of the array, it'll be found at sortArray[10] which is again not part of the array and your code will return the desired result.
Essentially, what you are doing is giving the function an array of 10 (or stop) elements, but the function is actually working with an array of 11 (or stop + 1) elements, with the last element being a garbage value. The simple fix is to change the conditional of the loop to j < stop - 1.
Note that if you had written this code in a managed (or a comparatively higher level) language like Java or C#, it would have raised an IndexOutOfBoundsException.
At index 9, j+1 is out of bounds. So to fix this, you only need to check till index 8
for(int counter = length-1; counter>=0; counter--)
{
for(int j=0; j<stop-1; j++)
{
if(sortArray[j]>sortArray[j+1])
{
temp = sortArray[j+1];
sortArray[j+1] = sortArray[j];
sortArray[j]=temp;
}
}
stop--;
}
Look carefully at the inner loop condition j<stop-1
I try to make a list of digit of consequence number from 1 to 100; for example, 123456789101112..... However, when I print out the result from the list_result; there is some strange number in my list_result vector. Here the following code:
int main()
{
vector<int> list_num;
vector<int> list_result;
int count =0;
for(int index = 1; index<=100; index++)
{
count = index;
if(index<10)
{
list_result.push_back(index);
}
else
{
while(count!=0)
{
list_num.push_back(count%10);
count=count/10;
}
for(int i=0; i<=list_num.size();i++)
{
list_result.push_back(list_num[list_num.size()-i]);
}
list_num.clear();
}
for(int i = 0; i<=list_result.size(); i++)
{
cout<<list_result[i];
}
}
return 0;
}
Anyone has any ideas? Thank,
Your program exhibits undefined behavior.
for(int i=0; i<=list_num.size();i++)
{
list_result.push_back(list_num[list_num.size()-i]);
}
Valid indexes into list_num are 0 through list_num.size()-1. Yet on the first iteration of this loop, when i == 0, you attempt to access list_num[list_num.size()]. There is no such element.
Igor Tandetnik described an issue in the for loop inside the else block, but I've identified another issue, this time in the output stage of the program.
Remember that indices are zero-based, which means they run from zero to the number of elements minus one. vector::size() returns the total number of elements, in this case 100. Because you're comparing this value with the index using a less-than-or-equal inequality, you end up trying to access element 100 on the final iteration of the loop, and element 100 does not exist since the range of valid indices is 0 to 99. When writing a loop that iterates through an array or vector, you should always compare indices with array/vector sizes using strict inequalities.
In the final for loop, replace the <= with a strict < comparison so that it stops at the actual last element and not afterwards:
for(int i = 0; i<list_result.size(); i++)
{
cout<<list_result[i];
}
Wikipedia has an easy-to-understand explanation of this common programming mistake, known as an off-by-one error.
I have a program that is supposed to read in values from user into a vector. My function is then supposed to keep a running sum and start from element 1 and compare element 2 to the sum(this point it is just element 1). Move to the next element, add element 2 to the sum and see if element 3 is greater than the sum of elements 1 and 2. I am supposed to print only the elements that are greater than the sum. I'm having trouble getting it to print out any values. Could someone please let me know what I might be doing wrong? Thanks
int main()
{
vector <int> theData;
int i;
cout<< "Enter in the list of integers ending with a -1" << endl;
do
{
cin >> i;
if (i==-1)
{
break;
}
theData.push_back(i);
}while(i!=-1);
int index = 1;
int runningSum = unsortedData[i];
largeValue(unsortedData, index, runningSum);
system("PAUSE");
return 0;
}
void largeValue(vector<int> myVector, int index, int runningSum)
{
int size = myVector.size();
if (index == size)
{
return;
}
if (myVector[index] > runningSum)
{
cout << myVector[index] << " ";
runningSum += myVector[index];
index = index +1;
largeValue(myVector, index, runningSum);
}
else if (myVector[index] < runningSum)
{
runningSum += myVector[index];
index = index + 1;
largeValue(myVector, index, runningSum);
}
}
There are several errors in your code:
int runningSum = unsortedData[i];
You probably meant index, not i. Both are wrong, though: the first index in the array is 0, not 1 (which is the value of index).
Also, your recursive function contains at least one error: you don’t consider that the current element equals the sum.
Another thing: you pass the vector to your function by value – not a good idea: for each call of the function, the whole vector is copied, which may take considerable time for medium-sized vectors. In “real” code, large data types should always be passed by (const) reference. Just change the function signature slightly:
void largeValue(vector<int> const& myVector, int index, int runningSum)
This way, you pass an unmodifiable reference of your vector to the function instead of copying it. Notice that this makes it impossible to modify the data of the vector inside the function.
Firstly, your function fails to meaningfully process the case when myVector[index] == runningSum.
Secondly, the initial value of runningSum is taken from unsortedData[i] which doesn't make any sense, since i is -1 at that time. You probably meant unsortedData[0].
Early in main you use theData and later you use unsortedData. I'm not sure why the compiler hasn't complained about unsortedData not being defined.