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
Related
I tried to write quicksort by myself and faced with problem that my algorithm doesn't work.
This is my code:
#include <iostream>
#include <vector>
using namespace std;
void swap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
}
void qsort(vector <int> a, int first, int last)
{
int f = first, l = last;
int mid = a[(f + l) / 2];
do {
while (a[f] < mid) {
f++;
}
while (a[l] > mid) {
l--;
}
if (f <= l) {
swap(a[f], a[l]);
f++;
l--;
}
} while (f < l);
if (first < l) {
qsort(a, first, l);
}
if (f < last) {
qsort(a, f, last);
}
}
int main()
{
int n;
cin >> n;
vector <int> a;
a.resize(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
qsort(a, 0, n - 1);
for (int i = 0; i < n; i++) {
cout << a[i] << ' ';
}
return 0;
}
My sort is similar to other that described on the Internet and I can't find where I made a mistake.
Even when I change sort function, the problem was not solved.
You don't pass qsort the array you want to sort, you pass it the value of that array. It modifies the value that was passed to it, but that has no effect on the array.
Imagine if you had this code:
void foo(int a)
{
a = a + 1;
}
Do you think if I call this like this foo(4); that foo is somehow going to turn that 4 into a 5? No. It's going to take the value 4 and turn it into the value 5 and then throw it away, since I didn't do anything with the modified value. Similarly:
int f = 4;
foo(f);
This will pass the value 4 to foo, which will increment it and then throw the incremented value away. The value f has after this will still be 4 since nothing ever changed f.
You meant this:
void qsort(vector <int>& a, int first, int last)
Your swap has the same problem. It swaps the values of a and b, but then never does anything with the value of a or b. So it has no effect. How could it? Would swap(3, 4); somehow change that 3 into a 4 and vice-versa? What would that even mean?
Your swap does not swap anything. You should write tests not only for the whole program but for as small pieces as possible. At least you should test single functions. Try this:
int main() {
int a= 42;
int b= 0;
std::cout << "before " << a << " " << b << "\n";
swap(a,b);
std::cout << "after " << a << " " << b << "\n";
}
This is "poor mans testing". For automated tests you should use a testing framework.
Then read about pass by reference. (While doing so you hopefully also realize the issue with not passing the vector to qsort by reference.)
Then use std::swap instead of reinventing a wheel.
I Found two error on your code
void swap(int a, int b) This method is not working, cause is receive value only and swap , but the original one is not updated.
void swap(int *a, int *b)
{
int t;
t = *b;
*b = *a;
*a = t;
}
swap(&a, &b);
And you pass vactor which also pass value. replace your void qsort(vector <int> &a, int first, int last) method.
This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 4 years ago.
My assignment is to use operator overloading to
create a random number array
get lowest number
get highest number
get average
get total and
get standard deviation.
It is just a mess. Here is my code:
#ifndef ASSIGNMENT6_HEAD6_H
#define ASSIGNMENT6_HEAD6_H
#include <iostream>
using namespace std;
class Analyzer {
//Private Member
private:
int numbers;
//Public Member
public:
Analyzer();//default constructor
~Analyzer();//destructor
Analyzer operator+(const Analyzer &a) const;
friend numbers operator+();
};//end of class
#endif //ASSIGNMENT6_HEAD6_H
//Class math with overloading operator and friends
#include "head6.h"
#include <cmath>
#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
using namespace std;
vector<int> numbers;
int min = numbers[0];
int max = numbers[0];
int sizeofArray;
Analyzer::Analyzer() {
}
int getLowest(const int[], int);
//Random number member
void randNumbers(int sizeofArray, int* numbers[]) {
for (int index = 0; index < sizeofArray; index++)
{
numbers[index] = (numbers() % 499) + 100;
}return;
}
//Setters
int lowest = getLowest(numbers, sizeofArray);
int highest = getHighest(numbers, sizeofArray);
float total = getTotal(numbers);
double average = getAverage(total, sizeofArray);
//Lowest number
void getLowest(const int numbers[], int sizeofArray) {
for (int i = 0; i < sizeofArray; i++) {
if (min > numbers[i]) {
min = numbers[i];
min = lowest;
}
}
return;
}
//Highest number
void getHighest(const int numbers[], int sizeofArray) {
for (int i = 0; i < sizeofArray; i++) {
if (max > numbers[i]) {
max = numbers[i];
max = lowest;
}
}
return;
}
//Total
float getTotal(const int numbers) {
total = sum(numbers[]);
return total;
}
//Average
double getAverage(const float total, int sizeofArray) {
double average = total / sizeofArray;
return average;
}
//standard deviation
float getStandardDeviation(int sizeofArray, float numbers[])const
{
float deviation1;
for (int i = 0; i < sizeofArray; i++)
sum = (mean - numbers[i]) * (mean - numbers[i]);
deviation1 = sqrt(sum / sizeofArray - 1);
float deviation = deviation1;
return deviation;
}
string a() {
stringstream sout;
sout << "STATISTICAL ANALYSIS OF RANDOMLY GENERATED NUMBERS" << endl;
sout << "====================================================" << endl;
sout << left << "Lowest Number:" << left << getLowest() << endl;
sout << left << "Highest Number:" << left << getHighest() << endl;
sout << left << "Numbers Total:" << left << getTotal() << endl;
sout << left << "Numbers Averge:" << left << getAverage() << endl;
sout << left << "Numbers of Standard Deviation:" << left <<
getStandardDeviation() << endl;
return sout.a();
}
int main()
{
Analyzer a;
a + 100;
cout << a;
return 0;
}
Thank you for any assistance.
Your assignment is to use operator overloading to solve the issues - but you actually don't do so anywhere (apart from the operator+ for your Analyzer class – which is meaningless, though).
Reading your lines, I'd rather assume that you're supposed to write separate classes for each task:
class Minimum
{
std::vector<int> const& values
public:
Minimum(std::vector<int> const& values) : values(values) { }
// calculates minimum / lowest value from member:
int operator()();
};
class Maximum
{
public:
//Maximum(); not needed in this variant
// calculates maximum from parameter
int operator()(std::vector<int> const& values);
};
void test()
{
std::vector<int> values({10, 12, 7});
int min = Minimum(values)();
int max = Maximum()(values);
}
These are two different patterns, for consistency, you should select one and implement all classes alike. In first approach, you can access the vector from any member function without having to pass it around as parameter, in second approach, you can re-use one and the same object to calculate the value on several different vectors (you could still maintain a pointer to the vector to avoid passing it around via parameters...).
Coming back to your original code, unfortunately it is full of errors
vector<int> numbers;
int min = numbers[0]; // vector is yet empty! undefined behaviour!
int max = numbers[0];
Actually, you might want not to use globals at all, see later...
//int sizeofArray; // use numbers.size() instead!
// not an error, but questionable: you have a std::vector already, why do you
// fall back to C-style raw arrays?
void randNumbers(int sizeofArray, int* numbers[])
// ^ array of pointers???
{
for (int index = 0; index < sizeofArray; index++)
{
numbers[index] = (numbers() % 499) + 100;
// you certainly intended to use rand function
}
// return; // just plain obsolete
}
// vector variant:
void randNumbers(unsigned int numberOfValues, std::vector<int>& destination)
// ^ not how many numbers ARE in,
// but how many SHALL be inserted
{
// assuming we want to re-use this function and guarantee that EXACTLY
// 'numberOfValues' values are contained:
destination.clear(); // there might have been some values in already...
// assure sufficently internal memory pre-allocated to prevent
// multiple re-allocations during filling the vector:
destination.reserve(numberOfValues);
while(numberOfValues--)
{
numbers.push_back(rand() * 500 / RAND_MAX + 100);
// modulus is unprecise; this calculation will give you better
// distribution
// however, rather prefer modern C++ random number generators!
// IF you use rand: assure that you call srand, too, but exactly ONCE,
// best right when entering main function
}
}
// C++ random number generator:
void randNumbers(unsigned int numberOfValues, std::vector<int>& destination)
{
static std::uniform_int_distribution<> d(100, 599);
static std::mt19937 g;
destination.clear();
destination.reserve(numberOfValues);
while(numberOfValues--)
{
numbers.push_back(d(g));
}
}
Now you have contradicting function declarations:
int getLowest(const int[], int);
void getLowest(const int numbers[], int sizeofArray) { /* ... */ }
int lowest = getLowest(numbers, sizeofArray);
// again: the vector is yet empty!
// so you certainly won't get the result desired
// however, this won't compile at all: numbers is a std::vector,
// but parameter type is array, so you need:
int lowest = getLowest(numbers.data(), numbers.size());
// ^ replaced the redundant global as well
// move this into your main function AFTER having filled the vector!
// picking int as return value:
int getLowest(const int numbers[], unsigned int sizeofArray)
{
// you'd now have to initialize the global first; better, though:
// return a local variable:
// this assumes that there is at least one element in! check before usage
// and decide what would be the appropriate error handling if the vector
// is empty (return 0? return INT_MIN? throw an execption?)
int min = numbers[0];
for (int i = 1; i < sizeofArray; i++)
{
if (min > numbers[i])
{
min = numbers[i];
// min = lowest; // don't overwrite the minimum again!
}
}
// returning at end of void function is obsolete, don't do that explicitly
// well, with int as return value, as is NOW, you NEED to return:
return min;
}
Maximum analogously, be aware that you did not change the comparison from > to <! Be aware that there are already std::min_element, std::max_element and std::minmax_element which do the same (if not prohibited by the assignment, you should rather use these instead of re-inventing the wheel).
// prefere double! float (on typical machines at least) has same size as int
// and it is quite likely that you will lose precision due to rounding; I
// personally would rather use int64_t instead, so you won't run into rounding
// issues even with double and you'd need quite a large amount of summands
// before overflow can occur...
float getTotal(const int numbers) // just one single number???
{
total = sum(numbers[]);
// index operator cannot be applied on a single int; additionally, you need
// to provide an argument; where is 'sum' function defined at all???
return total;
}
// prefer double again
double getStandardDeviation(int sizeofArray, float numbers[]) // const
// (free standing functions cannot be const)
{
// mean isn't declared/defined anywhere (average instead?)!
// and you need to declare and initialize the sum appropriately:
double sum = 0.0;
float deviation1;
for (int i = 0; i < sizeofArray; i++)
sum += (mean - numbers[i]) * (mean - numbers[i]);
// ^ you need to add, if you want to build sum
// why two variables, even both of same type???
deviation1 = sqrt(sum / sizeofArray - 1);
float deviation = deviation1;
return deviation;
// simplest: drop both deviation and deviation 1 and just do:
return sqrt(sum / sizeofArray - 1);
}
Finally: I don't think that you'd use the resulting string (below) for anything else than printing out to console again, so I'd output to std::cout directly (naming the function 'print'); if at all, I'd provide a std::ostream as parameter to be more flexible:
void print(std::ostream& sout)
{
sout << "STATISTICAL ANALYSIS OF RANDOMLY GENERATED NUMBERS" << endl;
sout << "====================================================" << endl;
sout << left << "Lowest Number:" << left << getLowest() << endl;
sout << left << "Highest Number:" << left << getHighest() << endl;
sout << left << "Numbers Total:" << left << getTotal() << endl;
sout << left << "Numbers Averge:" << left << getAverage() << endl;
sout << left << "Numbers of Standard Deviation:" << left
<< getStandardDeviation() << endl;
}
Now you could pass std::cout to, a std::ostringstream object or even write to file via a std::ofstream...
int main()
{
Analyzer a, b, c; // b, c added by me for illustration only
a + 100;
// the operator accepts another Analyzer object, so you could do
c = a + b;
cout << a; // there's no operator<< overload for Analyzer class
// it is HERE where you'd call all your getXZY functions!
return 0;
}
You are passing a pointer to an array of integers:
void randNumbers(int sizeofArray, int* numbers[])
where you really just want to pass numbers as an array. And since all arrays degrade to pointers when passed as a parameter, your function is simply this:
void randNumbers(int sizeofArray, int* numbers) {
for(int index = 0; index < sizeofArray; index++) {
numbers[index]= (rand() % 499) + 100;
};
}
The result is that the items in numbers will be integers in the range of [100..599] inclusive.
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.
I wrote a basic linear search C++ code. Whenever I run this, the result I get is always the opposite of the expected result.
For instance, I want to search 4. In an array where it is present, it will say the number is not found, but upon searching an absent element, it will say the element is found at position 0.
Even after an hour or so of constantly looking at the code I have not found any solution.
#include <iostream>
using namespace std;
//scanning program
int linearsearch (int A[] , int z, int n, int srchElement) {
for (int z = 0; z < n; z++) {
if (A[z] == srchElement) {
return z;
}
}
return -1;
}
//main program
int main () {
int i, n, A[1000], z;
//asking for size of array
cout << "give size of the array needed to be scanned: ";
cin >> n;
cout << endl;
if (n > 999) {
cout << "invalid value";
return -1;
}
//making sure of the size of the array
cout << "enter " << n << " integers: ";
//asking for the array
for (i = 0; i < n; i++) {
cin >> A[i];
}
int srchElement, index;
do {
cout << endl << "enter element to search (-1 to exit ): ";
//srchElement is defined here
cin >> srchElement;
if (srchElement == -1) break;
index = linearsearch(A, n, srchElement, z);
//calling thscanning function
if (index == -1) {
cout << srchElement << " not present" << endl;
}
//outputting the results of the scan
else {
cout << srchElement << " present " << index << endl;
}
} while (true);
return 0;
}
Your parameters to linearsearch are not in the correct order - you are passing n into the unused z parameter. With your current function you should call it like:
index=linearsearch(A, 8675309, n, srchElement);
I recommend you get rid of z as a parameter, then you won't need to pass a value to it.
Also please note: Spaces and indentation do not make your program run slower, but they do make it a lot easier to read.
The order of arguments in the function definition is not the same as in the function call.
It should be like (Line no 4):
int linearsearch (int A[] , int n, int srchElement, int z)
This is your search function correctly formatted:
int linearsearch (int A[] , int z, int n, int srchElement)
{
for (int z = 0; z < n; z++)
{
if(A[z] == srchElement)
{return z;}
}
return -1;
}
and here is how you call it:
index=linearsearch(A, n, srchElement, z);
You pass a value z in with the call. It is unitialised and does nothing, in main() or in the function.
You pass the arguments into the function in the wrong order. You are:
passing n (from main()) into the unused z value
searching for the uninitialised z (from main())
passing in the element you are looking for as n (array size). (This will quite likely result in out of bounds error, e.g. if searching for -1)
Try this:
int linearsearch (int A[], int n, int srchElement)
{
for (int z = 0; z < n; z++)
{
if(A[z] == srchElement)
{return z;}
}
return -1;
}
and here is how you call it:
index=linearsearch(A, n, srchElement);
You immediate problem: as The Dark spotted, this call:
index=linearsearch(A, n, srchElement, z);
doesn't match the declaration
int linearsearch (int A[] , int z, int n, int srchElement)
Function arguments in C++ are positional: just because the last call argument and the second declaration parameter are both called z doesn't mean anything.
Now, there are several local issues of style:
this kind of function is risky in the first place
int linearsearch (int[],int,int,int)
because it relies on you remembering the correct order for the last three integer parameters. If you must do this, you should be extra careful to give them all distinctive names, be very clear about which is which, and keep the order consistent across families of functions.
It's better, where possible, to help the compiler help you out, by either giving the arguments distinct types (or enumerations, or whatever), or grouping them into a structure.
For example, using a std::vector<int> instead of your array effectively groups int A[] and int n together in an object, so they can't get out of sync and n can't get confused with the other integers floating around
You shouldn't be passing z in the first place. You immediately hide it with a local int z in the loop, so it can't be doing anything. Remove it from both the declaration and the call. This simplification is sufficient to fix your bug.
Your secondary problem is that the code is ugly. It's poorly formatted and hard to read, and and that makes it more difficult to spot mistakes. Try to make your code simple and readable: there's less opportunity for things to go wrong, and its easier to see the problems when they occur.
Your tertiary problem is that the code is bad. Most of this can be done using standard library facilities (making your code simpler), which are themselves well-tested and generally have carefully-designed interfaces. Use them first, and replace if necessary.
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;