C++ Vectors Passing by Reference Syntax - c++

I am having issues passing the the return values of my reference into the main function.The code is supposed to return both the the amount of even and odd numbers the user enters. I think my syntax in the pass are wrong.
using namespace std;
int numOfOddEven(vector<int>);
int main ()
{
int numValues, odd;
vector<int> values;
cout << "Enter number of values: ";
cin >> numValues;
for(int count = 0; count < numValues; count++)
{
int tempValue;
cout << "Enter value: ";
cin >> tempValue;
values.push_back(tempValue);
}
cout <<"Odd numbers: " << numOfOddEven(odd);
}cout <<"Even numbers: " << numOfOddEven(even);
int numOfOddEven(vector<int> vect)
{
int odd = 0;
int even = 0;
for (int i = 0; i < vect.size(); i++)
if (i/2 == 1 )
++even;
else
++odd;
return odd;
return even;
}

Handful of things I see wrong with this code
You cannot return two elements like you are trying
You are not passing by reference anywhere
What you are passing to numofOddEven is not what the function is expecting(an int vs a vector)
Learn how functions work, what pass by reference actually means, what return does, and what taking a modulus of a number means in c++. Then try approaching this again.

You're calling with wrong parameters and using wrong logic
odd =numOfOddEven(values); //Use values
cout <<"Odd numbers: " << odd;
cout <<"Even numbers: " << values.size()- odd; //Get even count using this
In numOfOddEven just return the odd count
Fix Logic : -
int numOfOddEven(vector<int> vect)
{
int odd = 0;
//int even = 0;
for (int i = 0; i < vect.size(); i++)
if (vect[i]%2 != 0 )
++odd;
return odd;
//return even;
}
Another approach would be to use std::count_if
int numodd = std::count_if(values.begin(), values.end(),
[](int i) {return i % 2 != 0;});
int numeven = values.size() - numodd ;

int numOfOddEven(vector<int> & vect)
{
int odd = 0;
int even = 0;
for (int i = 0; i < vect.size(); i++)
if (vect[i]%2 == 1 )
++even;
else
++odd;
return odd;
}
int main ()
{
int numValues, odd;
vector<int> values;
cout << "Enter number of values: ";
cin >> numValues;
for(int count = 0; count < numValues; count++)
{
int tempValue;
cout << "Enter value: ";
cin >> tempValue;
values.push_back(tempValue);
}
cout <<"Odd numbers: " << numOfOddEven(values);
cout <<"Even numbers: " << numValues - numOfOddEven(values);
cin.get();
cin.get();
return 0;
}

References are defined in the function declaration/signature. For instance:
void fct( int &ref1, int &ref2)
{
ref1 = 1;
ref2 = 2;
}
int ref1, ref2;
fct(ref1, ref2);
No need for any returns. The compiler, when it sees the &, it considers it as a pointer but in code, you consider it as a variable.

To address the question in your subject:
int numOfOddEven(vector<int> vect) { }
Add a & before vect :
int numOfOddEven(vector<int> & vect) { }
Then vect will be passed by reference instead of copied. In regards to your return values, pass them in as references also and then declare the function of type void:
void numOfOddEven(vector<int> & vect, int & countodd, int & counteven) { }
Then just modify those variables in the function and don't return anything.

The first place to look is the declaration:
int numOfOddEven(vector<int>);
This returns one int, not two. You have to change something if you want to return two (independent) pieces of information. If you want to return two ints, you could write a function with this type:
pair<int,int> numOfOddEven(vector<int>);
Then, at the end of the function, you can return with return make_pair(num_odds, num_evens). Then, you would need also to do something like this to actually accept the returned values:
tie(odd, even) = numOfOddEven(values);
But, that's probably too complex for a beginner. You want to find another, roundabout, way to "return" two numbers from one function call.
void numOfOddEven(vector<int>, int&, int&);
Note the return type is not void. This function doesn't really return anything. But you can pass in your two variables odd and even by reference to this. When you say "passing by reference", this is probably what you mean.
... more code required ... [ community-wiki :-) ]
But, again! It's obvious that every number is odd or even. Therefore, it is sufficient to just return one number, the odd number. Then you can calculate (within main) that the number of even numbers is simply the total size of the vector minus the number of odd numbers.

