Related
I have the program that has two vectors of names and ages. It sorts the names vector and keeps the age vector in the correct order to match the sorted name vector. Now, I want to make a function from existing code, but I have some issues.
Existing code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>
using namespace std;
int main() {
vector<string> names {"One", "Two", "Three", "Four", "Five"};
vector<unsigned int> ages { 1, 2, 3, 4, 5};
const vector<string> namesCopy = names;
sort(begin(names), end(names));
decltype(ages) sortedAges(ages.size());
for(int i = 0; i < namesCopy.size(); ++i) {
const auto iter = lower_bound(begin(names), end(names), namesCopy[i]);
const auto pos = iter - begin(names);
sortedAges[pos] = ages[i];
}
for(int i = 0 ; i < names.size() ; ++i)
cout << setw(10) << names[i] << setw(4) << sortedAges[i] << '\n' ;
}
Output
Function:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>
using namespace std;
int test(vector<string> testNames, vector<string> testNamesCopy, vector<unsigned int> testAges, vector<unsigned int> testSortedAges) {
for(int i = 0; i < testNamesCopy.size(); ++i) {
const auto iter = lower_bound(begin(testNames), end(testNames), testNamesCopy[i]);
const auto pos = iter - begin(testNames);
return testSortedAges[pos] = testAges[i];
}
}
int main() {
vector<string> names {"One", "Two", "Three", "Four", "Five"};
vector<unsigned int> ages { 1, 2, 3, 4, 5};
const auto namesCopy = names;
sort(begin(names), end(names));
decltype(ages) sortedAges(ages.size());
for(int i = 0 ; i < names.size() ; ++i)
cout << setw(10) << names[i] << setw(4) << test(names, namesCopy, ages, sortedAges) << '\n' ;
}
Output 2
I think you are approaching this the wrong way. Having 2 vector that you sort but have to keep in the same order is error prone. Instead you should use a vector of pair.
std::vector<std::pair<std::string, int>> idendityVec;
Then you can sort by the name (the first element of the pair) by doing
std::sort(idendityVec.begin(), idendityVec.end());
If you want to sort by age, you can declare your own comparaison function and use it in the sort :
bool lesserAge(const pair<std::string,int> &a,
const pair<std::string,int> &b)
{
return (a.second < b.second);
}
std::sort(idendityVec.begin(), idendityVec.end(), lesserAge);
Which gives you something like this :
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
bool lesserAge(const std::pair<std::string, int> &a,
const std::pair<std::string, int> &b)
{
return (a.second < b.second);
}
int main()
{
std::vector<std::pair<std::string, int>> idendityVec = {std::make_pair("three", 3), std::make_pair("four", 4), std::make_pair("two", 2), std::make_pair("one", 1)};
for (auto v : idendityVec)
{
std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
}
// Sort by age i.e. second element
std::sort(idendityVec.begin(), idendityVec.end(), lesserAge);
for (auto v : idendityVec)
{
std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
}
//Sort by name i.e first element
std::sort(idendityVec.begin(), idendityVec.end());
for (auto v : idendityVec)
{
std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
}
}
vector<string> names {"One", "Two", "Three", "Four", "Five"};
vector<unsigned int> ages { 1, 2, 3, 4, 5};
names and ages seem connected in such a way that it'd be best to group them together in a class. We can use a simple struct which, by default, gives you direct access to its members, just like you have access to all the names and ages in your current solution. You can start with this:
struct person { // ... or animal, or thing. Give it a meaningful name.
std::string name{};
unsigned age{};
};
Now you can create a std::vector<person> instead of having two unconnected vectors, which makes sorting and general handling of the data a bit of a hassle.
With the above, sorting and printing etc. becomes more straight forward. I've used lambdas to create the sorting functions in the example:
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <tuple> // std::tie
#include <iomanip>
struct person {
std::string name{};
unsigned age{};
};
// print one "person"
std::ostream& operator<<(std::ostream& os, const person& p) {
return os << std::setw(10) << p.name << std::setw(4) << p.age;
}
int main() {
// one vector with all the persons
std::vector<person> persons{
{"One", 1},
{"Two", 2},
{"Three", 3},
{"Four", 4},
{"Five", 5}
};
// sort on name first, age second (if names are equal) - ascending order
std::sort(persons.begin(), persons.end(), [](const person& a, const person& b) {
return std::tie(a.name, a.age) < std::tie(b.name, b.age);
});
// print the current order:
for(const auto& p : persons) std::cout << p << "\n";
std::cout << "--\n";
// sort on age first, name second (if ages are equal) - ascending order
std::sort(persons.begin(), persons.end(), [](const person& a, const person& b) {
return std::tie(a.age, a.name) < std::tie(b.age, b.name);
});
// print the current order:
for(const auto& p : persons) std::cout << p << "\n";
}
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'm not sure if it's possible since I didn't really find anything, but I have a linear array called "Grades" and I'm trying to output it all in one line.
int Grades[5] = { 3, 2, 5, 2 };
cout << "Grades:" << Grades << "\n";
I know the above doesn't work, but I want something like:
Grades: 3, 2, 5, 2
(minus the formatting/commas of course)
I know you can loop through it, but it just ends up printing it on a new line which I don't want.
You can cout a container on a single line by using std::ostream_iterator and std::copy. Something like this will do the task you need:
#include <iostream> // std::cout
#include <iterator> // std::ostream_iterator
#include <vector> // std::vector
#include <algorithm> // std::copy
int main () {
int Grades[5] = { 3, 2, 5, 2 };
std::copy ( Grades, Grades + 4, std::ostream_iterator<int>(std::cout, ", ") );
return 0;
}
This is the example from std::ostream_iterator's documentation adapted a bit to fit the particular example. Also see the result on ideone.
(Contributed by Rerito) If you are using c++11 or later you can also make use of std::begin and std::end from <iterator> to make the code cleaner:
#include <iostream> // std::cout
#include <iterator> // std::ostream_iterator
#include <vector> // std::vector
#include <algorithm> // std::copy
#include <iterator>
int main () {
int Grades[5] = { 3, 2, 5, 2 };
std::copy (std::begin(Grades), std::end(Grades), std::ostream_iterator<int>(std::cout, ", ") );
return 0;
}
And the result on ideone.
int Grades[5] = { 3, 2, 5, 2 };
cout << "Grades: ";
for (int i = 0; i < sizeof(Grades)/sizeof(int); i++) {
cout << Grades[i] << ", "; //minus the commas, remove (<< ", ") or to space out the grades, just remove the comma
}
Or
Based on juanchopanza's suggestion, you can do it this way;
int Grades[] = { 3, 2, 5, 2 };
cout << "Grades: ";
for (auto g : Grades) {
cout << g << ", "; //minus the commas, remove (<< ", ") or to space out the grades, just remove the comma
}
If you have latest compiler supporting C++11/C++14 then You can use range-based for loop,
#include <iostream>
using namespace std;
int main()
{
int Grades[5] = { 3, 2, 5, 2, 1 };
bool bFirst = true;
for (int & i : Grades)
{
std::cout << (bFirst ? "Grades: " : ", ") << i;
bFirst = false;
}
return 0;
}
It shows output like,
Grades: 3, 2, 5, 2, 1
You can define an overload for operator<< that takes a pointer to array:
#include <iostream>
template <typename T, int i>
std::ostream& operator<<(std::ostream& os, T (*arr)[i] )
{
for (auto e: *arr)
os << e << ",";
os << std::endl;
return os;
}
int main()
{
int Grades[5] = {2,34,4,5,6};
std::cout<<& Grades;
}
I want to remove last 5 elements from a std::map.
One way is:
for(int i=0; i < 5; i++)
{
map<string, LocationStruct>::iterator it = myLocations.end();
it--;
myLocations.erase(it);
}
Is there a good way to do that without looping?
Thanks,
a compilable demo of one way to do it. Note that because map iterators are not random access iterators, there's likely to be a loop involved under the covers during the call to std::prev() anyway.
#include <iostream>
#include <map>
#include <string>
using namespace std::string_literals;
std::map<int, std::string> m = {
{ 0, "zero"s },
{ 1, "one"s },
{ 2, "two"s },
{ 3, "three"s },
{ 4, "four"s },
{ 5, "five"s }
};
auto main() -> int
{
for (const auto& entry : m) {
std::cout << entry.first << ", " << entry.second << std::endl;
}
// erase operation here
m.erase(std::prev(m.end(), 5), m.end());
std::cout << "\nafter erase \n\n";
for (const auto& entry : m) {
std::cout << entry.first << ", " << entry.second << std::endl;
}
return 0;
}
expected output:
0, zero
1, one
2, two
3, three
4, four
5, five
after erase
0, zero
You can use the std::prev function to do navigation for you:
m.erase(prev(m.end(), 5), m.end());
Use range erase
auto i = m.begin();
std::advance(i, (m.size() - 5) );
m.erase( i, m.end() );
As far as I know, std::map has normal access iterator, so you have to traverse to last element every time to erase it from memory.
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;
}