C++ Calling Vectors from Function to Main - c++

I'm trying read a large amount of values into a vector in a specific function and then calling it into the main to get the average. My readInput works perfectly. But I believe
my main function returns 0 when I cout << values.size();. Why is this? What can I do to change that?
using namespace std;
//function prototype
int readInput(vector<int> vect);
int main()
{
vector<int> values;
int sum, avg;
sum = readInput(values);
//cout << sum;
avg = sum / values.size();
cout << avg;
return 0;
}
int readInput(vector<int> vect)
{
int count;
int total = 0;
ifstream inputFile("TopicFin.txt"); //open file
if(!inputFile)
{
return 0; // if file is not found, return 0
}
while(inputFile >> count) //read file
vect.push_back(count); //add to file
for (int count = 0; count < vect.size(); count++)
total+=vect[count]; //sum data in vector
return total;
}

You are not passing your vector by reference, so your function only stores the values in a copy of your vector from main.
int readInput(vector<int>& vect);
this tells your program to pass the the vector by reference meaning anything modified in the function directly modifies your vector in main. If you're new to this stuff check out this post explaining the difference between reference and copy.

You need to pass the vector as a reference or as a pointer. The function just creates a copy of the vector currently passed by value, and manipulates that.
Change the function signature to . . .
int readInput(vector<int>& vect)
Or (perhaps more weirdly for this example) . ..
int readInput(vector<int> *vect)
also changing the function call to
sum = readInput(&values);

Although others have already mentioned the possibility of passing the vector by reference, that is not what I think I'd do in this case. I think I'd just return the vector from the function. I'd also pass the file name to the function:
std::vector<int> values = readInput("TopicFin.txt");
At least to me, this seems to reflect the intent far better. Maybe I'm just a little slow, but it doesn't seem at all obvious from the name that the return value from readInput would be the sum of the values it read.
While returning a vector could theoretically cause an efficiency problem with a compiler that supported neither move construction nor return value optimization, any such compiler is pretty much guaranteed to be so ancient that you really want to avoid it for other reasons anyway.
As far as reading the data into the vector goes, I'd use a pair of istream_iterators:
std::vector<int> data{std::istream_iterator<int>(infile),
std::istream_iterator<int>()};
Of course, given how simple this is, I'd tend to wonder whether it's worth having a separate function like readInput at all.
To sum the values, I'd use std::accumulate:
int total = std::accumulate(data.begin(), data.end(), 0);

Related

Vectors and Functions exercise

I have a question regarding this program. I am a beginner when it comes to programming and c++, and I'm trying to figure out two things.
why is this program not compiling (error: Using uninitialized memory 'total' - I have it defined as a variable??).
Could someone explain how the function outside of the main (sumUpTo) works? Specifically & vec and total, as I've never seen them before. Thanks.
/* 1) read in numbers from user input, into vector -DONE
2) Include a prompt for user to choose to stop inputting numbers - DONE
3) ask user how many nums they want to sum from vector -
4) print the sum of the first (e.g. 3 if user chooses) elements in vector.*/
#include <iostream>
#include <string>
#include <vector>
#include <numeric> //for accumulate
int sumUpTo(const std::vector<int>& vec, const std::size_t total)
{
if (total > vec.size())
return std::accumulate(vec.begin(), vec.end(), 0);
return std::accumulate(vec.begin(), vec.begin() + total, 0);
}
int main()
{
std::vector<int> nums;
int userInput, n, total;
std::cout << "Please enter some numbers (press '|' to stop input) " << std::endl;
while (std::cin >> userInput) {
if (userInput == '|') {
break; //stops the loop if the input is |.
}
nums.push_back(userInput); //push back userInput into nums vector.
}
std::cout << "How many numbers do you want to sum from the vector (the numbers you inputted) ? " << std::endl;
std::cout << sumUpTo(nums, total);
return 0;
}
Errors in your code -
int userInput, n, total;
.
.
.
std::cout << sumUpTo(nums, total);
Here you are declaring total and directly using it as a parameter to sumUpTo function. In that function you are using it in an comparison ( if (total > vec.size()) ). But, since you have never initialized it while declaration nor have you assigned it any value anywhere in the code, the compiler doesn't know what to make of that comparison that you are making since total doesn't have any value.
could someone explain how the function outside of main (sumUpTo)
works? Specifically '& vec' and 'total'
sumUpTo has the declaration as - int sumUpTo(const std::vector<int>& vec, const std::size_t total).
Here, you are expecting the function to take a vector of integers as parameters. But you probably have doubt with & that's before vec. That symbol just specifies that you are going to pass the vector as a reference and not by making a complete copy of the vector. In our regular passing, the vector we pass to function will get passed as a copy of our origin vector. But in this case, the vector is getting passed as a reference and not a copy of the original vector.
Do note that I have used the term reference and not pointers. If you are coming from C background, you could feel both are the same and in some cases, they might function a bit similar but there are few differences(some good answers on SO - 1, 2, 3 ) between them which you can read many good resources available online. Just understand that in this case, it prevents making a copy of the vector when it is passed to the function. If the function declaration wouldn't have mentioned that parameter to be const, you could also make changes in the vector which would also reflect in the original one as well (while they wouldn't have if you passed it normally rather than as reference).
std::size_t is a type that is used to represent the size of objects in bytes. It is an unsigned datatype and used whenever you are dealing with sizes of objects. You can also refer this if you are not sure about the difference between std::size_t and int ( which is what you might have been expecting total to be).
Lastly, it's obvious that const is being used in the function to ensure that the parameters that we are passing to function aren't getting modified in the function.

