Printing Vector Array with push_back [duplicate] - c++

This question already has answers here:
Why does my vector print out all zeroes?
(4 answers)
Closed 1 year ago.
I'm trying to show the values of a dynamic array input using vector and a for range loop but when it prints it shows the 0's then the value that was input.
Please don't mind the if statement as I commented it out to use a smaller sample size when testing. But if I enter the size say its 3 then input values such as 1,2,3 the output would be 0 0 0 1 2 3. I'm trying to remove the first three 0's.
int main()
{
std::cout << "How many numerical values do you wish to enter: ";
int values, index, collect;
std::cin >> values;
std::vector<int> numbers(values);
//if(values == 31)
//{
for (index = 0; index < values; index++)
{
std::cout << "Enter value[" << (index + 1) << "]: ";
std::cin >> collect;
numbers.push_back(collect);
}
for (auto &showNumbers : numbers)
{
std::cout << showNumbers << " ";
}
//}
return 0;
}

This line creates a vector of values elements.
std::vector<int> numbers(values);
When you're entering the 3 as values, the vector will hold a three elements with values of 0.
Then you're pushing 3 more elements:
numbers.push_back(collect);
You could either:
replace std::vector<int> numbers(values); with std::vector<int> numbers; (this will create empty vector), or
replace numbers.push_back(collect); with numbers.at(index) = collect; (this will set element value)

Just do numbers[index] = collect; and you are good. You can even try this cin >> numbers[index];

You are using a constructor in
std::vector<int> numbers(values);
In your case:
values = 3
which sets the first 3 contents as zeros. Then using push_back you are adding values further. You must just declare the vector as:
std::vector<int> numbers;

Related

Correctly reading a known number of integer inputs into a vector in C++