First of all, you are not passing anything by reference in your existing code. If you want to pass the vector by reference, you need to declare your function like this:
int OddCount(const std::vector<int>& v)
// ................................^ That denotes a reference
{
return std::count_if(v.begin(), v.end(), [](int i)
{
return i % 2;
});
}
int EvenCount(const std::vector<int>& v)
{
return std::count_if(v.begin(), v.end(), [](int i)
{
return !(i % 2);
});
}
NOTE: Your logic for determining an odd/even is fixed in both of the above functions. Your method is not correct (unless you think 2 is the only even number).
Second, you never declared an even vector (and there is no need to, nor is there a need to declare an odd vector). So you should modify your output statements:
cout << "Odd Numbers: " << OddCount(values) << std::endl;
cout << "Even Numbers: " << EvenCount(values) << std::endl;
If you want both values to be returned from a single function call, there are a few ways to do it. The "simplest" way would be to return a std::pair<int, int>:
std::pair<int, int> CountOddsAndEvens(const std::vector<int>& v)
{
int evens = std::count_if(v.begin(), v.end(), [](int i)
{
return !(i % 2);
});
int odds = v.size() - evens;
return std::make_pair(evens, odds);
}
Alternatively, you could pass them in as output parameters:
void CountOddsAndEvens(const std::vector<int>& v, int& evens, int& odds)
{
evens = std::count_if(v.begin(), v.end(), [](int i)
{
return !(i % 2);
});
odds = v.size() - evens;
}
Both of which would require you to make changes to your current output calls:
std::pair<int, int> results = CountOddsAndEvens(values);
std::cout << "Odds = " << results.second << ", Evens = " << results.first << std::endl;
Or
int evens, odds;
CountOddsAndEvens(values, evens, odds);
std::cout << "Odds = " << odds << ", Evens = " << evens << std::endl;

Related

How to not repeat code in calculation functions?

