Let's say I have a std::vector and I get by some means the address of the n-th element.
Is there a simple way (faster than iterating through the vector) to get the index at which the element appears, given the base address of my std::vector? Let's assume I'm sure the element is in the vector.
Since you know the element is within the vector, and vector guarantees that its storage is contiguous, you could do:
index = element_pointer - vector.data();
or
index = element_pointer - &vector[0];
Note that technically the contiguous guarantee was introduced in C++03, but I haven't heard of a C++98 implementation that doesn't happen to follow it.
distance( xxx.begin(), theIterator);
The above will only work for a vector::iterator. If you only have a raw pointer to an element, you must use it this way:
distance(&v[0], theElementPtr);
Yes - because a vector guarantees all elements are in a contiguous block of memory you can use pointer arithmetic to find it like so
#include <iostream>
#include <vector>
int main(int argc, char *argv[])
{
std::vector<int> vec;
for(int i=0; i<10; ++i)
{
vec.push_back(i);
}
int *ptr=&vec[5];
int *front=&vec[0];
std::cout << "Your index=" << ptr-front << std::endl;
return 0;
}
On the way of learning, I have taken the following notes:
#include <iostream>
#include <vector>
int main() {
std::vector<std::string> words={"This","is","just","a","trial!"};
size_t i; //using the contiguous property of a vector:
for (auto const& elem : words) {
i = &elem - &*words.begin();// or
i = &elem - &words.front();// or
i = &elem - words.data();// or
i = std::addressof(elem) - std::addressof(words[0]);
if(std::addressof(elem) == &words.front())
std::cout << elem <<" (at"<<&elem<<") relative to ("<< &words[0] << ") takes position ##"<<i<< std::endl;
else std::cout << elem <<" (at"<<&elem<< ") takes position ##"<<i<< std::endl;
}
return 0;
}
Test run here.
It is open to further study (or learn from masters) which one is the most secured/safe and/or most efficient approach.
Related
It is quite surprising that given that reserving size for a vector in anticipation helps improve the performance of the application and
ensures that costly relocations do not occur when it gets filled
to its capacity why there is no facility given to get a relocation_count
at any given time , this may very much help programmer track optimal
size to be allocated to vector in cases where the exact capacity may
need to be determined from average over period of observations as
exact figure may not be known upfront.
To count re-allocations of a std::vector, the std::vector (or at least the write access methods of it) might be wrapped into a helper class.
Sample code:
#include <iostream>
#include <vector>
template <typename VALUE>
struct AllocCounter {
std::vector<VALUE> &vec;
unsigned n;
AllocCounter(std::vector<VALUE> &vec): vec(vec), n(0) { }
void push_back(const VALUE &value)
{
size_t old = vec.capacity();
vec.push_back(value);
n += old != vec.capacity();
}
};
int main()
{
std::vector<int> values;
AllocCounter<int> countAllocs(values);
for (int i = 1; i <= 1024; ++i) {
unsigned nOld = countAllocs.n;
countAllocs.push_back(i);
if (countAllocs.n > nOld) std::cout << 'R';
std::cout << '.';
}
std::cout << '\n'
<< "Number of (re-)allocations: " << countAllocs.n << '\n';
// done
return 0;
}
Output:
R.R.R..R....R........R................R................................R................................................................R................................................................................................................................R................................................................................................................................................................................................................................................................R................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Number of (re-)allocations: 11
Live Demo on coliru
This sample is rather a proof of concept as it doesn't consider std::vector::emplace(), std::vector::resize(), etc.
Btw. if std::vector::push_back() is called directly the counting is by-passed (and may "overlook" re-allocations).
Using a custom allocator could solve this limitation.
just a quick one:
I plan to have an array of AVL Trees (for an assignment, as you imagined - does anyone ever use AVL trees apart from data structures students anyway?) and I was wondering if I could use a nice vector - and take advantage of the for(auto i : vect) c++ 11 functionality.
What I want to do: AVLTree array of 1.000.000 elements so I can check in CONSTANT time if the tree exists or not (array position will be NULL or not)
AVLTree_GeeksforGeeks **AVLArray = new (AVLTree_GeeksforGeeks*)[1000000];
for(int i=0; i<1000000; i++){ AVLArray[i] = nullptr; } //init everything to null
//do stuff with AVL trees
//...
if(AVLTree[52000]!=nullptr)
{
cout << "tree exists!\n";
}
Is there an equivalent with vectors, that will allow me constant time of searching for a tree? All the examples I've seen use vector.push_back() and vector.find() to search.
You can use std::vector as suggested by Exceptyon:
std::vector<unique_ptr<AVLTree>> trees(1000000);
by using also the smart pointers implemented in c++11. If your concern is dynamic resizing keep in mind that you can can reserve an initial amount of storage when you create the vector (by passing it as a parameter in the constructor) or via the resize member.
If your concern is random access to its objects, rest assured that the operator[] has O(1) complexity.
If you know the total capacity of the container at compile time you could also consider using c++11's std::array which provides the same for each functionality as well as the same constant time access to its elements.
std::array<unique_ptr<AVLTree>, 1000000> trees;
vector will work because they have an overloaded operator[] that guarantee constant time access to the nth element.
But your code is not clear:
AVLTree_GeeksforGeeks *AVLArray = new AVLTree_GeeksforGeeks[1000000];
for(int i=0; i<1000000; i++){ AVLArray[i] = nullptr; } //init everything to null
If you set to nullptr, then you need a pointer. Is AVLTree_GeeksforGeeks a typedef on a pointer ? I assume it is not the case, and that there is a typo -- otherwise you just have to remove this typedef definition to use std::unique_ptr<TheRealTyp>. So to clarify, I suppose your code is really:
AVLTree_GeeksforGeeks **AVLArray = new (AVLTree_GeeksforGeeks*)[1000000];
for(int i=0; i<1000000; i++){ AVLArray[i] = nullptr; } //init everything to null
In that case, as suggested you should use a std::vector<std::unique_ptr<AVLTree_GeeksforGeeks>>, and you won't have to initialize it to nullptr and the test of nullity changed for a direct "test" of std::unique_ptr:
std::vector<std::unique_ptr<AVLTree_GeeksforGeeks>> AVLArray(100000);
// Do stuff with AVL trees
if (AVLArray[52000])
{
cout << "tree exists!\n";
}
Now, how to use a std::vector<std::unique_ptr<X>> ?
Setting a value in the already allocated zone: AVLArray[5200] = std::unique_ptr(new AVLTree_GeeksforGeeks));
Setting a entry to null: AVLArray[5200].reset()
If you need to add something (the vector will grow): AVLArray.push_back(std::unique_ptr(new AVLTree_GeeksforGeeks));
To iterate over use for (auto& elem: AVLArray). The & is mandatory otherwise a copy construcotr is called and std::unique_ptr forbids this.
Here a example:
#include <iostream>
#include <vector>
#include <memory>
// boost
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/filtered.hpp>
class A {};
int main(int argc, char const *argv[])
{
std::vector<std::unique_ptr<A>> vector;
vector.resize(10000);
// Adding some values
if (!vector[100])
{
std::cout << "Adding vector[100]" << std::endl;
vector[100] = std::unique_ptr<A>(new A);
}
if (!vector[1000])
{
std::cout << "Adding vector[1000]" << std::endl;
vector[1000] = std::unique_ptr<A>(new A);
}
// Removing one
if (vector[100])
{
std::cout << "Removing vector[100]" << std::endl;
vector[100].reset();
}
std::cout << "Testing element." << std::endl;
auto printer = [](const std::unique_ptr<A>& elem) {
std::cout << "There is an elem !" << std::endl; };
// use auto& otherwise use unique_ptr(const unique_ptr&) that has been
// deleted)
for (auto& elem: vector)
{
if (elem)
{
printer(elem);
}
}
std::cout << "for_each element with filtering." << std::endl;
auto is_null = [](const std::unique_ptr<A>& elem) { return (bool) elem; };
// Just because I move boost range !
boost::for_each(vector | boost::adaptors::filtered(is_null), printer);
std::cout << "end !" << std::endl;
return 0;
}
I need to count letters from the string, sort them by count and cout results. For this purpose I'm trying to use vector and struct. Here is part of my code, but it's not working, because I don't know how to implement something:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct int_pair{
int key;
int value;
};
bool sort_by_value(int_pair left, int_pair right){
return left.value < right.value;
}
int main() {
string characters = "aasa asdfs dfh f ukjyhkh k wse f sdf sdfsdf";
vector<int_pair> most_frequent;
for (string::size_type i = 0; i <= characters.length(); i++) {
int int_char = (int)characters[i];
most_frequent[int_char]++; <-- I want to do something like this, but it's not working
}
sort(most_frequent.begin(), most_frequent.end(), sort_by_value);
for (vector<int_pair>::iterator it = most_frequent.begin(); it != most_frequent.end(); ++it) <-- is this call correct?
cout << " " << it->key << ":" << it->value << endl;
return 0;
}
At this code I have 2 parts that I don't know how to deal:
most_frequent[int_char]++; <-- I want to do something like this, but it's not working
and
for (vector<int_pair>::iterator it = most_frequent.begin(); it != most_frequent.end(); ++it) <-- is this call correct?
Maybe you can see any other mistakes and potential issues at this code.
I would use a std::map to determine the frequency of each letter, then copy that into a multimap while reversing the key and value to get them in order.
#include <iostream>
#include <map>
#include <algorithm>
template<class T, class U>
std::pair<U,T> flip_pair(const std::pair<T,U>& p) {
return std::make_pair(p.second,p.first);
}
int main(){
std::string characters = "zxcvopqiuweriuzxchajksdui";
std::map<char,int> freq;
std::multimap<int,char> rev_freq;
// Calculate the frequency of each letter.
for(char c: characters){
freq[c]++;
}
// Copy the results into a multimap with the key and value flipped
std::transform(std::begin(freq), std::end(freq),
std::inserter(rev_freq, rev_freq.begin()),
flip_pair<char,int>);
// Print out the results in order.
for(std::pair<int,char> p : rev_freq){
std::cout << p.first << ": " << p.second << std::endl;
}
};
This should do what you need:
most_frequent[int_char].key = int_char;
most_frequent[int_char].value++;
Yes, it sets the key many times, even though it doesn't need to.
When accessing the container with the key (vector is indexed with an integer, which is "the key" in your case), you don't have to store the key in the value field of the container again.
So you don't need your struct since you only need the value field and can can store the number of occurrences directly in the vector.
The idea is to fill the vector with 256 integers in the beginning, all initialized to zero. Then, use the vector index as your "key" (character code) to access the elements (number of occurrences).
This will result in a code similar to this:
// initialize with 256 entries, one for each character:
vector<int> counts(256);
for (string::size_type i = 0; i <= characters.length(); i++) {
// for each occurrence of a character, increase the value in the vector:
int int_char = (int)characters[i];
counts[int_char]++;
}
Once filling of the vector is done, you can find the maximum value (not only the value but also the key where it is stored) using the std::max_element algorithm:
vector<int>::iterator most_frequent =
std::max_element(counts.begin(), counts.end());
// getting the character (index within the container, "key"):
std::cout << (char)(most_frequent - counts.begin());
// the number of occurrences ("value"):
std::cout << (*most_frequent);
Here is your example with the changes (only printing the most frequent character, here it is the space so you don't see it): http://ideone.com/94GfZz
You can sort this vector, however, you will loose the key of course, since the elements will move and change their indices. There is a nice trick to process statistics like that: Use a reversed (multi)map (key, value reversed):
multimap<int,int> keyForOccurrence;
for (vector<int>::iterator i = counts.begin(); i != counts.end(); ++i) {
int occurrences = *i;
int character = i - counts.begin();
keyForOccurrence.insert(std::pair<int,int>(occurrences, character));
}
Updated code: http://ideone.com/Ub5rnL
The last thing you should now sort out by yourself is how to access and process the data within this map. The fancy thing about this reversed map is that it is now automatically sorted by occurrence, since maps are sorted by key.
I find more natural to use a std::map container to store each character occurrences. The character is map's key, its occurrence count is map's value.
It's easy to scan the source string and build this map using std::map::operator[], and ++ to increase the occurrence count.
Then, you can build a second map from the above map, with key and value inverted: so this map will be sorted by occurrences, and then you can print this second map.
Note that you have to use a std::multimap as this second map, since its keys (i.e. the occurrences) can be repeated.
Sample code follows (I tested it with VS2010 SP1/VC10):
#include <stddef.h> // for size_t
#include <algorithm> // for std::transform
#include <functional> // for std::greater
#include <iostream> // for std::cout
#include <iterator> // for std::inserter
#include <map> // for std::map, std::multimap
#include <ostream> // for std::endl
#include <string> // for std::string
#include <utility> // for std::pair
using namespace std;
int main()
{
string str = "aasa asdfs dfh f ukjyhkh k wse f sdf sdfsdf";
// Build the occurrences map (char -> occurrences)
map<char, size_t> freq;
for (size_t i = 0; i < str.length(); ++i)
freq[ str[i] ]++;
// Build a new map from previous map with inverted <key, value> pairs,
// so this new map will be sorted by old map's value (i.e. char's
// occurrences), which is new map's key.
// Use the std::greater comparator to sort in descending order.
multimap<size_t, char, greater<size_t>> sorted_freq;
transform(
freq.begin(), freq.end(), // source
inserter(sorted_freq, sorted_freq.begin()), // destination
[](const pair<char, size_t>& p) // invert key<->value
{
return pair<size_t, char>(p.second, p.first);
}
);
// Print results
for (auto it = sorted_freq.begin(); it != sorted_freq.end(); ++it)
cout << it->second << ": " << it->first << endl;
}
Output:
: 9
s: 7
f: 7
d: 5
a: 4
k: 3
h: 3
u: 1
w: 1
y: 1
j: 1
e: 1
If you don't want to print the space character occurrences, you can easily filter that out.
Note that using std::map/std::multimap will also scale up better than std::vector for non-ASCII characters, e.g. if you use Unicode UTF-32 (since Unicode characters are much more than just 256).
I have two questions but they are interlinked.:
part:a->
I have been trying to display the elements of vector in reverse order. But nothing is working. I have used iterotar like;
for (it=vec.end(); it!=vec.begin(); --it){
// it is iterator not reverse_iterator.
// do work
}
P.S I am not much familiar with iterators. I have used them for the first time today to
display elem in reverse order.
also tried;
for (int i=vec.size(); i!=0; i--){
//display
}
No matter what I do it always display the elem in same order as they are present i.e not in the reverse order.
part_b->
Is there any way that I can store the output of a recursive function direct into a vector. like the code is:
I know this does not work. I have tried but just giving you an idea
what I am upto.
#include <iostream>
using namespace std;
#include "vector"
int func(int num);
vector <int> vec;
int main() {
int num=34;
// I know this would not work. But is there any possibilitiy that
// I can store the output in a vector.
vec = binary(num);
// trying to display the vector.
for (int i=vec.size();i!=0;i--) {
cout<<vec[i]<<" ";
} // not working for reverse display.
} //main.
int func(int num) {
if (num==1) {
//vec.push_back(1);
return 1;
}
else if(num==0) {
//vec.push_back(0);
return 0;
}
else {
//vec.push_back(input%2);
return binary(input/2);
}
} //func.
I hope you do unnderstand the question. if I am able to do the part b the there is no need to reverse the elem of the vector.
The standard solution uses reverse iterators:
for (auto it = v.rbegin(); it != v.rend(); ++it)
{
if (it != v.rbegin()) { std::cout << ' '; }
std::cout << *it;
}
Alternatively, you can use indices, but keep the "reversal" idiom and increment the index:
for (std::size_t i = 0; i != v.size(); ++i)
{
if (i != 0) { std::cout << ' '; }
std::cout << v[v.size() - i - 1];
}
Note that reverse iterators are literally just doing something very similar to the explicit loop under the hood. In particular, the base() member function of a reverse iterator gives you the corresponding ordinary iterator offset by one, just as we have a - 1 in the index computation. (E.g. rbegin() is just end() under the hood, but decrements by one upon dereferencing.)
Use reverse iterators:
for (auto it = vec.crend(); it != vec.crbegin(); ++it) {
std::cout << *it << ' ';
}
std::cout << '\n';
Part A
Assuming you haven't got access to C++11:
vector<int>::const_reverse_iterator it;
for (it=vec.rbegin(); it!=vec.rend(); ++it)
{
// do work
}
Part B
It looks very much like you're trying to display a number in binary. Unfortunately the standard flags on ostream only allow hex, decimal or octal as far as I'm aware, but can I suggest a simpler way of doing this?
#include <bitset>
bitset< sizeof(int) << 3 > b(34);
cout << b << endl;
Which gives:
00000000000000000000000000100010
The rather ugly looking sizeof(int) << 3 is just a way of getting the size of an int in bits to avoid truncation.
I wrote little program which may help. Maybe your vector is empty?
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char *argv[])
{
vector<int> vec;
vec.insert(vec.begin(), 1, 1);
vec.insert(vec.begin(), 1, 2);
vec.insert(vec.begin(), 1, 3);
vector<int>::iterator i;
for (i = vec.end(); i != vec.begin(); --i)
{
cout << *i;
}
cout << *i;
return 0;
}
Is there a way of printing arrays in C++?
I'm trying to make a function that reverses a user-input array and then prints it out. I tried Googling this problem and it seemed like C++ can't print arrays. That can't be true can it?
Just iterate over the elements. Like this:
for (int i = numElements - 1; i >= 0; i--)
cout << array[i];
Note: As Maxim Egorushkin pointed out, this could overflow. See his comment below for a better solution.
Use the STL
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <ranges>
int main()
{
std::vector<int> userInput;
// Read until end of input.
// Hit control D
std::copy(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(userInput)
);
// ITs 2021 now move this up as probably the best way to do it.
// Range based for is now "probably" the best alternative C++20
// As we have all the range based extension being added to the language
for(auto const& value: userInput)
{
std::cout << value << ",";
}
std::cout << "\n";
// Print the array in reverse using the range based stuff
for(auto const& value: userInput | std::views::reverse)
{
std::cout << value << ",";
}
std::cout << "\n";
// Print in Normal order
std::copy(userInput.begin(),
userInput.end(),
std::ostream_iterator<int>(std::cout,",")
);
std::cout << "\n";
// Print in reverse order:
std::copy(userInput.rbegin(),
userInput.rend(),
std::ostream_iterator<int>(std::cout,",")
);
std::cout << "\n";
}
May I suggest using the fish bone operator?
for (auto x = std::end(a); x != std::begin(a); )
{
std::cout <<*--x<< ' ';
}
(Can you spot it?)
Besides the for-loop based solutions, you can also use an ostream_iterator<>. Here's an example that leverages the sample code in the (now retired) SGI STL reference:
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
short foo[] = { 1, 3, 5, 7 };
using namespace std;
copy(foo,
foo + sizeof(foo) / sizeof(foo[0]),
ostream_iterator<short>(cout, "\n"));
}
This generates the following:
./a.out
1
3
5
7
However, this may be overkill for your needs. A straight for-loop is probably all that you need, although litb's template sugar is quite nice, too.
Edit: Forgot the "printing in reverse" requirement. Here's one way to do it:
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
short foo[] = { 1, 3, 5, 7 };
using namespace std;
reverse_iterator<short *> begin(foo + sizeof(foo) / sizeof(foo[0]));
reverse_iterator<short *> end(foo);
copy(begin,
end,
ostream_iterator<short>(cout, "\n"));
}
and the output:
$ ./a.out
7
5
3
1
Edit: C++14 update that simplifies the above code snippets using array iterator functions like std::begin() and std::rbegin():
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
short foo[] = { 1, 3, 5, 7 };
// Generate array iterators using C++14 std::{r}begin()
// and std::{r}end().
// Forward
std::copy(std::begin(foo),
std::end(foo),
std::ostream_iterator<short>(std::cout, "\n"));
// Reverse
std::copy(std::rbegin(foo),
std::rend(foo),
std::ostream_iterator<short>(std::cout, "\n"));
}
There are declared arrays and arrays that are not declared, but otherwise created, particularly using new:
int *p = new int[3];
That array with 3 elements is created dynamically (and that 3 could have been calculated at runtime, too), and a pointer to it which has the size erased from its type is assigned to p. You cannot get the size anymore to print that array. A function that only receives the pointer to it can thus not print that array.
Printing declared arrays is easy. You can use sizeof to get their size and pass that size along to the function including a pointer to that array's elements. But you can also create a template that accepts the array, and deduces its size from its declared type:
template<typename Type, int Size>
void print(Type const(& array)[Size]) {
for(int i=0; i<Size; i++)
std::cout << array[i] << std::endl;
}
The problem with this is that it won't accept pointers (obviously). The easiest solution, I think, is to use std::vector. It is a dynamic, resizable "array" (with the semantics you would expect from a real one), which has a size member function:
void print(std::vector<int> const &v) {
std::vector<int>::size_type i;
for(i = 0; i<v.size(); i++)
std::cout << v[i] << std::endl;
}
You can, of course, also make this a template to accept vectors of other types.
Most of the libraries commonly used in C++ can't print arrays, per se. You'll have to loop through it manually and print out each value.
Printing arrays and dumping many different kinds of objects is a feature of higher level languages.
It certainly is! You'll have to loop through the array and print out each item individually.
This might help
//Printing The Array
for (int i = 0; i < n; i++)
{cout << numbers[i];}
n is the size of the array
std::string ss[] = { "qwerty", "asdfg", "zxcvb" };
for ( auto el : ss ) std::cout << el << '\n';
Works basically like foreach.
My simple answer is:
#include <iostream>
using namespace std;
int main()
{
int data[]{ 1, 2, 7 };
for (int i = sizeof(data) / sizeof(data[0])-1; i >= 0; i--) {
cout << data[i];
}
return 0;
}
You can use reverse iterators to print an array in reverse:
#include <iostream>
int main() {
int x[] = {1,2,3,4,5};
for (auto it = std::rbegin(x); it != std::rend(x); ++it)
std::cout << *it;
}
output
54321
If you already reversed the array, you can replace std::rbegin and std::rend with std::begin/std::end, respectively, to iterate the array in forward direction.
It's quite straightforward to copy the array's elements to a suitable output iterator. For example (using C++20 for the Ranges version):
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
template<typename T, std::size_t N>
std::ostream& print_array(std::ostream& os, std::array<T,N> const& arr)
{
std::ranges::copy(arr, std::ostream_iterator<T>(os, ", "));
return os;
}
Quick demo:
int main()
{
std::array example{ "zero", "one", "two", "three", };
print_array(std::cout, example) << '\n';
}
Of course it's more useful if we can output any kind of collection, not only arrays:
#include <algorithm>
#include <iterator>
#include <iosfwd>
#include <ranges>
template<std::ranges::input_range R>
std::ostream& print_array(std::ostream& os, R const& arr)
{
using T = std::ranges::range_value_t<R>;
std::ranges::copy(arr, std::ostream_iterator<T>(os, ", "));
return os;
}
The question mentions reversing the array for printing. That's easily achieved by using a view adapter:
print_array(std::cout, example | std::views::reverse) << '\n';
// Just do this, use a vector with this code and you're good lol -Daniel
#include <Windows.h>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<const char*> arry = { "Item 0","Item 1","Item 2","Item 3" ,"Item 4","Yay we at the end of the array"};
if (arry.size() != arry.size() || arry.empty()) {
printf("what happened to the array lol\n ");
system("PAUSE");
}
for (int i = 0; i < arry.size(); i++)
{
if (arry.max_size() == true) {
cout << "Max size of array reached!";
}
cout << "Array Value " << i << " = " << arry.at(i) << endl;
}
}
If you want to make a function that prints every single element in an array;
#include <iostream>
using namespace std;
int myArray[] = {1,2,3,4, 77, 88};
void coutArr(int *arr, int size){
for(int i=0; i<size/4; i++){
cout << arr[i] << endl;
}
}
int main(){
coutArr(myArray, sizeof(myArray));
}
The function above prints every single element in an array only, not commas etc.
You may be wondering "Why sizeoff(arr) divided by 4?". It's because cpp prints 4 if there's only a single element in an array.