I'm new to C++ and wanted to make a small function today which would flip all the elements of an array that was given to it (I had a pretty good idea for it). I started using arrays, but ran into issues since only a pointer to the first element is passed to the function; it was giving some very strange output. It was recommended I use a vector instead, but that started to give me some really odd output, too. I added a cout iterating over the vector values to see what it contains for some sanity-checking, but the outputs are completely bizarre; looks like I'm struggling to work out how to read input into it correctly.
As I mentioned, I first tried an array, which I could read into fine with a range-for loop. I tried that same thing with vectors (solution 1) and found it to be ignoring the first input, and assigning each element the last value that I gave it.
I first tried other Stack overflow threads but I found the solutions far too verbose or not suitable for something as simple as I need.
I thought maybe the vector couldn't be used in the range-for so I did for(auto x : array_size) instead - this gave an error stating there was no suitable "begin" for the function, so I changed this back.
Instead I looked around at the documentation and found .push_back(value) (solution 2) which appeared to put a given value at the end of the vector. Thought I might at least get some input into it correctly, which would be a step in the right direction. Instead, the output seems to show it doubled the number of positions in the vector and just assigned my first input to the furthest position. I imagine this is due to me specifying a size for the vector, and then having push_back grow the vector by that number of inputs (resulting in a double-size vector).
As for the input values themselves, I'm stumped.
Below is the offending bit of code as it stands with solution 2.
int main()
{
int array_size;
auto index_num = 0;
int arr_input = 0;
std::cout << "This program flips an array." << "\n";
std::cout << "Enter how many elements will be in your array: ";
std::cin >> array_size;
std::vector<int> user_array (array_size);
std::cout << "Fill your array with integer values. Press 'Enter' after each: " << std::endl;
for(auto x : user_array)
{
std::cin >> arr_input;
user_array.push_back(arr_input);
}
index_num = sizeof(user_array) / sizeof(user_array[0]); //or just use array_size-1 instead?
std::cout << "Your array, unflipped, contains the values: " << "\n";
for(auto y : user_array)
{
std::cout << "[" << user_array[y] << "] ";
}
Solution 2 provides this output:
Fill your array with integer values. Press 'Enter' after each:
1
2
3
4
5
Your array, unflipped, contains the values:
[0] [0] [0] [0] [0] [0] [0] [0] [0] [1]
Solution 1, where I attempt to input directly into the n-th location of the vector (as I would with an array) provides this output (with the same five 1 - 5 inputs):
Your array, unflipped, contains the values:
[0] [5] [5] [5] [5]
No error messages, everything is perfectly legal, I clearly just don't understand how something simple like a vector is implemented here.
I haven't even got to the taxing bit yet - flipping the array! Any advice appreciated.
std::vector<int> user_array (array_size) creates a vector containing array_size zeros. You then use push_back which adds additional elements to the end. You need to create an empty vector using std::vector<int> user_array, and optionally with a capacity of array_size by calling user_array.reserve(array_size). Since your vector starts out empty now, you'll need to change for(auto x : user_array) to a non-range-based loop such as for (int i = 0; i < array_size; i++).
sizeof(user_array) / sizeof(user_array[0]) only works with plain C arrays, not vectors. Use array_size or user_array.size().
In the last range-based for loop, y is the values in the array, not the indices. So print y, not user_array[y].
You seem to be confusing std::vector with C-style arrays.
std::vector<int> user_array (array_size);
initializes user_array with array_size zeroes.
for(auto x : user_array)
{
std::cin >> arr_input;
user_array.push_back(arr_input);
}
As noticed by Alexander Zhang, this piece modifies the vector while iterating over it, which results in Undefined Behaviour. It could result in anything happeining in your program, including infinite loop, crashing completely, supposingly working correct or demons flying out of your nose
index_num = sizeof(user_array) / sizeof(user_array[0]); //or just use array_size-1 instead?
This line makes no sense. You can get the length of vector using its size() method: user_array.size();, but you don't use that variable anyway.
for(auto y : user_array)
{
std::cout << "[" << user_array[y] << "] ";
}
This loop makes no sense either. y is not an index in the vector, it is a value from that vector. If you have a vector {10, 20, 30}, then in first iteration y is equal to 10, in second iteration y is 20 and in third y is 30.
After fixing the errors, your code should look like this:
std::vector<int> user_array ();
std::cout << "Fill your array with integer values. Press 'Enter' after each: " << std::endl;
for(int i = 0; i < array_size; ++i)
{
std::cin >> arr_input;
user_array.push_back(arr_input);
}
std::cout << "Your array, unflipped, contains the values: " << "\n";
for(auto y : user_array)
{
std::cout << "[" << y << "] ";
}
Or for an (invisible) increase in performance, you can reserve the size of the vector before you read it:
std::vector<int> user_array ();
user_array.reserve(array_size);
std::cout << "Fill your array with integer values. Press 'Enter' after each: " << std::endl;
for(int i = 0; i < array_size; ++i)
{
int x;
std::cin >> x;
user_array.push_back(x);
}

Iterating values into a vector while reading in a file using getline

I am trying to create a vector filled with values of the size of each string line of a file of 'blokus tiles' (tiles of periods or stars that are of dimensions 5x5). The file is read in as a vector of vectors of strings,
vector <std::string> tile
vector <vector<string>> alltiles
I am trying iterate values into a vector that stores the sizes of the tile strings (each line). I am doing this to later output an error if each line is not the same length, or each line is an incorrect length, or if there are other characters besides stars (*) or periods (.). I did this to print the size of the tiles in the file blokusstatus.txt (which was entered as a command line argument),
if (infile.is_open()) {
while (std::getline(infile, tileline)) {
int actualtilesize = tileline.length();
cout << actualtilesize << std::endl;
tile.push_back(tileline);
alltiles.push_back(tile);
}
}
infile.close();
//print out the contents of the file
std::ofstream outfile;
outfile.open(arginfile);
for (auto e: tile) {
cout << e << std::endl;
}
Here is the result:
ec327#ec327-VirtualBox:~$ ./w5blokus2 5 blokusstatus.txt
5
5
5
5
5
0
5
5
5
5
5
0
5
5
5
5
5
.....
.*...
**...
*....
*....
.....
.....
**...
*....
**...
.....
.....
*....
***..
*....
This looks good. However, I then try to make the list of numbers into a vector this way:
if (infile.is_open()) { //infile is open only if 3 or 4 arguments
int i = 0;
while (std::getline(infile, tileline)) {
for (int i=0; i <= tileline.end(); i++) {
vector <int> sizenums;
sizenums[i] = tileline.length();
i++;
cout << sizenums << std::endl;
}
//cout << actualtilesize << std::endl;
}
tile.push_back(tileline);
alltiles.push_back(tile);
}
infile.close();
std::ofstream outfile;
outfile.open(arginfile);
for (auto e: tile) {
cout << e << std::endl;
}
This gives quite a lengthy error when compiled, including
^~~~~~~~
/usr/include/c++/6/ostream:497:5: note: template argument
/substitution failed:
w5blokus3.cpp:80:15: note: deduced conflicting types for parameter
‘_CharT’ (‘char’ and ‘std::vector’)
cout << sizenums << std::endl;"
w5blokus3.cpp:80:15: note: cannot convert ‘sizenums’ (type
‘std::vector’) to type ‘char’
cout << sizenums << std::endl;
and I'm not sure what is wrong. I'm a newbie, thanks for any help or tips.
for (int i=0; i <= tileline.end(); i++) {
vector <int> sizenums;
sizenums[i] = tileline.length();
First, you create a new vector each iteration through the loop. You need to create the vector, then loop or iterate through it.
However, after
vector<int> sizenums;
your vector is empty. Direct access by [] won't work. Use push_back to add elements to the end:
vector <int> sizenums;
...
for (int i=0; i <= tileline.end(); i++) {
sizenums.push_back(tileline.length());
Also:
for(int i ...
...
i++;
Don't increase your loop variable manually. The for loop handles that already.
Two things, you need to iterate over the vector to print out the contents of it and you can't use sizenums[i] = tileline.length(); because the vector was just initialized, you have to use something like sizenums.push_back(tileline.length()); but then again the way you're using it is wrong anyway, you're reinitializing the variable each time you loop through therefore you've just used it to temporarily store one variable. Instead if you want to actually store each line length, then you need to move it outside the loops. And I don't know why you put i++; there again, it seems unnecessary.

Reading space separated input into an array in C++

What is the easiest way to read space separated input into an array?
//input:5
1 2 3 4 7
int main() {
int n;
cin>>n;
int array[n];
for (int i =0;i<n;i++){
cin>>array[i];
}
cout<<array;
return 0;
}
I tried the code above but the output is 0x7ffe42b757b0.
The problem lies with your printing. Since array is a pointer, you are only printing an address value.
Instead, do this:
for (int i =0;i<n;i++){
cout<< array[i] << " ";
}
You can do that by passing std::istream_iterator to std::vector constructor:
std::vector<int> v{
std::istream_iterator<int>{std::cin},
std::istream_iterator<int>{}
};
std::vector has a constructor that accepts 2 iterators to the input range.
istream_iterator<int> is an iterator that reads int from a std::istream.
A drawback of this approach is that one cannot set the maximum size of the resulting array. And that it reads the stream till its end.
If you need to read a fixed number of elements, then something like the following would do:
int arr[5]; // Need to read 5 elements.
for(auto& x : arr)
if(!(std::cin >> x))
throw std::runtime_error("failed to parse an int");
array variable always give base address of an array
for (int i =0;i<n;i++){
cout<< array[i] << " ";
cout<<*(array+i)<< " ";
}
Both cout statements will print same only.
in short
array[i] compiler will internally convert into *(array+i) like this only
in the second cout statement from base address of an array it won't add value,since it is an pointer it will add sizeof(int) each time for an increment

How do I add elements to an empty vector in a loop?

I am trying to create an empty vector inside a loop, and want to add an element to the vector each time something is read in to that loop.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<float> myVector();
float x;
while(cin >> x)
myVector.insert(x);
return 0;
}
But this is giving me error messages.
You need to use std::vector::push_back() instead:
while(cin >> x)
myVector.push_back(x);
// ^^^^^^^^^
and not std::vector::insert(), which, as you can see in the link, needs an iterator to indicate the position where you want to insert the element.
Also, as what #Joel has commented, you should remove the parentheses in your vector variable's definition.
std::vector<float> myVector;
and not
std::vector<float> myVector();
By doing the latter, you run into C++'s Most Vexing Parse problem.
Use push_back:
while(cin >> x)
myVector.push_back(x);
The insert function takes an iterator as the first argument, indicating the position to insert.
Also, you need to get rid of the parentheses in the declaration of myVector:
std::vector<float> myVector;
If you want to use myVector.insert(),
use it like myVector.insert(myVector.end(), x). This will append x at the end of myVector.
You can insert x in the beginning by myVector.insert(myVector.begin(), x).
Another option is to use std::vector::emplace_back() instead of std::vector::push_back(). The makes some optimizations and doesn't take an argument of type vector::value_type, it takes variadic arguments that are forwarded to the constructor of the appended item, while push_back can make unnecessary copies or movements.
This is demonstrated in the std::vector::emplace_back documentation and here is a related question.
Usage example:
std::vector<int> myVector;
while (cin >> x) {
myVector.emplace_back(x);
}
The code below may answer your question and also brings some other examples regarding how to insert new elements in different position or index.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vector_of_integers{};
vector_of_integers.push_back(1); // O(1)
vector_of_integers.push_back(3); // O(1)
vector_of_integers.push_back(5); // O(1)
vector_of_integers.push_back(7); // O(1)
for (int i = 8; i <= 10; i++)
vector_of_integers.push_back(i);
// Printing out all the elements of vector of integers - Method 1
copy(vector_of_integers.begin(), vector_of_integers.end(), ostream_iterator<int>(cout, " ")); // 1 3 5 7 8 9 10
cout << endl << endl;
// Inserting '2' at index 1
vector<int>::iterator it{ vector_of_integers.begin() };
advance(it, 1);
vector_of_integers.insert(it, 2); // O(N+M) => M is size of elements to be inserted
// Printing out all the elements of vector of integers - Method 2
for (auto const& element : vector_of_integers)
std::cout << element << " "; // 1 2 3 5 7 8 9 10
cout << endl << endl;
// "it" no longer valid, get a new one
it = vector_of_integers.begin();
vector_of_integers.insert(it + 4, 6); // O(N+M) => M is size of elements to be inserted
// Printing out all the elements of vector of integers - Method 3
for (it = vector_of_integers.begin(); it != vector_of_integers.end(); it++)
std::cout << *it << ' '; // 1 2 3 5 6 7 8 9 10
cout << endl << endl;
// insert '4' 7 times at index 3
vector<int> new_vector_to_be_inserted(7, 4);
vector_of_integers.insert(vector_of_integers.begin() + 3, new_vector_to_be_inserted.begin(), new_vector_to_be_inserted.end()); // O(N+M) => M is size of elements to be inserted
// Printing out all the elements of vector of integers - Method 4
for (int i = 0; i < vector_of_integers.size(); i++)
cout << vector_of_integers.at(i) << ' '; // 1 2 3 4 4 4 4 4 4 4 5 6 7 8 9 10
cout << endl << endl;
return 0;
}

Given a sequence of numbers report which have been repeated and how many times

for example
1 1 1 1 2 3 3 4 5 5 5
1 repeated 3 times,
3 repeated 1 time,
5 repeated 2 times
here's the code but it has some troubles
int i, k, m, number, number_prev, e;
cout << "Insert how many numbers: ";
cin >> m;
cout << "insert number";
cin >> number;
number_prev = number;
int num_rep[m]; //array of repeated numbers
int cant_rep[m]; // array of correspondent number of repetitions
e = 0;
for (i=1; i<m; i++)
{
cin >> number;
if (number == number_prev)
{
if (number == num_rep[e-1])
cant_rep[e-1]++;
else
{
num_rep[e] = number;
cant_rep[e] = e + 1;
e++;
}
}
else
e = 0;
number_prev = number;
}
for (k = 0; k < e; k++)
cout << "\nnumber " << num_rep[k] << " repeated " << cant_rep[k] << " times.\n";
You should learn algorithms and data structures. This make your code simpler. just using associative container that saves pair
a number --> how many times it repeats
can simplify your program sufficiently
int main()
{
std::map<int, int> map;
int v;
while(std::cin >> v) {
map[v]++;
}
for (auto it = map.cbegin(); it != map.cend(); ++it) {
if (it->second > 1) {
std::cout << it->first << " repeats " << it->second - 1 << " times\n";
}
}
}
std::map is an associative container.
You can think about it as a key-->value storage with unique keys.
The example in real word is a dictionary:
There you have word and its definition. The word is a key and the definition is a value.
std::map<int, int> map;
^^^ ^^^
| |
key type value type
You can refer to values using [] operator.
this works like usual array, except instead of index you use your key.
You can also examine all key-value pairs, storied in the map using iterators.
it = map.cbegin(); // refers to the first key-value pair in the map
++it; // moves to the next key-value pair
it != map.cend(); // checks, if we at the end of map, so examined all elements already
As, I pointed out, map saves key-value pairs.
And in Standard C++ library struct std::pair is used to express pair.
It has first and second members, that represents first and second values, storied in a pair.
In the case of map, first is a key, and second is a value.
Again, we are storing a number as a key and how many times it repeats in a value.
Then, we read user input and increase value for the given key.
After that, we just examine all elements stored in a map and print them.
int num_rep[m]; //array of repeated numbers
int cant_rep[m]; // array of correspondent number of repetitions
Here, m is only known when running, array sizes must be known in compile time. use std::vector instead.
The code seems like a C-style C++ program:
1.You don't need to declare variables in the beginning of block. Declare them before use, it's more readable.
2.Use the STL types like std::vector can save you a lot of trouble in programs like this.
you say "Insert m numbers", but for (i=1; i<m; i++) will loop m-1 times, which might not is what you want.
as a supplement advice, you should do input check for the variables get from external world.like cin >> m;, for it can be zero or negative.