I have made a simple program that performs basic arithmetic operations on all the elements of a given array. But the problem is that the code is very repetitive and it's not a good practice to write repeated code and I can't come up with a solution to this problem.
How can we minimize code repetition in this program?
int add(int numcount, int numarr[]){
int total = numarr[0];
// add all the numbers in a array
for (int i = 1; i < numcount; i++){
total += numarr[i];
}
return total;
}
int sub(int numcount, int numarr[]) {
int total = numarr[0];
// subtract all the numbers in array
for (int i = 1; i < numcount; i++){
total -= numarr[i];
}
return total;
}
int mul(int numcount, int numarr[]) {
int total = numarr[0];
// multiply all the numbers in array
for (int i = 1; i < numcount; i++){
total *= numarr[i];
}
return total;
}
int main(int argc, char* argv[]){
const int n = 5;
int arr[n] = {1, 2, 3, 4, 5};
cout << "Addition: " << add(n, arr) << endl;
cout << "Subtraction: " << sub(n, arr) << endl;
cout << "Multiplication: " << mul(n, arr) << endl;
}
How can we minimize code repetition in this program?
Generically, by identifying the repeated structure and seeing whether we can either abstract it out, or find an existing name for it.
The repeated structure is just setting the running result to the first element of a container, and using a binary function to combine it with each subsequent element in turn.
Take a look at the Standard Algorithms library and see if any existing function looks similar
std::accumulate can do what we need, without any extra arguments for the add, and with just the appropriate operator function object for the others
So, you can trivially write
int add(int numcount, int numarr[]){
return std::accumulate(numarr, numarr+numcount, 0);
}
// OK, your sub isn't actually trivial
int sub(int numcount, int numarr[]){
return std::accumulate(numarr+1, numarr+numcount, numarr[0],
std::minus<int>{});
}
// could also be this - honestly it's a little hairy
// and making it behave well with an empty array
// requires an extra check. Yuck.
int sub2(int numcount, int numarr[]){
return numarr[0] - add(numcount-1, numarr+1);
}
etc.
It would be slightly nicer to switch to using std::array, or to use ranges if you're allowed C++20 (to abstract iterator pairs over all containers).
If you must use C arrays (and they're not decaying to a pointer on their way through another function), you could write
template <std::size_t N>
int add(int (&numarr)[N]){
return std::accumulate(numarr, numarr+N, 0);
}
to save a bit of boilerplate (passing numcount everywhere is just an opportunity to get it wrong).
NB. as mentioned in the linked docs, std::accumulate is an implementation of a left fold. So, if the standard library didn't provide accumulate, there's still an existing description of the "thing" (the particular "higher-order function") we're abstracting out of the original code, and you could write your own foldl template function taking the same std::plus, std::minus etc. operator functors.
You can use std::accumulate:
auto adder = [](auto accu,auto elem) { return accu + elem; };
auto multiplier = [](auto accu, auto elem) { return accu * elem; };
auto sum = std::accumulate(std::begin(arr),std::end(arr),0,adder);
auto prod = std::accumulate(std::begin(arr),std::end(arr),0,multiplier);
The result of sub is just 2*arr[0] - sum.
Be careful with the inital value for std::accumulate. It determines the return type and multiplying lots of int can easily overflow, perhaps use 0LL rather than 0.
In cases where std::accumulate nor any other standard algorithm fits, and you find yourself writing very similar functions that only differ by one particular operation, you can refactor to pass a functor to one function that lets the caller specifiy what operation to apply:
template <typename F>
void foo(F f) {
std::cout << f(42);
}
int identity(int x) { return x;}
int main() {
foo([](int x) { return x;});
foo(identity);
}
Here foo prints to the console the result of calling some callable with parameter 42. main calls it once with a lambda expression and once with a free function.
How can we minimize code repetition in this program?
One way to do this is to have a parameter of type char representing the operation that needs to be done as shown below:
//second parameter denotes the operator which can be +, - or *
int calc(int numcount, char oper, int numarr[])
{
//do check here that we don't go out of bounds
assert(numcount > 0);
int total = numarr[0];
// do the operatations for all the numbers in the array
for (int i = 1; i < numcount; i++){
total = (oper == '-') * (total - numarr[i]) +
(oper == '+') * (total + numarr[i]) +
(oper == '*') * (total * numarr[i]);
}
return total;
}
int main()
{
int arr[] = {1,2,3,4,5,6};
std::cout << calc(6, '+', arr) << std::endl; //prints 21
std::cout << calc(6, '-', arr) << std::endl; //prints -19
std::cout << calc(6, '*', arr) << std::endl; //prints 720
}
Working demo

Eliminating duplicates Q

I had a task from one course on Udemy to create a program which eliminates duplicates from array and i failed so I have looked to my instructors code and I don't understand few things.
Why don't you have to write the capacity of array (function input) ? it is because of that you already has written the elements of array so it was recognized how long it is ?
the if statement for not true Boolean: the counter is initialized to zero so for the first time when unique_data[counter++]=numbers[i=0] is counter also zero a then it is incremented ?
sorry for asking these questions but I am little bit worried that i have not been able to solve this myself
void unique_numbers( int numbers[], unsigned int collection_size){
int unique_data [20];
unsigned int unique_counter{};//Initialized to zero. Counts the elements we have in
//the unique_data array
for(unsigned int i{}; i < collection_size; ++i){
bool already_in{false};
//See if the element is not already in our unique_data
for(unsigned int j{};j < unique_counter; ++j){
if(unique_data[j] == numbers[i]){
already_in = true;
break;
}
}
if(!already_in){
unique_data[unique_counter++] = numbers[i];
}
}
std::cout << "The collection contains " << unique_counter << " unique numbers, they are : ";
for(unsigned int i{};i < unique_counter ; ++i){
std::cout << unique_data[i] << " ";
}
I have modified your program with std::vector and std::find . The logic is the same. Now it is more readable. Hope you will understand it.
#include <iostream>
#include <vector>
#include <algorithm>
void unique_numbers(int numbers[], unsigned int collection_size)
{
std::vector<int> unique_data;
for (unsigned int i{}; i < collection_size; ++i)
{
//Find numbers[i] in unique_data. If it is not found insert it in unique_data
auto it = std::find(unique_data.begin(), unique_data.end(), numbers[i]);
if (it == unique_data.end())
{
unique_data.push_back(numbers[i]);
}
}
//print unique_data vector
std::cout << "The collection contains " << unique_data.size() << " unique numbers, they are : ";
for (const auto& v : unique_data){
std::cout << v << " ";
}
std::cout << std::endl;
}
int main()
{
int a[] = { 1, 2, 3, 4, 5, 4, 3, 2, 1 };
unsigned int n = sizeof(a)/sizeof(int);
unique_numbers(a, n);
}

Run-time check: stack around variable was corrupted

I am creating a program that rewrites an array with values from a file. I have linked the code below. When running the file I get the error "Run-time check failure, stack around 'arr' variable was corrupted.
Also, the output of the program returns all the array locations with the same number,
arr[0] = -858993460
The numbers in the file, separated by a line are:
12
13
15
#include<iostream>;
#include<fstream>;
using namespace std;
template <class T>
void init(T * a, int size, T v)//done
{
for (int i = 0; i < size; i++)
{
a[size] = v;
}
}
bool getNumbers(char * file, int * a, int & size)//not done
{
int count = 0;
ifstream f(file);
while (f.good() == true && count < 1)
{
f >> a[count];
count++;
}
if (size > count)
{
return true;
}
else if (size < count)
{
return false;
}
}
void testGetNumbers()
{
int arr[5];
int size = 5;
cout << "Testing init and getNumbers." << endl;
init(arr, 5, -1);
cout << "Before getNumbers: " << endl;
for (int i = 0; i < size; i++)
{
cout << "arr[" << i << "] = " << arr[i] << endl;
}
if (getNumbers("nums.txt", arr, size))
{
cout << size << " numbers read from file" << endl;
}
else
{
cout << "Array not large enough" << endl;
}
cout << "After getNumbers: " << endl;
for (int i = 0; i < size; i++)
{
cout << "arr[" << i << "] = " << arr[i] << endl;
}
cout << endl;
}
int main()
{
testGetNumbers();
return 0;
}
This line in the first loop looks like having error.
a[size] = v;
It causes out of array bound access and memory/stack corruption. It should be
a[i] = v;
Starting with the main function, the line
return 0;
... is not necessary because that's the default return value for main. I would remove it, some people insist on having it, I think most people don't care. But it's always a good idea to be fully aware of what the code expresses, implicitly or explicitly, so: returning 0 expresses that the program succeeded.
For an explicit main return value I recommend using the names EXIT_SUCCESS and EXIT_FAILURE from the <stdlib.h> header.
Then it's much more clear.
main calls testGetNumbers, which, except for an output statement, starts like this:
int arr[5];
int size = 5;
init(arr, 5, -1);
As it happens the init function is has Undefined Behavior and doesn't fill the array with -1 values as intended, but disregard. For now, look only at the verbosity above. Consider writing this instead:
vector<int> arr( 5, -1 );
Using std::vector from the <vector> header.
Following the call chain down into init, one finds
a[size] = v;
That attempts to assign value v to the item just beyond the end of the array.
That has Undefined Behavior.
Should probably be
a[i] = v;
But as noted, this whole function is redundant when you use std::vector, as you should unless strictly forbidden by your teacher.
Back up in testGetNumbers it proceeds to call getNumbers, in that function we find
ifstream f(file);
while (f.good() == true && count < 1)
{
f >> a[count];
count++;
}
Generally one should never use f.good() or f.eof() in a loop condition: use f.fail(). Also, ~never compare a boolean to true or false, just use it directly. Then the loop can look like this:
ifstream f(file);
while (!f.fail() && count < 1)
{
f >> a[count];
count++;
}
Tip: in standard C++ you can write ! as not and && as and. With the Visual C++ compiler you have to include the <iso646.h> header to do that.
Disclaimer: the fixes noted here do not guarantee that the loop is correct for your intended purpose. Indeed the increment of count also when the input operation fails, looks probably unintended. Ditto for the loop limit.
The function continues (or rather, ends) with
if (size > count)
{
return true;
}
else if (size < count)
{
return false;
}
This has a big problem: what if size == count? Then the execution continues to fall off the end of the function without returning a value. This is again Undefined Behavior.
I leave it to you to decide what you want the function to return in that case, and ensure that it does that.
In your init function...
template <class T>
void init(T * a, int size, T v)//done
{
for (int i = 0; i < size; i++)
{
a[size] = v;
}
}
Nope:
a[size] = v;
Yup:
a[i] = v;

Deleting element from an array in c++

I have read others posts, but they don't answer my problem fully.
I'm learning to delete elements from an array from the book and try to apply that code.
As far as I can grasp I'm passing array wrong or it is sending integer by address(didn't know the meaning behind that).
#include <iostream>
#include <cstdlib>
using namespace std;
void delete_element(double x[], int& n, int k);
int main()
{
// example of a function
int mass[10]={1,2,3,45,12,87,100,101,999,999};
int len = 10;
for(int i=0;i<10;i++)
{
cout<<mass[i]<<" ";
};
delete_element(mass[10],10&,4);
for(int i=0;i<10;i++)
cout<<mass[i]<<" ";
return 0;
}
void delete_element(double x[], int& n, int k)
{
if(k<1 || k>n)
{
cout<<"Wrong index of k "<<k<<endl;
exit(1); // end program
}
for(int i = k-1;i<n-1;i++)
x[i]=x[i+1];
n--;
}
There are a couple of errors in your code. I highlight some of the major issues in question 1-3:
You call exit, which does not provide proper cleanup of any objects since it's inherited from C. This isn't such a big deal in this program but it will become one.
One proper way too handle such an error is by throwing an exception cout<<"Wrong index of k "<< k <<endl;
exit(1);
Should be something like this:
throw std::runtime_error("invalid index");
and should be handled somewhere else.
You declare function parameters as taking a int& but you call the function like this: delete_element(mass[10],10&,4); 10& is passing the address of 10. Simply pass the value 10 instead.
You are "deleting" a function from a raw C array. This inherently doesn't make sense. You can't actually delete part of such an array. It is of constant compile time size created on the stack. The function itself doesn't do any deleting, try to name the functions something more task-oriented.
You are using C-Arrays. Don't do this unless you have a very good reason. Use std::array or std::vector. These containers know their own size, and vector manages it's own memory and can be re sized with minimal effort. With containers you also have access to the full scope of the STL because of their iterator support.
I suggest you rewrite the code, implementing some type of STL container
Line 15: syntax error
you can't pass a number&
If you want to pass by reference, you need to create a variable first, like:
your delete_element function signature conflicts with your declared arrays. Either use a double array or int array and make sure the signatures match.
delete_element(mass, len , 4);
when you write the name of an array without the brackets, then it's the same as &mass[0]
ie. pointer to the first element.
complete changes should be:
#include <iostream>
#include <cstdlib>
using namespace std;
void delete_element(int x[], int& n, int k);
int main(){
// example of a function
int mass[10] = { 1, 2, 3, 45, 12, 87, 100, 101, 999, 999 };
int len = 10;
for (int i = 0; i<10; i++){ cout << mass[i] << " "; };
cout << endl;
delete_element(mass, len , 4);
for (int i = 0; i<10; i++)cout << mass[i] << " ";
cout << endl;
cin.ignore();
return 0;
}
void delete_element(int x[], int& n, int k){
if (k<1 || k>n){
cout << "Wrong index of k " << k << endl;
exit(1); // end program
}
for (int i = k - 1; i<n - 1; i++)
x[i] = x[i + 1];
n--;
}
There are a couple of mistakes in your program.
Apart from some syntax issues you are trying to pass an int array to a function which wants a double array.
You cannot pass a lvalue reference of a int literal. What you want is to pass a reference to the length of the int array. see also http://en.cppreference.com/w/cpp/language/reference.
Here is an updated version of your program.
#include <iostream>
#include <cstdlib>
using namespace std;
void delete_element(int x[], int& n, int k);
int main() {
// example of a function
int mass[10] = { 1,2,3,45,12,87,100,101,999,999 };
int len = 10;
for (int i = 0;i < len;i++)
cout << mass[i] << " "; ;
cout << endl;
delete_element(mass, len, 4);
for (int i = 0;i < len;i++) // len is 9 now
cout << mass[i] << " ";
cout << endl;
return 0;
}
void delete_element(int x[], int& n, int k) {
if (k<1 || k>n) {
cout << "Wrong index of k " << k << endl;
exit(1); // end program
}
for (int i = k - 1;i<n - 1;i++)
x[i] = x[i + 1];
n--;
}
Although it does not answer your question directly, I would like to show you how you can use C++ to solve your problem in a simpler way.
#include <vector>
#include <iostream>
void delete_element(std::vector<int>& v, const unsigned i)
{
if (i < v.size())
v.erase(v.begin() + i);
else
std::cout << "Index " << i << " out of bounds" << std::endl;
}
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7};
delete_element(v, 4);
for (int i : v)
std::cout << i << std::endl;
return 0;
}
You cannot delete elements from an array, since an array's size is fixed. Given this, the implementation of delete_element can be done with just a single call to the appropriate algorithm function std::copy.
In addition, I highly suggest you make the element to delete a 0-based value, and not 1-based.
Another note: don't call exit() in the middle of a function call.
#include <algorithm>
//...
void delete_element(int x[], int& n, int k)
{
if (k < 0 || k > n-1 )
{
cout << "Wrong index of k " << k << endl;
return;
}
std::copy(x + k + 1, x + n, x + k);
n--;
}
Live Example removing first element
The std::copy call moves the elements from the source range (defined by the element after k and the last item (denoted by n)) to the destination range (the element at k). Since the destination is not within the source range, the std::copy call works correctly.

recursive algorithm to sum of every element in an array with a value lesser than x

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);