C++ Problems with arrays, begin and end in functions - c++

Hello I am trying to write a script that picks a random number and then excludes that number afterwards.
#include <iostream>
#include <ctime>
#include <random>
#include <iterator>
using namespace std;
random_device rd; // non-deterministic generator
mt19937 gen(rd()); // to seed mersenne twister.
uniform_int_distribution<> dist(1, 52); // distribute results between 1 and 6 inclusive.
int testFunc(int cardArray, int cardArray2, int k) {
cardArray[k] = dist(gen);
copy(begin(cardArray), end(cardArray), begin(cardArray2));
cardArray2[k] = 0;
bool exists = find(begin(cardArray2), end(cardArray2), cardArray[k]) != end(cardArray2);
cardArray[k] = dist(gen);
cout << i + 1 << ": " << cardArray[k] << " " << exists << endl;
return 0;
}
int main()
{
int cardArray[52] = { 0 };
int cardArray2[52] = { 0 };
int i = 0;
for (int n = 0; cardArray[n] == 0 && n < 52; n++) {
cardArray[i] = dist(gen);
copy(begin(cardArray), end(cardArray), begin(cardArray2));
cardArray2[i] = 0;
bool exists = find(begin(cardArray2), end(cardArray2), cardArray[i]) != end(cardArray2);
cardArray[i] = dist(gen);
cout << i + 1 << ": " << cardArray[i] << " " << exists << endl;
i++;
}
cout << endl;
cin.ignore();
return 0;
}
So there's a few problems so far. Here are the errors:
no instance of overloaded function "end" matches the argument list
no instance of overloaded function "begin" matches the argument list
expression must have pointer - to - object type
I just can't figure out what's wrong. The function itself works fine if it's just in main but I need to be able to call it.
Please tell me if I need to post more information.

You are taking in ints in you function not int*
int testFunc(int cardArray, int cardArray2, int k)
should be
int testFunc(int* cardArray, int* cardArray2, int k)
Unfortunately this will stop std::begin and std::end from working as they need an array and not a pointer. To pass the arrays to function you need to take them by reference. To do that we can use a template like:
template<typename T, std::size_t N, std::size_t M>
int testFunc(T (&cardArray)[N], T (&cardArray2)[M], int k)
Or we can skip using native arrays and use a std::array or std::vector

Related

c++ Problems with operator overloading [duplicate]

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.

Modify a variable passed by reference

I'm working on a function that finds the smallest element in an array. I'm trying to modify the variable s using pass by reference. I'm brand new to C++ and I'm not sure if I have done pass-by-reference correctly. Can anyone confirm that this is the correct way to do this, or suggest better ways to approach a min value function with pass by reference?
#include <cstdlib>
#include <stdlib.h>
#include <iostream>
using namespace std;
int smallestElm(int numArray[], int length, int &smallest);
int main() {
int n[3] = {2,5,3};
int s = 0;
int length = 0;
cout << smallestElm(n, length, s) << endl;
}
int smallestElm(int numArray[], int length, int &smallest) {
smallest = numArray[0];
length = sizeof (numArray) / sizeof (int);
for (int i = 1; i < length; i++) {
if (numArray[i] < smallest) {
smallest = numArray[i];
}
cout << smallest << endl;
return 0;
}
}
Yes this is correct, as you should be able to tell by yourself, by modifying your main function like this:
int main() {
int s = 0;
// call your function
cout << s << endl; // Here you print 's', thus you confirm whether you are right or not
}
If s wouldn't change its value, then your pass by reference won't be correct (since s does change its value inside the body of the function).
As for the function, it's wrong, since it will return before checking all the elements! So, change that to something like this to check all the elements of the array before saying for certain which the smallest element is:
#include <stdlib.h>
#include <iostream>
using namespace std;
void smallestElm(int numArray[], size_t length, int &smallest);
int main() {
int n[] = {2,5,3}; // size is not needed, it's automatically computed by the compiler
int s = 0;
size_t length = 3;
smallestElm(n, length, s);
cout << "smallest element = " << s << endl;
return 0;
}
void smallestElm(int numArray[], size_t length, int &smallest) {
smallest = numArray[0];
for (int i = 1; i < length; i++) {
if (numArray[i] < smallest) {
smallest = numArray[i];
}
cout << smallest << endl;
}
}
Output:
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
2
2
smallest element = 2
Don't forget that STL provides min_element, that you could use like this:
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
int n[] = {2,5,3};
int *s = std::min_element(n, n + 3); // 3 size of the array
cout << "smallest element = " << *s << endl;
return 0;
}
Output:
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
smallest element = 2
Can anyone confirm that this is the correct way to do this
Yes, that is the correct way to declare a reference argument. And yes, you can modify objects through a reference.
or suggest better ways to approach a min value function ...
A better way would arguably be to return the min value, instead of modifying an argument. Right now the function always returns 0, which seems useless.
... with pass by reference
That's a silly idea, but your approach is correct way to pass by reference. The function itself has multiple bugs.
It seems to always return after the first iteration, so it'll always find one of the first 2 element to be "smallest".
The value of int length argument is never used. It is overridden before use.
sizeof (numArray) returns the size of the pointer numArray which is not in any way related to the size of the pointed array.
The function always uses numArray[0] so it will have undefined behaviour if length == 0.
It's correct your code, but there is another way: Using a pointer to int, into the function argument and invoke this with the address of memory of variable s, as the below sample shows:
#include <stdlib.h>
#include <iostream>
using namespace std;
void smallestElm(int numArray[], size_t length, int *smallest);
int main() {
int n[] = {2,5,3}; // size is not needed, it's automatically computed by the compiler
int s = 0;
size_t length = 3;
smallestElm(n, length, &s);
cout << "smallest element = " << s << endl;
return 0;
}
void smallestElm(int numArray[], size_t length, int *smallest) {
*smallest = numArray[0];
for (int i = 1; i < length; i++) {
if (numArray[i] < *smallest) {
*smallest = numArray[i];
}
cout << *smallest << endl;
}
}

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.

