The following program is intended to check if a given element is in a given array, indices of array where the element occurs and number of times the element occurs. But, it doesn't give right results. I tried to replace poscount in seqsearch function with *poscount and did further changes for this pointer data type. Then the code works well. Why this is so?
#include <iostream>
using namespace std;
const int SIZE = 100;
void seqsearch(int[], int, int, int[], short);
int main() {
int array[SIZE], indices[SIZE];
int num, value;
short count = 0;
cerr << " Give number of elements in array : ";
cin >> num;
cerr << " Key in the array elements ";
for(int i = 0; i < num; i++) cin >> array[i];
cout << endl;
cerr << " Give the value to be searched : " << endl;
cin >> value;
cout << endl;
seqsearch(array, num, value, indices, count); // void function
if(count >= 0) {
cout << value << " found in array " << count << " times"
<< " at index positions " << endl;
for(int i = 0; i < count; i++) cout << indices[i] << " ";
cout << endl;
} else
cout << value << " not found in array " << endl;
return 0;
}
void seqsearch(int arr[], int size, int elm, int pos[], short poscount) {
int i, item;
poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[poscount] = i;
poscount = poscount + 1;
}
}
return;
}
The function seqsearch is supposed to return the result in pos and poscount, but the function takes poscount by-value which means that any changes you make to poscount inside the function, will be local to the function and not visible from the call site.
If you change the function to take the argument by-reference, the changes you make inside the function will actually be made to the variable used in the call to the function. Like this:
seqsearch(int arr[], int size, int elm, int pos[], short& poscount) // note short&
The int pos[] does not have the same problem because arrays decay into pointers, so it could have been int* pos instead - and that pointer points at the same array that you passed in at the call site.
Also note that the check after the call will make the program display "found in array" even if it isn't found in the array because the condition checks if count is zero or greater than zero.
if(count >= 0) { // should be if(count > 0) {
Suggestions unrelated to the problem in your question:
When the number of elements is not known at the time you compile your program, prefer to use a container which can grow dynamically, like a std::vector<int>. In your program you have a hardcoded limit of SIZE number of elements, but:
You will rarely use all of them.
You do not check if the user wants to enter more than SIZE elements and your program will gladly try to write out of bounds - which would cause undefined behavior.
Divide the program's subtasks into functions. It'll be easier to search for bugs if you can test each individual function separately.
Check that extracting values from std::cin actually succeeds.
int number;
if(std::cin >> number) { /* success */ } else { /* failure */ }
Check that the values entered makes sense too.
int wanted_container_elements;
if(std::cin >> wanted_container_elements && wanted_container_elements > 0) {
/* success */
} else {
/* failure */
}
poscount (or count in the context of the caller) in your code seems to be expected to be an output parameter.
To modify the passed value you must either have its address (a pointer) or a reference to the value.
Currently you are using "pass-by-value", meaning that poscount is a copy of count.
The original count stays untouched.
My personal favorite would be to return the value instead of using an out-parameter:
short seqsearch(int arr[], int size, int elm, int pos[]) {
int i, item;
short poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[poscount] = i;
poscount = poscount + 1;
}
}
return poscount;
}
count = seqsearch(array, num, value, indices);
Alternatively you can use a reference to manipulate the out-parameter:
void seqsearch(int arr[], int size, int elm, int pos[], short& poscount) {
int i, item;
poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[poscount] = i;
poscount = poscount + 1;
}
}
return;
}
seqsearch(array, num, value, indices, count);
And, as you already tried, you can also solve this by passing a pointer to the value:
void seqsearch(int arr[], int size, int elm, int pos[], short* poscount) {
int i, item;
*poscount = 0;
for(i = 0; i < size; i++) {
if(arr[i] == elm) {
pos[*poscount] = i;
*poscount = *poscount + 1;
}
}
return;
}
seqsearch(array, num, value, indices, &count);
When you pass your posscount argument, you pass a copy to the count variable in main, not the variable itself. That's why it works, when you pass it by pointer. You can also pass by reference. https://www.includehelp.com/cpp-tutorial/argument-passing-with-its-types.aspx
Related
I am supposed to be creating a program that asks a user to populate an array of size 10. There are three functions which by their name are self-explanatory; one fills up the array with elements, the second one displays the array horizontally, and the third function checks to see if a number entered by the user is an element in the array.
#include<iostream>
#include<iomanip>
void fillUpArray(int array[], int size);
void displayArray(int array[], int size);
bool isNumberPresent(int array[], int size, int SearchNum);
int main(){
int s = 10; //size of array
int A[s]; //array A with size s
int num; //search number
fillUpArray(A, s);
std::cout <<"\n";
displayArray(A, s);
std::cout << "\n";
std::cout << "Enter a number to check if it is in the array:\n";
std::cin >> num;
std::cout << std::boolalpha << isNumberPresent(A, s, num) << std::endl;
return 0;
}
void fillUpArray(int array[], int size)
{
std::cout << "Enter 10 integers to fill up an array, press enter after every number:\n";
for(int i = 0; i < size; i++){
std::cin >> array[i];
}
}
void displayArray(int array[], int size)
{
for(int j = 0; j < size; j++){
std::cout << array[j] << "\t";
}
}
bool isNumberPresent(int array[], int size, int SearchNum)
{
bool isPresent;
for(int k = 0; k < size; k++){
if(array[k] == SearchNum)
isPresent = true;
else
isPresent = false;
}
return isPresent;
}
That last function, which is a bool function, is not performing the way I thought it would. I thought by doing array[k] whatever index k is then it should spit out the element in the array and then with the expression if(array[k] == SearchNum) it should then work as if(element == SearchNum) but that doesn't seem to be the case and the output is always false.
The for loop in your isNumberPresent function will run to the end of the array (until k equals size) unconditionally; in each run of that loop, you set the value of the isPresent variable according to whether or not the current element is a match for searchNum, overwriting the previous value. So, the function, as it stands, will simply return whether or not the last element in the array is the same as the given test number.
You can simplify that function and remove the need for the local variable: if you find a match, then return true immediately; if the loop ends without finding a match, then return false:
bool isNumberPresent(int array[], int size, int SearchNum)
{
for(int k = 0; k < size; k++){
if(array[k] == SearchNum) return true; // Found a match - we can return immediately
}
return false; // We didn't find a match
}
Note, also, that Variable Length Arrays (VLAs) are not part of Standard C++, though some compilers (like GNU g++) support them (they are part of the C language according to the C99 Standard). In your program, as you only use one (fixed) value for the array size, you can conform to Standard C++ simply by qualifying that s is a const:
int main()
{
const int s = 10; //size of array - make this a "const" be 'proper' C++
int A[s]; //array A with size s
//...
For this homework problem, we need to create a new jagged array with the code provided by our professor, print the array, and calculate the max, min, and sum of the array's contents. We are only allowed to edit the createAndReturnJaggedArray() and printAndThenFindMaxMinSum(int**,int*,int*,int*) functions, as the rest of the code was provided for us so we could check that we get the correct output.
I'm able to get the program to run, however after printing an initial string it terminates the program giving me the error terminate called after throwing an instance of 'std::bad_array_new_length' what(): std::bad_array_new_length. I believe the problem is in my creation of the jagged array and my allocation of memory for the columns part of the array, however I used the notes we were given as reference and have no idea where the problem is coming from. The entire program is provided below. Thanks for any help!
EDIT/NOTE: We haven't learned vectors yet so we're not allowed to use them.
#include <iostream>
#include <climits>
using namespace std;
class JaggedArray {
public:
int numRows;
int *numColumnsInEachRow;
JaggedArray() {
numRows = 11;
numColumnsInEachRow = new int[numRows];
for (int i = 0; i < numRows; i++) {
if (i <= numRows / 2) {
numColumnsInEachRow[i] = i + 1;
} else {
numColumnsInEachRow[i] = numRows - i;
}
}
readComputeWrite();
}
int **createAndReturnJaggedArray() { // COMPLETE THIS FUNCTION
int **A = new int*[numRows];
for(int i=0;i<numRows;i++){ //allocate columns in each row
A[i] = new int[numColumnsInEachRow[i]];
for(int j=0;j<numColumnsInEachRow[i];j++){
if(i <= numRows/2)
A[i][j] = (i + j);
else
A[i][j] = -1 * (i+j);
}
}
return A;
}
void printAndThenFindMinMaxSum(int **A, int *maxPtr, int *minPtr, int *sumPtr) { // COMPLETE THIS FUNCTION
maxPtr = new int[INT_MIN];
minPtr = new int[INT_MAX];
sumPtr = 0;
for(int i=0;i<numRows;i++){
for(int j=0;j<numColumnsInEachRow[i];j++){
//1. print array
if (j == (numColumnsInEachRow[i]-1))
cout << A[i][j] << endl;
else
cout << A[i][j] << " ";
//2. compute max, min, and sum
sumPtr += A[i][j];
if (A[i][j] > *maxPtr)
maxPtr = new int[A[i][j]];
if (A[i][j] < *minPtr)
minPtr = new int[A[i][j]];
}
}
}
void print(int max, int min, int sum) {
cout << endl;
cout << "Max is " << max << "\n";
cout << "Min is " << min << "\n";
cout << "Sum is " << sum << "\n";
}
void readComputeWrite() {
int max, min, sum;
int **A = createAndReturnJaggedArray();
cout << "*** Jagged Array ***" << endl;
printAndThenFindMinMaxSum(A, &max, &min, &sum);
print(max, min, sum);
}
};
int main() {
JaggedArray jaf;
return 0;
}
As #user4581301 hints at, your problem is in printAndThenFindMinMaxSum. Simply changing it to the below solves your problem:
void printAndThenFindMinMaxSum(int **A, int &maxPtr, int &minPtr, int &sumPtr) { // COMPLETE THIS FUNCTION
maxPtr = INT_MIN;
minPtr = INT_MAX;
sumPtr = 0;
.
.
.
sumPtr += A[i][j];
if (A[i][j] > maxPtr)
maxPtr = A[i][j];
if (A[i][j] < minPtr)
minPtr = A[i][j];
}
}
}
We also need to change readComputeWrite to:
void readComputeWrite() {
int max, min, sum;
int **A = createAndReturnJaggedArray();
cout << "*** Jagged Array ***" << endl;
printAndThenFindMinMaxSum(A, max, min, sum);
print(max, min, sum);
}
I would also recommend changing the name minPtr, maxPtr, and sumPtr to something more appropriate, as they aren't pointer at this point and represent primitive values.
You will note, that I changed pointers to references as this is a more natural adaptation for this type of operation. Essentially, passing by reference allow the user to operate on the passed value in a straightforward manner without the tedious task of making sure you dereference things at the appropriate time. It also allows one to operate in a less error prone manner.
Again, as #user4581301 shrewdly points out, the intent of this assignment was probably to deal with pointers. As such, there are a few things that need to be changed if the OP cannot use references. Observe:
void printAndThenFindMinMaxSum(int **A, int *maxPtr, int *minPtr, int *sumPtr) { // COMPLETE THIS FUNCTION
*maxPtr = INT_MIN; // Make sure to deference before assigning
*minPtr = INT_MAX; // Make sure to deference before assigning
*sumPtr = 0; // Make sure to deference before assigning
for(int i=0;i<numRows;i++){
for(int j=0;j<numColumnsInEachRow[i];j++){
//1. print array
if (j == (numColumnsInEachRow[i]-1))
cout << A[i][j] << endl;
else
cout << A[i][j] << " ";
//2. compute max, min, and sum
*sumPtr += A[i][j]; // Make sure to deference before assigning
if (A[i][j] > *maxPtr) // Make sure to deference before comparing
*maxPtr = A[i][j]; // Make sure to deference before assigning
if (A[i][j] < *minPtr) // Make sure to deference before comparing
*minPtr = A[i][j]; // Make sure to deference before assigning
}
}
}
And the readComputeWrite can stay unaltered from the OP's original attempt.
In the OP's code, they are mainly forgetting to deference before assigning/comparing.
At the moment, I am stumped and cannot progress on this problem. Any help or guidance would be greatly appreciated. The first part is working, however when I try to return the # of user inputs in the second part I get a Segmentation Fault. Below are the descriptions of both parts::
P2.1 Write a program consisting of main and displayArray functions. The main function declares an integer array with 10 elements and at the same time initializes them with up to 10 arbitrary values. The main function then calls displayArray function to display the contents of the array.
P2.2 Expand P2.1 with an additional fillArray function that prompts the user to enter up to 10 (size of the array) integers. Since a statically allocated array is often partially filled with values less than the actual size or storage capacity of the array (10 in our case), so the fillArray function must return a positive integer value representing the actual # of input values entered by the user.
#include <iostream>
using namespace std;
int displayArray(int arr[]);
int fillArray(int newArray[], int &inputs);
const int size = 10;
int main() {
int x, inputs = 0;
int arr[size] = {0,1,2,3,4,5};
int newArray[] = {};
displayArray(arr);
cout << "Enter .5 when finished. ";
fillArray(newArray, inputs);
cout << inputs;
cin >> x;
return 0;
}
int displayArray(int arr[]) {
for (int i = 0; i < size; i++)
cout << arr[i] << " " << endl;
}
int fillArray(int newArray[], int &inputs) {
for(int i = 0; ; i++) {
cout << "Enter an integer: " << endl;
cin >> newArray[i];
if(newArray[i] == .5) {
inputs = i + 1;
return inputs;
break;
}
}
}
You do not reserve memory for your newArray, since int newArray[] = {} will allocate an array of size 0 (actually not even defined as far as I know). So when calling fillArray, you will exceed array bounds.
Write
int newArray[10] = { 0 }
and it should at least work if you do not enter more than 10 values then.
Further, in fillArray, to not run out of bounds, I'd write...
int fillArray(int newArray[], int &inputs) {
for(inputs = 0; inputs < 10 ; inputs++) {
cout << "Enter an integer: " << endl;
cin >> newArray[i];
if(newArray[i] == 0) {
break;
}
}
inputs++;
return inputs;
}
Note further that the newArray[i] == .5 is at least misleading, since newArray is of type int and .5 is a floating point value. It will never evaluate to true, since the integral value newArray[i] will be converted to a float before comparison, and this conversion will never result in 0.5.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I've been learning c++ recently (coming from java) and I am attempting to count the number of repeating values in an array. For some reason the array is not being properly passed to my counter function.
#include <iostream>
#include <time.h>
using namespace std;
//quicksort for int arrays, left should be left index (0), right is right index(last one)
void quSort(int input[], int left, int right);
//binary search will return the index of the target or -1 if not found
int biSearch(int input[], int target, int iLeft, int iRight);
//count reapeats in the array with biSearch
int countRepeats(int input[], int target);
int main()
{
srand((unsigned int) time(0));
int test[1000];
//generate 100 random numbers under 1000
for(int i = 0; i < 1000; i++)
test[i] = rand()%1000;
//output test original
cout << "orig: ";
for(int i = 0; i < sizeof(test)/sizeof(*test); i++)
{
cout << test[i] << " ";
}
cout << endl << endl;
//sorting
quSort(test,0,( (sizeof(test)/sizeof(*test))-1));
cout << "sorted: ";
for(int i = 0; i < sizeof(test)/sizeof(*test); i++)
{
cout << test[i] << " ";
}
//binary search test
int target;
int iTarget;
cout << "\nenter target: ";
cin >> target;
iTarget = biSearch(test,target,0,sizeof(test)/sizeof(*test));
cout << "\n the target is at index: " << iTarget << " :: test[" << iTarget << "] = " << test[iTarget];
//count repeats
cout << "\nWith " << countRepeats(test,target) << " repeats";
system("pause");
return 0;
}
//quicksort function; effiecent array sorter; important for furture array analysis!!!
void quSort(int input[], int left, int right)
{
int pivot = input[(left+right)/2];
int l = left;//to control loop
int r = right;
while(l <= r)//will get smaller over iterations
{
int placeHold;// for use in swap, temp number
//finds value higher than the pivot from left
while(input[l] < pivot)
l++;
//find value lower than pivot on right
while(input[r] > pivot)
r--;
//swapper
if(l <= r)
{
//if the value greater than pivot is to the left of the value
//lessser than pivot
placeHold = input[l];
input[l] = input[r];
input[r] = placeHold;
l++;
r--;
}
//recursion to sort whole array until l=r
if(left<r)
quSort(input, left, r);
if(l < right)
quSort(input, l , right);
}
}
//binary search function; array MUST be sorted
int biSearch(int input[], int target, int iLeft, int iRight)
{
if(iLeft > iRight)
return -1;
else
{
int iMid = ((iLeft+iRight)/2);
if(input[iMid] > target)
return biSearch(input, target, iLeft, iMid-1);
else if(input[iMid] < target)
return biSearch(input, target, iMid+1, iRight);
else
return iMid;//target found
}
}
//Must be sorted
int countRepeats(int *input, int target)
{
int holder[sizeof(input)/sizeof(*input)];
int biSResult;
int counter = 0;
biSResult = biSearch(input,target,0,sizeof(input)/sizeof(*input));
//bug test
cout<<"c++" << biSResult << "c++";
//
while(biSResult != -1)
{
holder[biSResult] = target;
counter++;
input[biSResult] = 0;
quSort(input,0,( (sizeof(input)/sizeof(*input))-1));
biSResult = biSearch(input,target,0,sizeof(input)/sizeof(*input));
}
biSResult = biSearch(holder,target,0,sizeof(holder)/sizeof(*holder));
while(biSResult != -1)
{
input[biSResult] = target;
holder[biSResult] = 0;
quSort(holder,0,( (sizeof(holder)/sizeof(*holder))-1));
biSResult = biSearch(input,target,0,sizeof(holder)/sizeof(*holder));
}
return counter;
}
If anyone knows why this is happening it would be a great help
There are several issues in countRepeats():
(1) as already mentionned in other answers, there is an error in the way parameters are passed. There is no way to calculate the size of the array in the function whether you use int* or int[]. So best pass arguments to this function as you do in quSort() by giving not only the array address but also a start and an end counter.
(2) your programme will crash if the user would asks for a target of 0 : your while(biSResult != -1) would loop for ever.
(3) this function sorts again and again the array. This seems to be pretty bad for performance. Why don't you make use of the fact that the array is already sorted ? You could start counting from the found index . Just think that you'd have to count before and after this position, because you're not sure that iTarget is the very first occurence. This could look like:
int countRepeats(int input[], int pos, int start, int end )
{
if (pos<start || pos>=end) // you never know !
return 0;
int counter = 1;
for (int i=pos-1; i>=start && input[i]==input[pos]; i--)
counter++;
for (int i=pos+1; i<end && input[i]==input[pos]; i++)
counter++;
return counter;
}
By the way, I've tested it and it works. You just have to adapt the prototype and call it in your main function with
cout << "\nWith " << countRepeats(test, iTarget, 0,
sizeof(test)/sizeof(*test) ) << " repeats";
The first parameter of function countRepeats declared as
int countRepeats(int *input, int target)
that is it has type int *
So
sizeof(input)/sizeof(*input)
is equivalent to
sizeof( int * )/sizeof( int )
If for example sizeof( int * ) is equal to 4 and sizeof( int ) also is equal to 4 then the expression will be equal to 1. That is the value of the expression does not depend on how many elements the array that was passed to the function as argument has.
You should pass the size of the array explicitly as an argument of the function. So th function should be declared as
int countRepeats(int *input, int n, int target);
Or you could declare the first parameter of the function as a reference to array.
You can't calculate the size of an array inside a function that received a pointer to the array. This is because the value of sizeof(input) inside your counting function is just going to return the size of a pointer to an int. So sizeof(input)/sizeof(*input) will always be 1.
If you instead calculate the size of the array and store it as an int in main, then pass that to your counting function it should work. So changing your counting function call to:
cout << "\nWith " << countRepeats(test,target,sizeof(test)/sizeof(*test)) << " repeats";
And your countRepeats declaration to:
int countRepeats(int input[], int target, int size);
Then inside your countRepeats definition, everywhere you had (sizeof(input)/sizeof(*input)) you can just say size:
int countRepeats(int *input, int target, int size)
{
int holder[size];
int biSResult;
int counter = 0;
biSResult = biSearch(input,target,0,size);
//bug test
cout<<"c++" << biSResult << "c++";
//
while(biSResult != -1)
{
holder[biSResult] = target;
counter++;
input[biSResult] = 0;
quSort(input,0,(size-1));
biSResult = biSearch(input,target,0,size);
}
biSResult = biSearch(holder,target,0,size);
while(biSResult != -1)
{
input[biSResult] = target;
holder[biSResult] = 0;
quSort(holder,0,(size-1));
biSResult = biSearch(input,target,0,size);
}
return counter;
}
But you should really just use std::vector instead. Could have had std::vector<int> test (1000); and since your countRepeats changes your array through calls to quSort you can pass the vector as a reference (just as efficient as passing a pointer, allows changes to affect the original): int countRepeats(std::vector<int>&, int target); and you can always find its size by test.size()
I'm a beginner to c++ and I'm trying to write an recursive algorithm that returns the sum of every element in an array with a value less than x.
Here is my code:
#include <iostream>
using namespace std;
int sumOfElement(int xList[],int x, int lengthOfArray){
int sum = 0;
if (lengthOfArray == 0)
return sum;
else
for (int i=0; i <= lengthOfArray; i++) {
if(xList[i] < x)
return sum + xList[i];
else
sumOfElement(xList,x,lengthOfArray-1);
}
}
int main() {
cout << "Size of Array: ";
int size;
cin >> size;
int *xList = new int[size];
//Inputing array.
cout << "Enter elements of array followed by spaces: ";
for (int i = 0; i<size; i++)
cin >> xList[i];
cout << "Enter the integer value of x: " <<endl;
int limit;
cin >> limit;
cout << "Sum of every element in an array with a value less than x: " << sumOfElement(xList,limit,size) << endl;
return 0;
}
I'm using Visual Studio, while I was running the code, I got this warning: "warning C4715: 'sumOfElement' : not all control paths return a value. " And the program always stop executing when it asks me to enter the integer value for x.
What's wrong with my code?
Your approach here isn't really recursive. The idea with recursion is to consider a base case, and then consider how to reduce the problem at each step until you get to the base case.
For this problem:
The base case is when the length of the array is zero. In this case we return a sum of zero. (Intuitively: if the array is empty then we're adding nothing, giving a sum of zero.)
In order to reduce our array we look at the last element of the array (ie. at lengthOfArray - 1). We process this element: if it's less than x we add it, if it's not then we ignore it. We then get the result of processing the rest of the array by the same means (by calling the same function, but with a different array length), and add our result if applicable.
So, some example code:
int sumOfElement(int xList[], int x, int lengthOfArray){
if (lengthOfArray == 0) {
// base case
return 0;
} else {
int value = xList[lengthOfArray-1];
if (value < x) {
// process the rest of the array and add our result
return value + sumOfElement(xList, x, lengthOfArray - 1);
} else {
// process the rest of the array
return sumOfElement(xList, x, lengthOfArray - 1);
}
}
}
for (int i=0; i <= lengthOfArray; i++)
{
if(xList[i] < x)
return sum + xList[i];
else sumOfElement(xList,x,lengthOfArray-1);
}
You shouldn't have a for-loop, and recursive functions should "return" the deeper call, so
int retVal = 0;
if(xList[lengthOfArray-1] < x)
retval = xList[lengthOfArray-1]
return retVal + sumOfElement(xList,x,lengthOfArray-1);