I am a beginner and I would like to ask you something.
We have an array whose size depends on value input by user in a variable ‘arraysize’. Look at below code and comments please, is it a correct way to achieve this said be behaviour?
int * myArray = NULL;
int arraySize;
cout << "Enter array size: ";
cin >> arraySize;
myArray = new int[arraySize];
delete [] myArray;
The earlier answer was a community wiki. Since you asked for an example, here's a more detailed answer.
A std::vector is a class belonging to the standard template library read in detail.
//since you used "using namespace std;" I'm omitting the "std::"
Declaration
vector< int > v; //creates a vector of integers
vector< double > vd; //vector of double values
This is quite similar to int a[/*any number*/].
Inserting values
v.push_back(5); //adds 5 to the end of the vector (or array of variable size)
With the above two lines you dont need to know in advance how many numbers you'll have to store.
One more sample code.
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector;
int myint;
std::cout << "Please enter some integers (enter 0 to end):\n";
do {
std::cin >> myint;
myvector.push_back (myint);
} while (myint);
std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n";
return 0;
}
This program reads values and saves to myvector till 0 is entered in input.
Iteration
std::vector<int>::size_type sz = myvector.size(); //even int works here
// assign some values:
for (unsigned int i=0; i<sz; i++) myvector[i]=i;
Deletion
v.pop_back(); //removes last element
Use std::vector as a C++ best practice.
Related
I have following piece of code,
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int input,n;
cin >> n;
vector<int> v(n);
for(int i=0;i<n;i++){
cin>>input;
v.push_back(input);
}
for(int i=0; i<v.size();i++){
cout << v[i] << endl;
}
cout << v.size() << endl;
return 0;
}
and
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int input,n;
vector<int> v(n);
cin >> n;
for(int i=0;i<n;i++){
cin>>input;
v.push_back(input);
}
for(int i=0; i<v.size();i++){
cout << v[i] << endl;
}
cout << v.size() << endl;
return 0;
}
for the following input, n=5, 1 2 3 4 5 , first program gives the output
0
0
0
0
0
1
2
3
4
5
10
and the second program gives the result
1
2
3
4
5
5
I donot understand why vector is initializing 0's in the first doubling the size but not in the second
Actually, neither of those are correct for what you want (I'm assuming here you want the five elements you input and nothing more - that may be an invalid assumption but it seems like a good bet to me).
In your first one, you have (comments added to explain what's happening):
int input,n; // n has arbitrary value.
cin >> n; // overwritten with 5.
vector<int> v(n); // initial vector has five zeros.
This means your vector will be created with five (assuming you input that for n) default-constructed entries. Then you go and insert five more, which is why you get five zeros followed by your actual data.
Your second one has:
int input,n; // n has arbitrary value.
vector<int> v(n); // initial vector of that arbitrary value (probably).
cin >> n; // overwritten with five but it's too late anyway.
This is actually undefined behaviour since you have no idea what n will be when you create a vector of that size. In your case, it appears to be zero but that's just a lucky coincidence.
Note the use of the word "probably" above. While it's likely that the vector will be created with some arbitrary number of entries, undefined behaviour means exactly that - you should not rely on it at all. By rights, it could quite easily delete all your files while playing derisive_laughter.wav through your sound system :-)
The most likely case however will be one of:
it'll work as you thought, because n is zero;
it'll have some arbitrary number of zeros at the start, similar to your first code snippet;
it'll cause an out-of-memory exception because n is ridiculously large; or
it'll cause an exception because n is negative.
In any case, you should generally either pre-allocate and just set the already-existing values:
vector<int> v(2);
v[0] = 7;
v[1] = 42;
or not pre-allocate, using push_back to expand the vector on demand:
vector<int> v;
v.push_back(7);
v.push_back(42);
Hope, one can write the 1st case of writing program in the question in the following way to get correct result
1
2
3
4
5
5
for the input given as in the question
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> v(n);
for(int i=0;i<n;i++){
cin>>v.at(i);
}
for(int i=0;i<v.size();i++){
cout << v[i] << endl;
}
cout << v.size() << endl;
return 0;
}
I'm trying to get a vector of string from input to create a graph , but i don't know why in middle my code it crashes. please help me fix it. I use Visual Studio.
#include <iostream>
#include <vector>
#include <iterator>
void main(void)
{
{
using namespace std;
int8_t n{ 0 };
cout << "enter the size of graph : ";
cin >> n;
vector<string> graph(n);
string connectionsWith;
vector<string>::iterator i;
string::iterator e;
int p{ 0 };
for (i = graph.begin(); i != graph.end(); ++i)
{
cout << '\n' << "enter the vertices that are connected to " << p << " : ";
cin >> connectionsWith;
graph.push_back(connectionsWith);
p++;
}
p = 0;
for (i = graph.begin(); i != graph.end(); ++i)
{
cout << p << " is connected to " << *i;
p++;
}
}
}
In your constructor of graph, you allocate n string. Inside the loop you add on top of the constructed n strings, n more strings via push back. That potentially invalidates your iterators, as ChrisMM said, also not the most efficient way to implement such a scenario.
So as a solution, instead of
vector<string> graph(n);
do
vector<string> graph;
graph.reserve(n);
and iterate over the index, e.g. from 0 to n, and push back.
Especially in the first loop you are not dereferencing the iterator at all, which suggests that using index based loop would show your intent better.
life_steal pointed out the problem. I would like to add few information and other way to solve the problem.
int8_t n{ 0 };
vector<string> graph(n); // Here initialization happening with ASCII. If input is "1" then it would be "49". Consider changing int8_t to int if you unaware of that.
graph.push_back(connectionsWith); //Instead of this line Use: *i = connectionsWith; it directly assign the value.
My goal is to try and create a program that takes in grades in percents and multiply it with their weight value (either in decimal form or percent form). The equation is basically:
Overall grade = (grade1*weightInDecimal1)+(grade2*weightInDecimal2)+(grade3*weightInDecimal3)+...
or
Overall grade = (grade1*weight%1)+(grade2*weight%2)+(grade3*weight%3)+...
Is there a way to store the inputs and then recall it later in the code? Or possibly a more efficient way?
I also want to try and make a dynamic array. I want to make a program that asks the user for how many assignments they have and makes an array based on that. That way it's not stuck at 4 assignments
#include <string>
#include <iostream>
using namespace std;
int main() {
int numbers[4][2];
for(int i=0;i<4;i++)
{
cout<<"Grade #"<<i<<endl;
cin>>numbers[i][0];
cout<<"Weight for grade #"<<i<<":"<<endl;
cin>>numbers[i][1];
}
for (int i = 0; i<4; i++)
{
cout << "|" << numbers[i][0]*numbers[i][1]<< "|";
}
system ("PAUSE");
return 0;
}
This is what structs are for
#include <string>
#include <iostream>
#include <array>
using namespace std;
struct entry {
int grade;
int weight;
int gradeWeight; //grade*weight
};
int main() {
array<entry,4> numbers;
for(int i=0;i<numbers.max_size();i++)
{
cout<<"Grade #"<<i<<endl;
cin>>numbers[i].grade;
cout<<"Weight for grade #"<<i<<":"<<endl;
cin>>numbers[i].weight;
}
for (int i = 0; i<numbers.max_size(); i++)
{
numbers[i].gradeWeight = numbers[i].grade*numbers[i].weight;
cout << "|" << numbers[i].gradeWeight << "|";
}
system ("PAUSE");
return 0;
}
This way you can also increase the amount of numbers by just increasing the array size.
As pointed by others, if you ask the user for how many assignments they have, std::array is a wrong container because it's dimension is fixed at compile time.
As others, I discurage the use of direct memory allocation but the use of std::vector to manage it.
I just suggest the use of reserve() (method of std::vector), when you know how many assignments.
The following is a full example using, instead a couple of std::vector of int, a single std::vector of std::pair<int, int>
#include <utility>
#include <vector>
#include <iostream>
int main()
{
int valG, valW;
std::size_t dim;
std::vector<std::pair<int, int>> vec;
std::cout << "How many grade/weight couples? ";
std::cin >> dim;
vec.reserve(dim);
for ( auto i = 0U ; i < dim ; ++i )
{
std::cout << "Grade #" << i << "? " << std::endl;
std::cin >> valG;
std::cout << "Weight for grade #" << i << "? " << std::endl;
std::cin >> valW;
vec.emplace_back(valG, valW);
}
for ( auto const & p : vec )
std::cout << '|' << (p.first * p.second) << '|';
std::cout << std::endl;
return 0;
}
There are many reasons to avoid using arrays (dynamic or otherwise). See for example Stroustrup's FAQ entry What's wrong with arrays? As Greg suggests in the comments you will most likely write better quality code if you use a container like std::vector.
If you can calculate or input the size of your container before allocating it you can (if you wish) pass that size to the constructor ...
auto syze{ 0 };
auto initialValue{ 0 };
// calculate or input syze
. . .
// dynamically allocate an "array"
// of ints and an "array" of floats
std::vector<int> grades(syze, initialValue);
std::vector<float> weights(syze, initialValue);
On the other hand if you prefer to use a container that dynamically grows to hold data as it arrives you can do that too...
// dynamically allocate an empty "array"
// of ints and an empty "array" of floats
std::vector<int> grades;
std::vector<float> weights;
while (...condition...)
{
std::cin >> g; // input a grade ...
std::cin >> w; // ... and a weight
// grow the containers by adding
// one item at the end of each
grades.emplace_back(g);
weights.emplace_back(w);
}
Update
I should have pointed out how to calculate the result from the two vectors. You can calculate your overall grade with just one more line of code by using std::inner_product from the STL's <numeric> header. Note that in the code below the last argument is 0.0 (rather than just 0) so that std::inner_product returns a double rather than an int. That avoids any risk of float values being truncated to int (and avoids some pretty ugly warnings from the compiler).
auto overallGrade = std::inner_product(grades.begin(), grades.end(), weights.begin(), 0.0);
I'm doing some exercises with vectors. I created a function that fill a vector with defined size but when I tried to make it n size, the vector apparently is filled with trash memory, it shows: 0x23fe20, and my code crash when I try to use the vector.
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
using namespace std;
int cargavn(int vec[]) // fill vector
{
int i, t;
cout << "vector size: ";
cin >> t;
for(i = 0 ; i <= t-1; i++)
{
cout << "v["<< i <<"]=";
cin >> vec[i];
}
return (1);
}
int main()
{
int vec[10]; // the vector, size here wont matter
cargavn(vec); // call fill vector n positions
cout << vec; // to test if the vector is well filled
system("PAUSE");
}
you are exprecting cout << vec to somehow pretty print the vector. It wont, it just prints its address
You need to loop over the contents and print each element
for(int i =0 ; i < 10 ; i++)
{
cout << vec[i];
}
Here's how it would look using modern C++:
#include <iostream>
#include <vector>
using namespace std;
void cargavn(vector<int> &vec)
{
int t;
cout << "vector size: ";
cin >> t;
for(int i = 0; t > 0; ++i, --t)
{
cout << "v["<< i <<"]=";
int v;
cin >> v;
vec.push_back(v);
}
}
ostream &operator<<(ostream &s, vector<int> const &vec)
{
s << '{';
bool first = true;
for (int v : vec)
{
if (!first)
{
s << ", ";
}
s << v;
first = false;
}
return s << '}';
}
int main()
{
vector<int> vec;
cargavn(vec);
cout << vec;
system("PAUSE");
return 0;
}
Things to understand about this version compared to yours:
Unnecessary includes are ommitted.
Prefer C++ containers like vector over C style arrays.
Use dynamically sized containers when they need to hold an arbitrary number of values provided by the user instead of fixed-size containers that break when the user enters too much data. See the rule of 0, 1, infinity.
When all control paths of a function return the same value, then the returned value is pointless and can be omitted. Particularly if none of the callers even bothers to check the return value. I suspect you had the intention of using the return value to indicate some kind of unexpected error. This is a C-style approach to error handling. C++ uses exceptions to deal with unexpected errors.
Overload operator<< to extend the stream insertion operator to decide how containers and your own custom types should be formatted. The standard library doesn't provide any such insertion operator for vector because there isn't any universally agreed upon way to decide how a vector of values should be formatted. So you decide this for yourself.
It is good form for main to return a value, even though this is not technically required.
So this is my main method:
#include <iostream>
#include "TextFileToArray.h"
#include <vector>
using namespace std;
int main()
{
cout << "Hello world!" << endl;
TextFileToArray myobject("C:/bunz.txt");
vector<string> v[10];
myobject.vectorfiller(*v);
for(int i =0; i<10; i++){
cout << v;
}
}
It calls upon an object known as myobject and it calls upon a method/function. Here is the method/function:
int TextFileToArray::vectorfiller(vector<string>& givenpointer) {
vector<string> *innervec = &givenpointer;
const char * constantcharversion = path.c_str();
ifstream filler(constantcharversion);
string bunz;
string lineoutliner = "Line ";
string equalssign = " = ";
int numbercounter = 1;
while (!filler.eof()) {
std::getline(filler, bunz, ';');
if (bunz.empty()) {
lineoutliner = "";
numbercounter = 0;
equalssign = "";
}
cout << lineoutliner << numbercounter << equalssign << bunz <<endl;
cout << "" << endl;
innervec->push_back(bunz);
numbercounter++;
}
filler.close();
return 0;
}
So far it displays the text from the textfile, but for some reason it pushes memory addresses into the vector, so when main() displays the vector, it shows memory locations:
vector<string> v[10]; creates an array of 10 vectors, which is probably not what you want.
Create a single vector, pass that as parameter, and output its contents:
vector<string> v;
myobject.vectorfiller(v);
for(int i =0; i < v.size(); i++){
cout << v[i];
}
Agree, size should not be 10, should be size(), and count<
The problem is that you're printing the array of vectors, not the elements in the first vector. Instead, you want this in your main:
for (int i = 0; i < v[0].size(); i++) {
cout << v[0][i] << endl;
}
PS: As Luchian said, you are creating 10 vectors, not one vector with 10 slots. To get just one vector do this:
vector<string> v;
You also don't need to mention 10; vectors grow when you push elements on them. If you happen to know how much space you want to be reserved ahead of time, you can use the reserve member function like so:
vector<string> v;
v.reserve(some_number);
reserve doesn't change the size of v; it only makes the vector ready to accept that many elements, so that it doesn't have to reallocate memory, and copy things around as much. It is purely an optimization; if you were to simply comment out reserve calls in your program, it will behave exactly the same. The only thing that might change is performance, and memory usage.