random array generation in c++ [duplicate]

This question already has answers here:
rand() returns same values when called within a single function
(5 answers)
Closed 8 years ago.
I'm trying to write a simple function that generates an array with random integers.
I encountered with an interesting thing, when I run this program outputs -each cout
statements- seem the same.
However, when I am debugging and watching it step by step array values are changing.
Am I doing something wrong?
Thanks.
void generateRandomArray( int *&inputArray, int size){
if(inputArray != NULL){
delete []inputArray;
}
//create a new array
inputArray = new int [size];
//fill with random numbers
srand(unsigned (time (NULL)));
for (int i = 0; i < size ; i++)
inputArray[i] = (rand() % 100) ;
}
int main(){
//Variables
int *inputArray = NULL;
int size;
//Test
size = 10;
//first call
generateRandomArray( inputArray, size);
for(int i = 0 ; i < size; i++){
cout << inputArray[i] << endl;
}
cout << "------------------" << endl;
//second call
generateRandomArray( inputArray, size);
//output is the same with previous
for(int i = 0 ; i < size; i++){
cout << inputArray[i] << endl;
}
return 0;
}
The program runs too fast, srand(unsigned (time (NULL))); will get a seed having the same seconds (since epoch). Hence, the rand sequences are the same.
The problem is that if the calls to srand all happen withing the same second, the generator will be seeded with the same values and so generate the same sequence, always.
When you're debugging it will be slower, and allow time to pass and have different seed for the generator. When not debugging the time between calls will be too fast.
Don't call srand more than once, unless you know what you're doing. Put it at the start of the main function, and don't call it again.
Call srand(time(NULL)) and it will seed the current time and make a random number from it. Since time is changing all the time, it will give you a different number every time.
With C++11, you may use something like: (https://ideone.com/EIb0nY)
#include <iostream>
#include <random>
#include <vector>
std::vector<int> generateRandomArray(std::default_random_engine& generator, int size)
{
std::uniform_int_distribution<int> distribution(1, 100);
std::vector<int> res(size);
for (auto& e : res) {
e = distribution(generator);
}
return res;
}
int main()
{
std::default_random_engine generator;
const int size = 10;
//first call
for (auto e : generateRandomArray(generator, size)) {
std::cout << e << std::endl;
}
std::cout << "------------------" << std::endl;
//second call
for (auto e : generateRandomArray(generator2, size)) {
std::cout << e << std::endl;
}
return 0;
}
That use the new random facilities.
It avoids manual memory management (with std::vector).

Why is "n" not incremented in this function?

My code:
#include <iostream>
#include <vector>
#include <algorithm>
int test_n(std::vector<int>::iterator b, std::vector<int>::iterator e, int &n)
{
n++;
std::vector<int>::difference_type l = e-b;
if (l<100) return std::accumulate(b, e, 0);
std::vector<int>::iterator tmp = b + l/2;
int nL = test_n(b, tmp, n);
int nR = test_n(tmp, e, n);
return nL + nR;
}
int main()
{
int n=0;
std::vector<int> v;
for (int i=1; i<1000; i++) v.push_back(i);
std::cout << test_n(v.begin(), v.end(), n) << " (n=" << n << ")\n";
return 0;
}
Why is n not incremented at least once?
n is incremented. It's just that C++ doesn't have a fixed order of evaluating arguments in a statement. Therefore, in the statement where you call test_n (the std::cout line just before the end), the compiler probably decides first to check the value of n, and only then call test_n and get its output.
My advice: Separate the calls - do test_n before cout and you should see the change.
So:
int testnresult = test_n(v.begin(), v.end(), n);
std::cout << testnresult << " (n=" << n << ")\n";
See e.g. the question Compilers and argument order of evaluation in C++ for details on order in which arguments are evaluated in C++.