I am fairly new to STLs in C++ and i tried making a heap using vectors. Didnt get the desired output

#include<bits/stdc++.h>
using namespace std;
class Heap
{
vector <int> v;
int length;
public:
void create(vector <int> v, int s);
void display();
};
void Heap::create(vector <int> v, int s)
{
length=s+1;
for(int i=1;i<=s;i++)
{
this->v[i]=v[i-1];
}
int temp;
int j;
for(int i=2;i<length;i++)
{
temp=v[i];
j=i;
while(j>1&&temp>v[j/2])
{
swap(v[j],v[j/2]);
j=j/2;
}
if(j==1)
{
v[j]=temp;
}
}
}
void Heap::display()
{
for(int i=1;i<length;i++)
{
cout<<v[i]<<"\t";
}
cout<<endl;
}
int main()
{
vector <int> v;
int ans=1;
int d;
while(ans==1)
{
cout<<"Enter the Data\n";
cin>>d;
v.push_back(d);
cout<<"Do you want to enter more data?\n";
cin>>ans;
}
cout<<endl;
Heap h;
h.create(v,((int)v.size()));
h.display();
}
When i execute this code, it asks me to enter the data value. i enter all the data values i want to enter and click the enter button. it shows segmentation error. also the execution is taking a lot of time which is very unusaul. i use codeblocks version 20.
When i execute this code, it asks me to enter the data value. i enter all the data values i want to enter and click the enter button
Yeah, I'm not interested in guessing what you typed in order to reproduce your problem. I'm also not interested in guessing whether the issue is in your I/O code or the code you think you're testing.
Always remove interactive input when you're preparing a minimal reproducible example so that other people can actually reproduce it.
Sometimes removing the interactive input may fix your problem, in which case you've learnt something important (and probably want to ask a different question about your input code).
it shows segmentation error
A segmentation fault interrupts your program at the exact point where it happens. If you run your program in a debugger, it will show you where this is, and the state of everything in your program when it happened. You should try this, and learn to use your debugger.
this->v[i]=v[i-1];
As correctly pointed out in the other answer, there is a bug on this line.
You correctly called push_back when reading input, so you could just do the same here. Alternatively you need to explicitly size this->v before indexing elements that don't exist.
The other main problem with this function is that it mixes up this->v (used, illegally, only once on the line above) and v which is a local copy of the v in main, and which goes out of scope and is lost forever at the end of the function.
Just give your variables different names so you don't have to write this->v on all the other lines where you currently refer to v. Also, consider passing the original v by const ref instead of making a copy.
NB. I do see and understand that you're deliberately switching to 1-based indexing for the sort. If for some reason you can't just use std::sort or std::make_heap, you could at least explicitly set the zeroth element to zero, and then just std::copy the rest.
Finally, Heap::create really looks like it should just be a constructor. Forcing two-phase initialization is poor style in general, and I don't see any reason for it here.
First issue: you have used 'this->v' before initializing it. In this point:
this->v[i]=v[i-1];
this->v have size 0 and has no element to be accessed via index;
Furtheremore you have used wrong indices for it. Assuming this->v has initialized, correct index access is like this
this->v[i-1]=v[i-1];
Finally, it is better to sort the std vectors by using std::sort builtin function:
#include <algorithm>
std::sort(this->v.begin(), this->v.end());
This is obviously a school exercise. So I will only give you pointers as to where your code goes wrong.
class Heap
{
// vector <int> v; // v is not a suitable name for a class member, it's too short
// int length; // why length ? Your container declared above has length information, using
// a duplicate can only introduce opportunities for bugs!!!
vector<int> heap; // I've also renamed it in code below
public:
void create(vector <int> v, int s);
void display();
};
// some documentation is needed here...
// A I read it, it should be something like this, at least (this may reveal some bug):
//
// Initializes heap from range [v[1], v[s])
// void Heap::create(vector <int> v, int s) // you do not need a copy of the source vector!
void Heap::create(const vector& <int> v, int s) // use a const reference instead.
{
// This is not how you assign a vector from a range
// length=s+1;
// for(int i=1;i<=s;i++)
// {
// this->v[i]=v[i-1];
// }
// check inputs always, I'll throw, but you should decide how to handle errors
// This test assumes you want to start at v[1], see comment below.
if (0 > s || s >= v.size())
throw std::out_of_range ("parameter 's' is out of range in Heap::Create()");
// assign our private storage, why the offset by '1' ????
// I doubt this is a requirement of the assignment.
heap.assign(v.begin() + 1, v.begin() + s + 1);
//int temp; // these trivial variables are not needed outside the loop.
//int j;
// why '2' ?? what happens to the first element of heap?
// shouldn't the largest element be already stored there at this point?
// something is obviously missing before this line.
// you'll notice that v - the parameter - is used, and heap, our
// private storage is left unchanged by your code. Another hint
// that v is not suitable for a member name.
for(int i = 2; i < v.length(); i++)
{
int temp = v[i]; // temp defined here
int j = i;
//while(j > 1 && temp > v[j/2]) // avoid using while() when you can use for().
//{
// swap(v[j],v[j/2]);
// j=j/2;
//}
// This is your inner loop. it does not look quite right
for (; j > 1 && temp > v[j / 2]; j = j / 2)
swap(v[j], v[j/2]);
if (j == 1)
v[j] = temp;
}
}
void Heap::display()
{
for(int i=1;i<length;i++)
{
cout<<v[i]<<"\t";
}
cout<<endl;
}
From reading your code, it seems you forgot that vectors are zero-based arrays, i.e. The first element of vector v is v[0], and not v[1]. This creates all kinds of near unrecoverable errors in your code.
As a matter of personal preference, I'd declare Heap as deriving publicly from std::vector, instead of storing data in a member variable. Just something you should consider. You could use std::vector<>::at() to access and assign elements within the object.
As is, your code will not function correcly, even after fixing the memory access errors.

