A have a vector of strings in c++:
vector<string> myVect = {"A", "A", "A", "B", "B", "A", "C", "C", "foo", "A", "foo"};
How can I convert this to a vector of integers, so that each integer uniquely corresponds to a string in myVect?
i.e. I would like a vector
out = {0, 0, 0, 1, 1, 0, 2, 2, 3, 0, 3}
In addition, I would like a vector of the unique strings, each position corresponding to the number in out:
uniqueStrings = {"A", "B", "C", "foo"}
So far I have the following:
vector<string> uniqueStrings; // stores list of all unique strings
vector<int> out(myVect.size());
for (int i = 0; i < myVect.size(); ++i)
{
// seeing if this string has been encountered before
bool assigned = false;
for (int j = 0; j < uniqueStrings.size(); ++j)
if (!myVect.at(i).compare( uniqueStrings.at(j) ))
{
out.at(i) = j;
assigned = true;
break;
}
// if not, add new example to uniqueStrings
if (!assigned)
{
uniqueStrings.push_back(myVect.at(i));
out.at(i) = uniqueStrings.size();
}
}
This works, but surely there must be a better way?
Keep pushing them in a map where the string is the key and the value corresponds to the id of each string. Then the values of your map will uniquely correspond to the strings and the keys will be the unique strings.
Use a set.
# include <set>
...
set <string> uniqueStrings;
...
for (int i = 0; i < myVect.size(); ++i)
{
uniqueStrings.insert(myVect[i]);
}
Here's a more or less complete example of how you might use a std::map<> to maintain a mapping of unique strings to an integer ID:
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
// a simple functor type that makes it easier to dump the contents of a
// container of simple values or a container of std::pair
struct dump
{
template <typename K, typename V>
void operator()( typename std::pair<K,V> const& x)
{
cout << x.first << " ==> " << x.second << endl;
}
template <typename T>
void operator()( T const& x)
{
cout << x << endl;
}
};
#define NUM_ELEM(x) (sizeof(x)/sizeof(x[0]))
char const* data[] = {"A", "A", "A", "B", "B", "A", "C", "C", "foo", "A", "foo"};
int main() {
// intialize the data set
vector<string> myVect( data, data + NUM_ELEM(data));
cout << "dump of initial data set" << endl << endl;
for_each( myVect.begin(), myVect.end(), dump());
map<string,size_t> uniqueStrings; // stores collection of all unique strings
for (vector<string>::iterator i = myVect.begin(); i != myVect.end(); ++i) {
// I'm using uniqueStrings.size() as a convenience here...
// I just needed something to generate unique ID's easily,
// it might not be appropriate to use size() for your ID's in real life
// this will insert the new mapping if there's not already one
uniqueStrings.insert( make_pair(*i, uniqueStrings.size()));
}
cout << endl << endl<< "dump of uniqueStrings" << endl << endl;
for_each( uniqueStrings.begin(), uniqueStrings.end(), dump());
// I'm not sure if you'd need this `out` vector anymore - you can probably just
// use the `uniqueStrings` map directly for this information (but that would
// depend on your specific needs)
vector<int> out;
for (vector<string>::iterator i = myVect.begin(); i != myVect.end(); ++i) {
out.push_back( uniqueStrings[*i]);
}
cout << endl << endl << "dump of `out` vector" << endl << endl;
for_each( out.begin(), out.end(), dump());
return 0;
}
Related
So, I'm beginning C++, with a semi-adequate background of python. In python, you make a list/array like this:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Then, to print the list, with the square brackets included, all you do is:
print x
That would display this:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
How would I do the exact same thing in c++, print the brackets and the elements, in an elegant/clean fashion? NOTE I don't want just the elements of the array, I want the whole array, like this:
{1, 2, 3, 4, 5, 6, 7, 8, 9}
When I use this code to try to print the array, this happens:
input:
#include <iostream>
using namespace std;
int main()
{
int anArray[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
cout << anArray << endl;
}
The output is where in memory the array is stored in (I think this is so, correct me if I'm wrong):
0x28fedc
As a sidenote, I don't know how to create an array with many different data types, such as integers, strings, and so on, so if someone can enlighten me, that'd be great!
Thanks for answering my painstakingly obvious/noobish questions!
You can write a simple helper function to allow you to stream the array to an output stream (including but not limited to std::cout):
#include <iostream>
// print an array to an output stream
// prints to std::cout by default
template <typename T, std::size_t N>
void print_array(const T(&a)[N], std::ostream& o = std::cout)
{
o << "{";
for (std::size_t i = 0; i < N-1; ++i)
{
o << a[i] << ", ";
}
o << a[N-1] << "}\n";
}
where a function template is used in order to deduce both the type and size of the array at compile time. You can use it like this:
#include <fstream>
int main()
{
int a[] = {1,2,3,4,5};
print_array(a); // prints {1, 2, 3, 4, 5} to stdout
std::string sa[] = {"hello", "world"};
print_array(sa, std::cerr); // prints {hello, world} to stderr
std::ofstream output("array.txt");
print_array(a, output); // prints {1, 2, 3, 4, 5} to file array.txt
}
This solution can be trivially generalized to deal with ranges and standard library containers. For even more general approaches, see here.
As for the side note, you cannot do that in C++. An array can only hold objects of one type.
Inspired by the answers of juanchopanza and Raxman I decided to do a real IO manipulator, which leads to a syntax like:
const char* arr[] = { "hello", "bye" };
std::cout
<< "Woot, I can has " << print(arr)
<< " and even " << print(std::vector<int> { 1,2,3,42 }, ":") << "!\n";
printing
Woot, I can has { hello, bye } and even { 1:2:3:42 }!
Note
it works seamlessly with chained output streaming using operator<< as usual
it is fully generic (supporting any container of streamable types)
it even allows to pass a delimiter (as an example)
with a little more template arguments it could be made so generic as to work with ostream, wostream etc.
fun: Since the delimiter can be any streamable 'thing' as well, you could even... use an array as the delimiter:
std::cout << "or bizarrely: " << print(arr, print(arr)) << "\n";
resulting in the rather weird sample output:
or bizarrely: { hello{ hello, bye }bye }
Still demonstrates the power of hooking seamlessly into IO streams, if you ask me.
I believe it will not get much more seamless than this, in C++. Of course there is some implementing to do, but as you can see you can leverage full genericity, so you're at once done for any container of streamable types:
#include <iostream>
#include <vector>
namespace manips
{
template <typename Cont, typename Delim=const char*>
struct PrintManip {
PrintManip(Cont const& v, Delim d = ", ") : _v(v), _d(std::move(d)) { }
Cont const& _v;
Delim _d;
friend std::ostream& operator<<(std::ostream& os, PrintManip const& manip) {
using namespace std;
auto f = begin(manip._v), l(end(manip._v));
os << "{ ";
while (f != l)
if ((os << *f) && (++f != l))
os << manip._d;
return os << " }";
}
};
template <typename T, typename Delim=const char*>
manips::PrintManip<T, Delim> print(T const& deduce, Delim delim = ", ") {
return { deduce, std::move(delim) };
}
}
using manips::print;
int main()
{
const char* arr[] = { "hello", "bye" };
std::cout
<< "Woot, I can has " << print(arr)
<< " and even: " << print(std::vector<int> { 1,2,3,42 }, ':') << "!\n"
<< "or bizarrely: " << print(arr, print(arr)) << "\n";
}
See it live at http://ideone.com/E4G9Fp
for(int i=0;i<9;i++)
cout << anArray[i] << endl;
ahh ok with brackets it be such (simply array print logic for your arrays , u can make it more general in future)
cout<<'{';
for(int i=0;i<8;i++)
cout << anArray[i] <<',';
cout<<anArray[8]<<'}';
For python users and c++ lovers there is std::vector .
here how it be print logic for vector
//solution with [] operator
if(anVector.size()>=1){
std::cout<<"{";
for(int i=0;i<anVector.size()-1;i++){
std::cout<<anVector[i]<<',' ;
}
std::cout<<anVector[anVector.size()-1]<<'}' ;
}
//solution with iterator
std::vector<int>::iterator it =anVector.begin();
if(it!=anVector.end()){
std::cout << '{'<<*it;
++it;
for (; it != anVector.end(); ++it){
std::cout<<','<< *it ;
}
std::cout << '}';
}
Also check C++ 11 std::vector . In new standart initializing and other things more elegant
Probably the easiest way to get an array printed nicely (assuming it has a length greater than zero) is with something like:
std::cout << "{" << anArray[0];
for (int i = 1; i < sizeof (anArray) / sizeof (*anArray); i++)
std::cout << ", " << array[i];
std::cout << "}";
If you wish to be able to print less than the full array, you'll need a way to specify the length (which may be zero so you should handle that case:
if (length == 0)
std::cout << "{}";
else {
std::cout << "{" << anArray[0];
for (int i = 1; i < length; i++)
std::cout << ", " << array[i];
std::cout << "}";
}
There may be other variations of that such as printing at a given starting point rather than element zero but I won't go into that here. Suffice to say, it's just a small modification to the loop and if condition.
Of course, if you want to do it the simple way, with std::cout << myvariable;, you can consider wrapping the whole thing in a class and providing your own operator<< for it - that would be a more object-oriented way of doing things.
If you don't care too much about having the comma as a separator, you could also use output iterators.
#include <iostream>
#include <iterator>
#include <algorithm>
...
int anArray[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
std::cout << "{ ";
std::copy(anArray, anArray + 9, std::ostream_iterator<int>(std::cout, " "));
std::cout << "}" << std::endl;
Another idea to achieve this, is to define a macro to convert c-arrays to std::vector and a template function to output a std::vector, like this:
#include <vector>
#include <iostream>
// convert an array (e.g. int32_t x[20]) into an std::vector
#define ARRAY_TO_STD_VECTOR(VAR, TYPE) std::vector<TYPE>(VAR, VAR + sizeof(VAR)/sizeof(TYPE))
// output of std::vector<T>
namespace std {
template<typename T>
std::ostream& operator<<(std::ostream& p, const std::vector<T>& v)
{
p << "{";
for (size_t i = 0; i < v.size(); ++i)
{
p << v[i];
if (i < (v.size() - 1)) p << ", ";
}
p << "}";
return p;
}
}
Having this, you can output your array like this:
int main()
{
int anArray[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
cout << ARRAY_TO_STD_VECTOR(anArray, int) << endl;
}
I have a vector of custom classes (std::string just for example).
The vector is large and I iterate through often, so I rely on cache locality.
I also have one raw pointer which points at one of the vector elements.
Now is the trick:
The vector is sorted from time to time, so the raw pointer loose the actual pointed element value, and will point to some random element value.
Here is an example to illustrate the same:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <memory>
using namespace std;
int main()
{
vector<string> v = {"9","3", "8", "7", "6", "5", "1", "4", "2"};
string* rs = &v[7]; //point to the 7th element
for (size_t i = 0; i < v.size(); ++i)
cerr << v[i];
cerr << endl;
cerr << "Referenced string: " << rs->c_str() << endl;
cerr << "Sort ..." << endl;
sort(v.begin(), v.end(), [](const string& a, const string& b)
{
if (a < b)
return true;
else
return false;
}
);
for (size_t i = 0; i < v.size(); ++i)
cerr << v[i];
cerr << endl;
cerr << "Referenced string: " << rs->c_str() << endl;
cin.get();
return 0;
}
Output:
938765142
Referenced string before sort : 4
Sort ...
123456789
Referenced string after sort : 8
Since I wish the rs pointer to keep pointing to the 7th element value (which is 4) even after the sort, I came up with the following solution (vector of pointers):
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <memory>
using namespace std;
int main()
{
vector<unique_ptr<string>> v;
v.resize(9);
v[0] = make_unique<string>("9");
v[1] = make_unique<string>("3");
v[2] = make_unique<string>("8");
v[3] = make_unique<string>("7");
v[4] = make_unique<string>("6");
v[5] = make_unique<string>("5");
v[6] = make_unique<string>("1");
v[7] = make_unique<string>("4");
v[8] = make_unique<string>("2");
string* rs = v[7].get();
for (size_t i = 0; i < v.size(); ++i)
cerr << v[i]->c_str();
cerr << endl;
cerr << "Referenced string before sort: " << rs->c_str() << endl;
cerr << "Sort ..." << endl;
sort(v.begin(), v.end(), [](const unique_ptr<string>& a, const unique_ptr<string>& b)
{
if (*a < *b)
return true;
else
return false;
}
);
for (size_t i = 0; i < v.size(); ++i)
cerr << v[i]->c_str();
cerr << endl;
cerr << "Referenced string after sort: " << rs->c_str() << endl;
cin.get();
return 0;
}
Output:
938765142
Referenced string before sort: 4
Sort ...
123456789
Referenced string after sort: 4
While this latter solution works, there is a price: I have lost the cache locality of my vector, since I store pointers in it, rather than the actual objects.
Is there a way to maintain cache locality (e.g.: store my actual objects in the vector), and somehow manage to rs pointer to keep track where its pointed value wander around due to the sorts?
Or from the other perspective, is there a way to achieve cache locality with the vector of pointers?
Solution from Pubby, thanks!:
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <memory>
using namespace std;
int main()
{
vector<string> data = { "d","e", "f", "g", "i", "b", "c", "a", "h" };
vector<int> indexes = {0,1,2,3,4,5,6,7,8};
int si = 6;
for (size_t i = 0; i < indexes.size(); ++i)
cerr << indexes[i];
cerr << endl;
for (size_t i = 0; i < indexes.size(); ++i)
cerr << data[indexes[i]];
cerr << endl;
cerr << "Referenced string before sort: " << data[si] << endl;
cerr << "Sort ..." << endl;
sort(indexes.begin(), indexes.end(), [&](const int a, const int b)
{
return data[a] < data[b];
}
);
for (size_t i = 0; i < indexes.size(); ++i)
cerr << indexes[i];
cerr << endl;
for (size_t i = 0; i < indexes.size(); ++i)
cerr << data[indexes[i]];
cerr << endl;
cerr << "Referenced string after sort: " << data[si] << endl;
cin.get();
return 0;
}
You can increase locality by storing the strings in a vector which doesn't change, and then store a vector of pointers/indexes to these strings.
Like this:
vector<string> data = {"9","3", "8", "7", "6", "5", "1", "4", "2"};
vector<unsigned> indexes(data.size());
std::iota(indexes.begin(), indexes.end(), 0u);
To sort your data you'd sort indexes using a custom comparator function which retrieves the values from data and compares them. Remember: indexes can change, but data should not!
sort(indexes.begin(), indexes.end(), [&](unsigned a, unsigned b)
{
return data[a] < data[b];
});
Just an idea: Instead of storing std::string in the vector, just append the character arrays of each string to a std::vector<char>.
This packs the strings closely together in memory, improving locality even better than std::string with small string optimization. It will also give better results if the strings exceed the max. size for small string optimization.
For sorting, store index and size of each string in a 2nd vector similar to Pubbys suggestion.
Of course this only works if the string length doesn't need to change dynamically. Otherwise you would have to rebuild the vector<char>.
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <string_view>
using namespace std;
using IndexAndSize = pair<size_t,size_t>;
void push_and_index( vector<char>& v, vector<IndexAndSize>& vi, string_view s )
{
vi.emplace_back( v.size(), s.size() );
v.insert( end(v), begin(s), end(s) );
}
string_view make_string_view( vector<char> const& v, IndexAndSize is )
{
return { v.data() + is.first, is.second };
}
int main()
{
vector<char> v;
vector<IndexAndSize> vi;
push_and_index( v, vi, "foo" );
push_and_index( v, vi, "bar" );
push_and_index( v, vi, "foobar" );
push_and_index( v, vi, "barfoo" );
sort( begin(vi), end(vi), [&]( IndexAndSize a, IndexAndSize b )
{
return make_string_view( v, a ) < make_string_view( v, b );
});
for( IndexAndSize is : vi )
{
cout << make_string_view( v, is ) << endl;
}
}
Live demo on Coliru.
Note: C++17's string_view is used only to help with the sorting and output, it's not crucial for this idea.
I have a string like "aabcdba" now I want to store the position of different character's position. I am trying to store using vector and unordered_map. Is there any good approach to store the position of different characters?
void topKFrequent(string s) {
vector<vector<int> >v(123);
//unordered_map<char, vector<int>>m;
for(int i=0;i<s.size();i++) {
v[s[i]].push_back(i);
// m[s[i]].push_back(i);
}
for(int i=0;i<123;i++) {
for(int j=0;j<v[i].size();j++) {
char ch=i;
cout<<ch<<"->"<<v[i][j]<<endl;
}
}
}
if string = "aabcdba", I want the following result:
a->0,1,6;
b->2,5;
c->3;
d->4;
You could use a map<char, vector<unsigned int> >.
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
map<char, vector<unsigned int> > storePos(string s)
{
map<char, vector<unsigned int> > charPos;
for(int i=0;i<s.size();i++)
{
auto itr = charPos.find(s[i]);
if(itr != charPos.end())
{
itr->second.push_back(i);
}
else
{
charPos[s[i]] = vector<unsigned int>(1, i);
}
}
return charPos;
}
int main(void)
{
string example = "aabcdba";
auto result = storePos(example);
for(auto itr1 = result.begin(); itr1 != result.end(); itr1 ++)
{
cout << "Letter: " << itr1->first << ", Locations: ";
for(auto itr2 = itr1->second.begin(); itr2 != itr1->second.end();
itr2 ++)
{
cout << *itr2 << " ";
}
cout << endl;
}
}
If you really want to store ordinal positions in the original string sequence, you can do so with either an unordered or ordered map of char to vector, where char is the key, and the vector contains the positions. Using an unordered map will not give you the lexicographical ordering of keys you seem to be seeking, but will nonetheless give you accurate positional vectors.
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
int main()
{
std::string s = "aabcdba";
std::unordered_map<char, std::vector<unsigned int>> mymap;
for (unsigned i=0; i<s.size(); ++i)
mymap[s[i]].push_back(i);
for (auto const& pr : mymap)
{
std::cout << pr.first << "->";
auto it = pr.second.cbegin();
std::cout << *it;
while (++it != pr.second.cend())
std::cout << ',' << *it;
std::cout << ";\n";
}
}
Output
d->4;
c->3;
b->2,5;
a->0,1,6;
If you want lexicographical ordering, the simplest alternative is to simply using a regular ordered map instead. Changing only this:
std::unordered_map<char, std::vector<unsigned int>> mymap;
to this:
std::map<char, std::vector<unsigned int>> mymap;
and including the appropriate header delivers us this for output:
a->0,1,6;
b->2,5;
c->3;
d->4;
which fits exactly what you seem to be looking for.
A possible implementation to store the positions could be using unordered_multimap: (where the key characters can be repeated).
void storePos(string s) {
unordered_multimap<char, int>m;
for(int i=0;i<s.size();i++) {
m.insert(make_pair(s[i],i));
}
}
[EDITED]
But the output may depend on how you use it, or print out the data.
For example, consider the use of a std::multimap instead of std::unordered_map, to populate it you just do:
multimap<char, int>m;
void storePos(string s) {
for(int i=0;i<s.size();i++) {
m.insert(make_pair(s[i],i));
}
}
And to print the data you could have the following method:
void printPos()
{
std::multimap<char,int>::iterator it,itup;
for (it = m.begin(); it != m.end(); )
{
cout << (*it).first << " -> ";
itup = m.upper_bound ((*it).first );
// print range [it,itup):
for (it; it!=itup; ++it)
{
cout << (*it).second << ", ";
}
cout << endl;
}
}
Output:
a -> 0, 1, 6,
b -> 2, 5,
c -> 3,
d -> 4,
Try this!
I'd like to know how to get a specific value from a map
that holds two vectors, using row and column strings.
For example, if the user enters "R1" and "C1" the string "1" is printed.
In this code, I am using array subscript to access vector.
It would be helpful if you could explain how to access it using iterator.
Sorry if this is repeated question.
Thanks.
#include <string>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
typedef pair<string, string> Pair;
typedef map<Pair, string> Map;
typedef vector<string> strVec;
int main()
{
const int COL_SIZE = 3;
const int ROW_SIZE = 3;
string row_array[ROW_SIZE] = {"R1","R2","R3" };
string col_array[COL_SIZE] = { "C1", "C2", "C3" };
strVec column;
strVec row;
for (size_t i = 0; i < COL_SIZE; ++i)
{
row.push_back(col_array[i]);
column.push_back(row_array[i]);
}
Map MyMap;
Map::iterator iterator;
string numbers[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
int numberIndex = 0;
for (int i = 0; i < ROW_SIZE; ++i)
{
for (int j = 0; j < COL_SIZE; ++j)
{
MyMap[make_pair(row[i], column[j])] = numbers[numberIndex];
cout << MyMap[make_pair(row[i], column[j])];
++numberIndex;
}
cout << endl;
}
string userInputRow;
cout << "Enter a row: " << endl;
cin >> userInputRow;
string userInputCol;
cout << "Enter a column: " << endl;
cin >> userInputCol;
}
You map is not holding two vectors, it is mapping from a pair of string to another string.
I wonder what is your use case for using such structure instead of vectors?
You already have the access to an element of the map in your code:
cout << MyMap[make_pair(row[i], column[j])];
Note that the [] operator will insert in the map if the entry does not exist, it is not always intended.
You can iterate on a map the same way as every container, and it is sorted on its key:
for(const auto &p : MyMap) {
std::cout << p.second << std::endl;
}
Map::const_iterator item_pos = MyMap.find(make_pair(userInputRow, userInputCol));
if(item_pos != MyMap.end())
cout << item_pos->second << endl;
Edit:
Please, fix this 2 lines:
row.push_back(row_array[i]);
column.push_back(col_array[i]);
So, I'm beginning C++, with a semi-adequate background of python. In python, you make a list/array like this:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Then, to print the list, with the square brackets included, all you do is:
print x
That would display this:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
How would I do the exact same thing in c++, print the brackets and the elements, in an elegant/clean fashion? NOTE I don't want just the elements of the array, I want the whole array, like this:
{1, 2, 3, 4, 5, 6, 7, 8, 9}
When I use this code to try to print the array, this happens:
input:
#include <iostream>
using namespace std;
int main()
{
int anArray[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
cout << anArray << endl;
}
The output is where in memory the array is stored in (I think this is so, correct me if I'm wrong):
0x28fedc
As a sidenote, I don't know how to create an array with many different data types, such as integers, strings, and so on, so if someone can enlighten me, that'd be great!
Thanks for answering my painstakingly obvious/noobish questions!
You can write a simple helper function to allow you to stream the array to an output stream (including but not limited to std::cout):
#include <iostream>
// print an array to an output stream
// prints to std::cout by default
template <typename T, std::size_t N>
void print_array(const T(&a)[N], std::ostream& o = std::cout)
{
o << "{";
for (std::size_t i = 0; i < N-1; ++i)
{
o << a[i] << ", ";
}
o << a[N-1] << "}\n";
}
where a function template is used in order to deduce both the type and size of the array at compile time. You can use it like this:
#include <fstream>
int main()
{
int a[] = {1,2,3,4,5};
print_array(a); // prints {1, 2, 3, 4, 5} to stdout
std::string sa[] = {"hello", "world"};
print_array(sa, std::cerr); // prints {hello, world} to stderr
std::ofstream output("array.txt");
print_array(a, output); // prints {1, 2, 3, 4, 5} to file array.txt
}
This solution can be trivially generalized to deal with ranges and standard library containers. For even more general approaches, see here.
As for the side note, you cannot do that in C++. An array can only hold objects of one type.
Inspired by the answers of juanchopanza and Raxman I decided to do a real IO manipulator, which leads to a syntax like:
const char* arr[] = { "hello", "bye" };
std::cout
<< "Woot, I can has " << print(arr)
<< " and even " << print(std::vector<int> { 1,2,3,42 }, ":") << "!\n";
printing
Woot, I can has { hello, bye } and even { 1:2:3:42 }!
Note
it works seamlessly with chained output streaming using operator<< as usual
it is fully generic (supporting any container of streamable types)
it even allows to pass a delimiter (as an example)
with a little more template arguments it could be made so generic as to work with ostream, wostream etc.
fun: Since the delimiter can be any streamable 'thing' as well, you could even... use an array as the delimiter:
std::cout << "or bizarrely: " << print(arr, print(arr)) << "\n";
resulting in the rather weird sample output:
or bizarrely: { hello{ hello, bye }bye }
Still demonstrates the power of hooking seamlessly into IO streams, if you ask me.
I believe it will not get much more seamless than this, in C++. Of course there is some implementing to do, but as you can see you can leverage full genericity, so you're at once done for any container of streamable types:
#include <iostream>
#include <vector>
namespace manips
{
template <typename Cont, typename Delim=const char*>
struct PrintManip {
PrintManip(Cont const& v, Delim d = ", ") : _v(v), _d(std::move(d)) { }
Cont const& _v;
Delim _d;
friend std::ostream& operator<<(std::ostream& os, PrintManip const& manip) {
using namespace std;
auto f = begin(manip._v), l(end(manip._v));
os << "{ ";
while (f != l)
if ((os << *f) && (++f != l))
os << manip._d;
return os << " }";
}
};
template <typename T, typename Delim=const char*>
manips::PrintManip<T, Delim> print(T const& deduce, Delim delim = ", ") {
return { deduce, std::move(delim) };
}
}
using manips::print;
int main()
{
const char* arr[] = { "hello", "bye" };
std::cout
<< "Woot, I can has " << print(arr)
<< " and even: " << print(std::vector<int> { 1,2,3,42 }, ':') << "!\n"
<< "or bizarrely: " << print(arr, print(arr)) << "\n";
}
See it live at http://ideone.com/E4G9Fp
for(int i=0;i<9;i++)
cout << anArray[i] << endl;
ahh ok with brackets it be such (simply array print logic for your arrays , u can make it more general in future)
cout<<'{';
for(int i=0;i<8;i++)
cout << anArray[i] <<',';
cout<<anArray[8]<<'}';
For python users and c++ lovers there is std::vector .
here how it be print logic for vector
//solution with [] operator
if(anVector.size()>=1){
std::cout<<"{";
for(int i=0;i<anVector.size()-1;i++){
std::cout<<anVector[i]<<',' ;
}
std::cout<<anVector[anVector.size()-1]<<'}' ;
}
//solution with iterator
std::vector<int>::iterator it =anVector.begin();
if(it!=anVector.end()){
std::cout << '{'<<*it;
++it;
for (; it != anVector.end(); ++it){
std::cout<<','<< *it ;
}
std::cout << '}';
}
Also check C++ 11 std::vector . In new standart initializing and other things more elegant
Probably the easiest way to get an array printed nicely (assuming it has a length greater than zero) is with something like:
std::cout << "{" << anArray[0];
for (int i = 1; i < sizeof (anArray) / sizeof (*anArray); i++)
std::cout << ", " << array[i];
std::cout << "}";
If you wish to be able to print less than the full array, you'll need a way to specify the length (which may be zero so you should handle that case:
if (length == 0)
std::cout << "{}";
else {
std::cout << "{" << anArray[0];
for (int i = 1; i < length; i++)
std::cout << ", " << array[i];
std::cout << "}";
}
There may be other variations of that such as printing at a given starting point rather than element zero but I won't go into that here. Suffice to say, it's just a small modification to the loop and if condition.
Of course, if you want to do it the simple way, with std::cout << myvariable;, you can consider wrapping the whole thing in a class and providing your own operator<< for it - that would be a more object-oriented way of doing things.
If you don't care too much about having the comma as a separator, you could also use output iterators.
#include <iostream>
#include <iterator>
#include <algorithm>
...
int anArray[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
std::cout << "{ ";
std::copy(anArray, anArray + 9, std::ostream_iterator<int>(std::cout, " "));
std::cout << "}" << std::endl;
Another idea to achieve this, is to define a macro to convert c-arrays to std::vector and a template function to output a std::vector, like this:
#include <vector>
#include <iostream>
// convert an array (e.g. int32_t x[20]) into an std::vector
#define ARRAY_TO_STD_VECTOR(VAR, TYPE) std::vector<TYPE>(VAR, VAR + sizeof(VAR)/sizeof(TYPE))
// output of std::vector<T>
namespace std {
template<typename T>
std::ostream& operator<<(std::ostream& p, const std::vector<T>& v)
{
p << "{";
for (size_t i = 0; i < v.size(); ++i)
{
p << v[i];
if (i < (v.size() - 1)) p << ", ";
}
p << "}";
return p;
}
}
Having this, you can output your array like this:
int main()
{
int anArray[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
cout << ARRAY_TO_STD_VECTOR(anArray, int) << endl;
}