I am trying to print all the elements in a vector using a pointer. What is wrong in the code?
#include <bits/stdc++.h>
using namespace std;
int main() {
vector <int> v = {1,2,3};
int * p;
for(p=v.begin();p != v.end();p++)
cout<<*p<<" ";
}
I get a compilation error.
You can use a pointer, you just really don't want to
using namespace std;
int main() {
vector <int> v = {1,2,3};
int * p;
for(p=v.data(); p != (&v[v.size()-1])+1 ; p++)
cout<<*p<<" ";
}
p=v.data() get you the pointer to the underlying element storage. See https://en.cppreference.com/w/cpp/container/vector/data
(&v[v.size()-1]) get you the address of the last element. +1to get the first invalid address.
Now why your code doesn't compile.
The type of v.begin() is std::vector::iterator. And an iterator cannot be cast to a pointer, that why you get the error :
cannot convert 'std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}' to 'int*' in assignment
Now, how to print all the elements ?
vector <int> v = {1,2,3};
for(const int& e : v )
cout<<e<<" ";
Or with iterator :
vector <int> v = {1,2,3};
for(auto it = v.begin(); it != v.end() ; it++ )
cout<<*it<<" ";
Or the fancy way :
vector <int> v = {1,2,3};
std::copy( v.begin(), v.end(), std::ostream_iterator<int>( std::cout, " "));
Note:
In the general case, you can find the type of an expression with
template <class T>
struct td ;
using namespace std;
int main() {
vector <int> v ;
td<decltype(v.begin())> d;
}
This will give you an error with the type:
error: aggregate 'td<__gnu_cxx::__normal_iterator<int*, std::vector<int> > > d'
has incomplete type and cannot be defined
What is wrong in the code?
You are using p in the for loop as though it is an iterator. Iterators and pointers are related but they are not the same.
Change p to be an iterator. There is nothing to be gained by making it a pointer.
std::vector<int>::iterator p;
for(p=v.begin();p != v.end();p++)
cout<<*p<<" ";
Related
I was recently asked this question in an interview of C++ where I
was asked to improve the below piece of code which fails when
adding two int's results in the result being long and return
type needs accordingly to be derived.
Here the below code fails because the decltype() based derivation is not intelligent enough to identify based on the actual range of values of input but the type and derives return type as same. Hence we need perhaps some metaprogramming template technique to derive the return type as long if T is int.
How can this be generalized any hints or clues?
I feel that decltype() won't be helpful here.
#include<iostream>
#include<string>
#include<climits>
using namespace std;
template<typename T> auto adder(const T& i1, const T& i2) -> decltype(i1+i2)
{
return(i1+i2);
}
int main(int argc, char* argv[])
{
cout << adder(INT_MAX-10, INT_MAX-3) << endl; // wrong.
cout << adder<long>(INT_MAX-10, INT_MAX-3) << endl; // correct!!.
return(0);
}
Hence we need perhaps some metaprogramming template technique to derive the return type as long if T is int.
Not so simple.
If T is int, you're non sure that long is enough.
The standard say only that
1) the number of bits for int (sizeof(int) * CHAR_BIT) is at least 16
2) the number of bits for long (sizeof(long) * CHAR_BIT) is at least 32
3) sizeof(int) <= sizeof(long)
So if a compiler manage a int with sizeof(int) == sizeof(long), this is perfectly legal and
adder<long>(INT_MAX-10, INT_MAX-3);
doesn't works because long can be not enough to contain (without overflow) the sum between two int's.
I don't see a simple and elegant solution.
The best that come in my mind is based on the fact that C++11 introduced the following types
1) std::int_least8_t, smallest integer type with at least 8 bits
2) std::int_least16_t, smallest integer type with at least 16 bits
3) std::int_least32_t, smallest integer type with at least 32 bits
4) std::int_least64_t, smallest integer type with at least 64 bits
C++11 also introduce std::intmax_t as the maximum width integer type.
So I propose the following template type selector
template <std::size_t N, typename = std::true_type>
struct typeFor;
/* in case std::intmax_t is bigger than 64 bits */
template <std::size_t N>
struct typeFor<N, std::integral_constant<bool,
(N > 64u) && (N <= sizeof(std::intmax_t)*CHAR_BIT)>>
{ using type = std::intmax_t; };
template <std::size_t N>
struct typeFor<N, std::integral_constant<bool, (N > 32u) && (N <= 64u)>>
{ using type = std::int_least64_t; };
template <std::size_t N>
struct typeFor<N, std::integral_constant<bool, (N > 16u) && (N <= 32u)>>
{ using type = std::int_least32_t; };
template <std::size_t N>
struct typeFor<N, std::integral_constant<bool, (N > 8u) && (N <= 16u)>>
{ using type = std::int_least16_t; };
template <std::size_t N>
struct typeFor<N, std::integral_constant<bool, (N <= 8u)>>
{ using type = std::int_least8_t; };
that, given a number of bits, define the corresponding smallest "at least" integer type.
I propose also the following using
template <typename T>
using typeNext = typename typeFor<1u+sizeof(T)*CHAR_BIT>::type;
that, given a type T, detect the smallest integer type that surely contain a sum between two T values (a integer with a number of bits that is at least the number of bits of T plus one).
So your adder() simply become
template<typename T>
typeNext<T> adder (T const & i1, T const & i2)
{ return {typeNext<T>{i1} + i2}; }
Observe that th returned value isn't simply
return i1 + i2;
otherwise you return the correct type but with the wrong value: i1 + i2 is calculated as a T value so you can have overflow, then the sum is assigned to a typeNext<T> variable.
To avoid this problem, you have to initialize a typeNext<T> temporary variable with one of two values (typeNext<T>{i1}), then add the other (typeNext<T>{i1} + i2) obtaining a typeNext<T> value, finally return the computed value. This way the sum in calculated as a typeNext<T> sum and you doesn't have overflow.
The following is a full compiling example
#include <cstdint>
#include <climits>
#include <iostream>
#include <type_traits>
template <std::size_t N, typename = std::true_type>
struct typeFor;
/* in case std::intmax_t is bigger than 64 bits */
template <std::size_t N>
struct typeFor<N, std::integral_constant<bool,
(N > 64u) && (N <= sizeof(std::intmax_t)*CHAR_BIT)>>
{ using type = std::intmax_t; };
template <std::size_t N>
struct typeFor<N, std::integral_constant<bool, (N > 32u) && (N <= 64u)>>
{ using type = std::int_least64_t; };
template <std::size_t N>
struct typeFor<N, std::integral_constant<bool, (N > 16u) && (N <= 32u)>>
{ using type = std::int_least32_t; };
template <std::size_t N>
struct typeFor<N, std::integral_constant<bool, (N > 8u) && (N <= 16u)>>
{ using type = std::int_least16_t; };
template <std::size_t N>
struct typeFor<N, std::integral_constant<bool, (N <= 8u)>>
{ using type = std::int_least8_t; };
template <typename T>
using typeNext = typename typeFor<1u+sizeof(T)*CHAR_BIT>::type;
template<typename T>
typeNext<T> adder (T const & i1, T const & i2)
{ return {typeNext<T>{i1} + i2}; }
int main()
{
auto x = adder(INT_MAX-10, INT_MAX-3);
std::cout << "int: " << sizeof(int)*CHAR_BIT << std::endl;
std::cout << "long: " << sizeof(long)*CHAR_BIT << std::endl;
std::cout << "x: " << sizeof(x)*CHAR_BIT << std::endl;
std::cout << std::is_same<long, decltype(x)>::value << std::endl;
}
In my Linux 64bit platform, i get 32bit for int, 64bit for long and for x and also that long and decltype(x) are the same type.
But this is true for my platform; nothing guaranties that long and decltype(x) are ever the same.
Observe also that trying to get a type for the sum of two std::intmax_t's
std::intmax_t y {};
auto z = adder(y, y);
gives an error and doesn't compile because isn't defined a typeFor for a N bigger that sizeof(std::intmax_t)*CHAR_BIT.
This question already has answers here:
error: invalid initialization of non-const reference of type ‘bool&’ from an rvalue of type ‘std::vector<bool>::reference {aka std::_Bit_reference}’
(2 answers)
Closed 4 years ago.
Why does iterating over a vector of bool ( w/ modifying the element) require the &&, and not the vector of int?
// junk10.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <algorithm>
#include <array>
#include <vector>
using namespace std;
int main()
{
vector<int> miv{ 1, 2, 3 };
for (auto &e : miv) { e = 15; } // Legal
vector<bool> mbv{ false };
for (auto &e : mbv) { e = true; } // Illegal
for (auto &&e : mbv) { e = true; } // Legal
return 0;
}
The way std::vector<bool> is implemented, is that for space efficiency each boolean occupies 1 bit and not 1 byte, as a boolean.
This means you cannot take a reference to it. A reference is a wrapped pointer, and you cannot have a pointer to a bit.
You can use auto && in C++ 11 to modify the bit, but note that auto does not become a boolean:
std::vector<bool> vec { 1, 0, 1 };
bool &&i = vec[1];
i = 1; // DOES NOT MODIFY VECTOR
auto &&k = vec[2];
k = 0; // MODIFIES VECTOR
for (bool i : vec)
std::cout << i;
100
I am very much new to C++11 and learning about the STL Libraries. I have written a code which is like this,
#include <bits/stdc++.h>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
void Print( const vector<int> &arrays )
{
for ( int x : arrays ) cout << x << ' ';
}
int main() {
int citys, cityPairs, fv, lv, w;
vector <int> fvarr;
vector <int> lvarr;
vector <int> warr;
vector <int> warr_temp;
vector <int> disjoint_pairs;
scanf("%d%d", &citys, &cityPairs);
for(int nr = 0; nr < cityPairs; nr++){
scanf("%d%d%d", &fv, &lv, &w);
fvarr.push_back(fv);
lvarr.push_back(lv);
warr.push_back(w);
warr_temp = warr;
}
for (int j = 0; j < citys; j++){
auto result = min_element(begin(warr_temp), end(warr_temp));
auto pos_temp = distance(begin(warr_temp), result);
cout << pos_temp;
auto pos = distance(begin(warr), result);
cout << pos;
disjoint_pairs.push_back(fvarr[pos]);
disjoint_pairs.push_back(lvarr[pos]);
warr_temp.erase(warr_temp.begin() + pos_temp);
}
// Print(disjoint_pairs);
}
What i am doing in this code is i am taking 3 vectors and 1 vector to copy the last one warr_temp = warr;. Then i am checking the minimum value in vectorwarr_temp and storing it's index in pos_temp, next i am storing that min value's index from vector warr into pos.
Now the problem is the first cout which is pos_temp giving me correct values but the second one which is pos giving me the output something like this,
-61-62-63-64
why is this happening? what are these numbers? are they pointers? I know that distance is a template so what is the right way to implement this?
If anyone can clear my doubts that would be very helpfull.
Sorry if stupid question!!!
The root cause of the problem is auto pos = distance(begin(warr), result); line. It gives unpredictable results because result and begin(warr) belong to different vectors.
result is iterator pointing to warr_temp element, it cannot be mixed with iterators pointing to warr elements like begin(warr).
To get element position in warr vector use std::find(begin(warr), end(warr), *result) instead:
auto warr_res = std::find(begin(warr), end(warr), *result);
auto pos = distance(begin(warr), warr_res);
It is kind of exasperating that std collections don't provide a functional map interface to fill a collection
std::vector< int > oldV = {1,3,5};
std::vector< int > newV = (oldV % [&](int v)-> int{ return v+1; });
newV.insert( oldV.begin(), oldV.end(), [&](int v)-> int{ return 2*v; });
Is there a simple header library that implements wrappers for functional style programming with std collections?
I don't see a way to do it such that it would apply both to things like std::vector and std::unordered_set without repeating the operator definition for each container. In the case of vector it would be like this:
#include <iostream>
#include <vector>
template <typename T, typename Lambda>
std::vector< T > operator |(const std::vector< T >& input, Lambda map)
{
std::vector< T > output;
for (const T& elem : input)
output.push_back( map(elem) );
return std::move(output);
};
int main()
{
std::vector< int > oldV = {1,3,5};
std::vector< int > newV = oldV | [&](int v) -> int { return v + 1; };
for(int i=0; i< newV.size() ; i++)
{
std::cout << newV[i] << std::endl;
}
};
For the case of std::unordered_set you would only have to replace push_back with insert
The pipe operator here has the same well known semantics as on Unix/Linux shells and some languages
You could use std::generate and std::transform to do this.
I am a lazy programmer. I want to use C++ vector to create a multidimensional array. For example, this code create a 3x2 2D array:
int nR = 3;
int nC = 2;
vector<vector<double> > array2D(nR);
for(int c = 0; c < nC; c++)
array2D.resize(nC, 0);
However, I am too lazy to
declare array2D's data type: vector<vector<double> >
C++ auto could solve this problem.
However, I am too lazy to
write loop(s) to allocate the space(s) for each object like array2D.
Writing a function could solve this problem.
However, I am too lazy to
write each function for each N-dimensional array.
write nested N-1 loops for allocating spaces.
wirte each function for each data type.
The C++11 variadic template with function recursion could solve this problem.
Is it possible ...?
This is what you want. (Tested on Microsoft Visual C++ 2013 Update 1)
#include <iostream>
#include <vector>
using namespace std;
template<class elemType> inline vector<elemType> getArrayND(int dim) {
// Allocate space and initialize all elements to 0s.
return vector<elemType>(dim, 0);
}
template<class elemType, class... Dims> inline auto getArrayND(
int dim, Dims... resDims
) -> vector<decltype(getArrayND<elemType>(resDims...))> {
// Allocate space for this dimension.
auto parent = vector<decltype(getArrayND<elemType>(resDims...))>(dim);
// Recursive to next dimension.
for (int i = 0; i < dim; i++) {
parent[i] = getArrayND<elemType>(resDims...);
}
return parent;
}
int main() {
auto test3D = getArrayND<double>(2, 3, 4);
auto test4D = getArrayND<double>(2, 3, 4, 2);
test3D[0][0][1] = 3;
test4D[1][2][3][1] = 5;
cout << test3D[0][0][1] << endl;
cout << test4D[1][2][3][1] << endl;
return 0;
}