Passing class with array member into overload of function that uses that array member

I'm trying to implement a polynomial class consisting of an int (degree) and an integer array (the coefficients for each term). I have a function to print the polynomial, which works fine when I pass in the degree and term array directly, but things get funky when I try to put those values into an instance of my polynomial class.
I am using variadic arguments in the polynomial's constructor, such that you should be able to call polynomial(degree, ). I made sure to output each term in my va_list so I know I'm targeting what I want to.
Here's my class:
class polynomial{
public:
polynomial(int degree...){
va_list args;
_degree = degree;
int p[degree];
va_start(args,degree);
for(int i = 0; i < degree; i++){
p[i] = va_arg(args,int);
cout << p[i] << endl; //just to verify that I'm grabbing the right values.
}
va_end(args);
_terms = p;
}
int degree(){return _degree;}
int* terms(){return _terms;}
private:
int _degree;
int* _terms;
};
And here's the function(s) I'm using to print the polynomial:
void printArray(int*p, int l){
std::cout << "[";
for(int i = 0; i < l; i++){
std::cout << p[i];
if(i != l-1) std::cout << ",";
}
std::cout << "]" << std::endl;
}
void printArray(polynomial p){
printArray(p.terms(), p.degree());
}
my main function:
int main()
{
int a[3] = {2,5,3};
printArray(a,3);
polynomial p1(3,2,5,3);
printArray(p1.terms(), p1.degree());
printArray(p1);
return 0;
}
and the output:
[2,5,3]
2
5
3
[2,0,94004573]
[1,0,1]
As you can see, I call printArray() 3 times. The first time, I directly create an integer array and pass it and its length into printArray(). This time, it works fine, outputting [2,5,3] as expected. The second time, I again use the first implementation of printArray(), but this time I pass in the int* and int from an instance of my polynomial. This time, I get some array whose first two elements always seem to be 0 and 2 and whose last value is some garbage value.
The third time, I simply pass in the polynomial to the second implementation of printArray(). This seems to output [1,0,1] consistently (which is of course incorrect).
I suppose it wouldn't be too confusing if the second and third calls to printArray() generated the same garbage values, but as it stands, I am fairly lost in terms of what's happening behind the scene. Any help at all would be appreciated. Thank you!
The problem is these two lines:
int p[degree];
and
_terms = p;
The first (besides not being a non-portable variable-length array extension of your compiler) defined p to be a local variable.
The second line makes _terms point to the first element of this array.
Then the constructor ends, and the life-time of p with it, leaving you with an invalid pointer in _terms.
The natural solution is to use std::vector instead. And if you need to use pointers (because assignment/exercise requirements) you need to use dynamic allocation (using new[], and also then you need to learn about the rule of three/five).

Using Arrays in functions in C++

I am a student who is doing an assignment for C++ and I have encountered something I am very unfamiliar with. I have an int array with no size but a list of numbers. After it's creation, there is a function call inside a function that has that array as a parameter with an index in it.
For example:
for (int x = 0; x < CAPACITY, x++)
functionCall(array[x]);
Now I am supposed to create a function so the call can work. However when I make my function:
void functionCall(int array[]);
It does not work because it cannot turn an int to an int[].
I guess my question is, how am I supposed to get that list of numbers created originally by the array if I have to call it in my function as if it isn't an array.
Right now if I just put as an int but not an array like it wants me to do it just gives me the number 5 but not any of the numbers in the array. For example:
void functionCall(int array);
Sincere thank you for anything and I apologize if this sounds confusing.
functionCall(array[x]);
This passes the xth element in the array to the function, so a single int.
array[2] = 5;
functionCall(array[2]); // This is the same as functionCall(5);
So in the function, you get the current element of the array. Not the array itself.
You cannot get the list inside the function, because you only give a single element of that list each time you call it.
Taking a wild guess, I suspect you are looking for something like the MCVE below:
#include <iostream>
void functionCall(int v) {
std::cout << v << " ";
}
void func(int array[], size_t CAPACITY) {
for (size_t x = 0; x < CAPACITY; x++)
functionCall(array[x]);
}
int main() {
int list[] = { 1,2,3,4,3,0, 42 };
func(list, std::distance(std::begin(list), std::end(list)));
return 0;
}

Passing vector by value

I want to create a program that uses a vector to sort it for testing reasons. So I want to calculate the CPU time by a benchmark that sorts the vector a certain amount of times. So the original vector needs to remain constant, and then use another vector so that it can be sorted.
So what I have done is...
#include <iostream>
#include <vector>
#include <random>
#include <chrono>
using namespace std;
typedef vector<int> intv;
int main(){
intv vi;
// Stuff to create my vector with certain characteristics...
intv vii=vi;
cout << "Size: \n";
cin >> tt ;
for(i=0; i<tt; ++i){
tb=sort(t,vii);
m=m+tb;
vii=vi;
}
m=m/tt;
cout << "BS" << m << "\n";
}
So I pass the vector by reference, and make a copy for each sorting so that I can sort it again. How can I do this a better way? Is it better to pass it by value, and in that case, Could someone provide me a minimum example of the best way to do this?
sort is a basic bubble sorting function:
double sort(int t, intv &vii){
vii.reserve(t);
bool swapped=true;
int a;
auto t0 =chrono::high_resolution_clock::now();
while (swapped==true){
for (int i=1; i<t; ++i){
swapped=false;
if (vii[i-1]>vii[i]){
a=vii[i];
vii[i]=vii[i-1];
vii[i-1]=a;
swapped=true;
}
}
t=t-1;
}
auto t1 = chrono::high_resolution_clock::now();
double T = chrono::duration_cast<chrono::nanoseconds>(t1-t0).count();
return T;
}
Once you have sorted, you have to do something that is equivalent to:
vii=vi;
I think assigning vi to vii will be the most efficient method of copying the contents of vi to vii. You can try:
size_t index = 0;
for ( auto const& val : vi )
{
vii[index++] = val;
}
However, I will be really surprised if the second method is more efficient than the first.
Nothing wrong with sorting in-place, and making a copy of the vector. The code you have should work, though it is not clear from where your parameter t is coming.
Note that the statement vii.reserve(t) is not doing anything useful in your sort routine: either t is less than or equal to the size of vii, in which case the reserve call does nothing, or it is greater than the size of vii, in which case you are accessing values outside the range of the vector. Better to check t against the vector size and throw an error or similar if it is too big.
Passing by value is straightforward: just declare your sort routine as double sort(int t, intv vii). When the function is called, vii will be copied from whichever vector you pass in as the second argument.
From a design point of view though, it is better to make a copy and then pass a reference. Sorting should change the thing being sorted; passing by value in the context of your code would mean that nothing would be able to inspect the sorted result.