how to print out contents of char** vector - c++

SO,
I am looking to print out the contents of a vector; I have tried an iterator for it but that is no good
for(vector<char**>::const_iterator i=myVec.begin();i!=myVec.end();i++) {
cout<<**i<<endl;
}
this does not work, what I am thinking is I will need two iterators (the above one will be the outer one, and the inner one would be as such:
for(vector<char*>::const_iterator j=???;j!=??;j++) {....}
but I haven't been able to get it to work.
Thanks.

Seems to work just fine here:
#include <iostream>
#include <vector>
int main()
{
const char* sentence1[] = {"foo", "bar", "baz"};
const char* sentence2[] = {"xyzzy", "frob", "plugh"};
std::vector<const char**> vec = {sentence1, sentence2};
for (auto i : vec) {
for (size_t w = 0; w < 3; ++w) {
std::cout << i[w] << ' ';
}
}
std::cout << '\n';
}
This will print:
foo bar baz xyzzy frob plugh
The above is C++11. If you don't have that, you'll need to change the vector initialization and the for loop:
std::vector<const char**> vec;
vec.push_back(sentence1);
vec.push_back(sentence2);
for (std::vector<const char**>::iterator it = vec.begin();
it != vec.end(); ++it)
{
for (size_t w = 0; w < 3; ++w) {
std::cout << (*it)[w] << ' ';
}
}
As you can imagine, you'll need to assume the same amount of words for each sentence. If you don't want that, you can create a new data structure that also holds the amount of words per sentence together with the vector of sentences.
Being a masochist is a good exercise, but for practical purposes you should probably switch to vectors so that you can iterate over the words more easily.

Related

How to have access using pointers on two type definition vectors

I'm trying to learn how I can use the different typedef vector, and after creating them how I can access the variables. I have commented as I wrote the code
#include <iostream>
#include <vector>
//#include <stdlib.h>
using namespace std;
//Here I wanted to created a structure where I have position vector
struct Point {
double pos;
};
// now I have the type vector definitons named List
typedef std::vector<Point> List;
int main()
{
//I have initialized two list which are List A, and List B
List A;
List B;
//Point a, and Point b are two double data type variables that I want to push back into the two kind of list
Point a;
Point b;
for(int i =0; i<100; i ++){
a.pos = 2*i+1;
b.pos = 2*i -1;
A.push_back(a);
B.push_back(b);
}
return 0;
}
Now my question is how I can access the variables from the two List that I have created. I want to have access to the same index vector.
This is how I tried with dereferencing the pointer, but I think I'm making some mistakes:
for (List::iterator it = A->begin(); it != A->end(); it++) {
Point* val = &(*it);
cout << val->pos()<<endl;
//I need to access the value from B list too
}
Here is the code that would work (assuming A and B are the same length):
size_t jj = 0;
for (List::iterator it = A.begin(); it != A.end(); it++) {
cout << it->pos<<endl;
cout << (B.begin() + jj)->pos<< endl;
jj++;
}
Note that A and B are not pointers so you access their methods normally. By the way, if you have access to C++11 and above, you can use the following:
size_t ii = 0;
for (const auto& el: A) {
cout << el.pos << "," << B.at(ii).pos << endl;
ii++;
}
This has nothing to do with vectors, typedefs or anything else.
val->pos is a double, not a function.
So, remove the ():
Point* val = &(*it);
cout << val->pos << endl;
Or, a little more neatly:
const Point& val = *it;
std::cout << val.pos << '\n';

How to get indices of a Mat with specific value?

I want to find indices of an array that equal with specific value. so i've Written this code:
vector<int> _classes = { 2,2,1,1,3,3,3,3,5,5,4,4,5,6,6 };
vector<int> labelVec = {1,2,3,4,5,6};
vector<int> index;
for (int i = 0; i < labelVec.size(); i++)
{
compare(_classes, labelVec[i], index, CMP_EQ);
std::vector<int>::iterator nn = find(index.begin(), index.end(), 255);
}
but i have this error : Unhandled exception at 0x760B5608 in compareFuncTest.exe: Microsoft C++ exception: cv::Exception at memory location 0x004DDC44. if i define index as Mat, this problem will be resolved. but if i define index as Mat, i can't use from find(). also in this documentation states: output array (in my code as index) that has the same size and type as the input arrays. PLZ help me to fix this code.
I still do not get what is the point of this test, I guess this will be in some other algorithm... So, I give you two possible solutions.
1) Without OpenCV
First, you must know that
std::vector<int>::iterator nn = find(index.begin(), index.end(), 255);
Will only give you the first occurrance. Knowing this, here is a way you could check if the label is inside the _classes vector.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> _classes = { 2,2,1,1,3,3,3,3,5,5,4,4,5,6,6 };
std::vector<int> labelVec = {1,2,3,4,5,6,7};
for (const auto& label: labelVec)
{
std::vector<int>::iterator nn = find(_classes.begin(), _classes.end(), label);
if (nn != _classes.end())
{
std::cout << "I got the value from _classes: " << *nn << std::endl;
} else
{
std::cout << "I couldn't find the value with label:" << label << std::endl;
}
}
}
Here I iterate over all the labels (as you did) and then use the find directly in the classes, but with the label variable. Then I check if I found the label or not, if not, it will give you a value equal to _classes.end() which will give error if you try to use it (look at the extra label 7 which is not found).
This example can be tested here online.
2) With OpenCV
no oline test here. But this one is also easy to do. If you have a Mat in index you will only need to change the iterators to be templated. Like this:
auto nn = find(index.begin<int>(), index.end<int>(), 255);
If you a cv::Mat of classes you can also do it as in the method before and skip the comparison part (this would be faster)
Update
Since you want is the indices and all of them, then you have to iterate over it :/ if you wanted the values you could have used copy_if. You can create a lambda function to easily do the job.
like this:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
auto getIndices = [](const std::vector<int>& vec, const int value){
std::vector<int> result;
for (size_t t = 0; t < vec.size(); t++)
{
if (vec[t] == value)
{
result.push_back(static_cast<int>(t));
}
}
return result;
};
std::vector<int> _classes = { 2,2,1,1,3,3,3,3,5,5,4,4,5,6,6 };
std::vector<int> labelVec = {1,2,3,4,5,6,7};
for (const auto& label: labelVec)
{
std::vector<int> nn = getIndices(_classes, label);
std::cout << "I got the following indices for value"<< label<< ": [ ";
for (const auto& n : nn)
{
std::cout << n << ",";
}
std::cout << " ]" << std::endl;
}
}

How to extract certain values from list and put it in another list

I am having a really hard time doing this. I have a code block setup where it checks each and every value from one list to another. How i want it to work is when two values are similar it is supposed to either copy or duplicate that value into a completely separate list. So far all my efforts have failed. Can anyone please shed some light on this matter?
void compare_list_warning(list<string>*list_one,list<string>*list_two)
{
cout << "Made a function call!!!" << endl;
list<string> duplicates;
string line;
string *ptline = &line;
list<string>::iterator pt1 = list_one->begin();
cout << "About to compare the lists" << endl;
for (int x = 0; x < list_one->size(); ++x)
{
list<string>::iterator pt2 = list_two->begin();
for (int x = 0; x < list_two->size(); ++x)
{
if (*pt1 == *pt2)
{
*pt1 = *ptline;
duplicates.push_back(line);
}
else
{
++pt2;
}
}
++pt1;
}
How i want it to work is when two values are similar it is supposed
to either copy or duplicate that value into a completely separate
list.
You're complicating things a lot with unnecessary variables and pointers, when you can just translate rather straightforwardly into C++.
From your description, you want a function that takes two lists of strings and returns a list of the strings that exist in both input lists.
That is,
list<string> duplicates(list<string> list_one, list<string> list_two)
{
We're going to need a separate list to return from the function.
list<string> duplicates;
That's all the variables we're going to need.
Now, traverse both lists looking for duplicates.
The x you're using for iteration serves no real purpose, and also confuses.
Let's use the more idiomatic iterator loops.
For each item in list_one
for (list<string>::iterator p1 = list_one.begin(); p1 != list_one.end(); ++p1)
{
Go through each item in list_two
for (list<string>::iterator p2 = list_two.begin(); p2 != list_two.end(); ++p2)
{
And if the two items are the same, you add one of them to the duplicates list.
if (*pt1 == *pt2)
{
duplicates.push_back(*pt1);
}
}
}
And when you've looked through everything, return the result
return duplicates;
}
(You had a bug here where you overwrote the current item in list_one with the empty string instead of the other way around.
Also, you only advanced an iterator if you didn't find a match.)
This is a set intersection problem.
I tried to optimize the code as much as possible. This will run on O(N+M) where M,N are the sizes of your sets respectively.
This compiles on C++11
#include <iostream>
#include <string>
#include <unordered_set>
#include <list>
#include <algorithm>
using namespace std;
list<string> compare_list_warning(list<string> const& list_one, list<string> const& list_two)
{
list<string> const& small_list = list_one.size() < list_two.size() ? list_one : list_two;
list<string> const& big_list = list_one.size() < list_two.size() ? list_two : list_one;
list<string> duplicates;
unordered_set<string> duplicate_finder;
duplicate_finder.insert(begin(small_list), end(small_list));
copy_if(
begin(big_list), end(big_list)
, back_inserter(duplicates)
, [&](string const& v) {
return (duplicate_finder.find(v) != end(duplicate_finder));
}
);
return duplicates;
}
int main() {
list<string> common_names =
compare_list_warning(
{"one", "two", "three", "four"}
, {"three", "one", "five", "xx", "two"}
);
for(string const& common : common_names)
std::cout << common << "\t";
return 0;
}
there is your output from GCC 4.9 or Clang 3.4 :
three one two
Here I have generated two lists(as you can see, then compared their values).The program stores the common value in the "common_list" as you can see by printing these values. Now, you can manipulate these lines to get whatever you want!
#include <iostream>
#include <list>
#include <string>
using namespace std;
void compare_list_warning(list<string>list_one, list<string>list_two);
int main()
{
list <string> list1;
list <string> list2;
list1.push_back("hi");
list1.push_back("there");
list1.push_back("I am");
list1.push_back("abc");
list2.push_back("hello");
list2.push_back("something_random");
list2.push_back("there");
list2.push_back("greetings");
list2.push_back("cheers");
compare_list_warning(list1, list2); //here calling the function
system("pause");
return 0;
}
//defining the function here
void compare_list_warning(list<string>list_one, list<string>list_two)
{
list<string> ::iterator pt1 = list_one.begin();
list<string> ::iterator pt2 = list_two.begin();
list<string> common_list;
for (int i = 0; i < list_one.size(); ++i)
{
for (int j = 0; j < list_two.size(); ++j)
{
if (*pt1 == *pt2)
{
common_list.push_back(*pt1);
}
++pt2;
}
pt2 = list_two.begin(); //this is important; reset the iterator
++pt1;
}
list<string> ::iterator pt3 = common_list.begin();
cout << "Here is list of common values: " << endl;
for (int i = 0; i < common_list.size(); ++i)
{
cout << *pt3 << endl;
++pt3;
}
}
// bingo! it prints "there"
I guess, the important point here was to reset the iterator pt2! good luck!
molbdnilo answer is great and simple.
Here is one overkill way to do it (C++11 only). It should perform better on huge datasets. Code stays nicely small. You can also implement the logic of "similar" elements by providing a comparison function other than std::less.
#include <iostream>
#include <string>
#include <set>
#include <unordered_set>
#include <list>
#include <algorithm>
using namespace std;
template <typename T> using intersection_set = set<reference_wrapper<T const>, less<T>>;
list<string> compare_list_warning(list<string> const& list_one, list<string> const& list_two)
{
intersection_set<string> set_one, set_two;
set_one.insert(begin(list_one), end(list_one));
set_two.insert(begin(list_two), end(list_two));
list<string> output;
set_intersection(begin(set_one), end(set_one), begin(set_two), end(set_two), back_inserter(output), less<string>());
return output;
}
int main() {
list<string> common_names = compare_list_warning({"Roger", "Marcel", "Camille", "Hubert"}, {"Huguette", "Cunegond", "Marcelle", "Camille"});
for(string const& common : common_names) {
std::cout << "Common element: " << common << "\n";
}
std::cout << std::flush;
return 0;
}
EDIT
AK_ answer is interesting in terms of complexity, though I would have written it like this:
list<string> compare_list_warning(list<string> const& list_one, list<string> const& list_two)
{
list<string> const& small_list = list_one.size() < list_two.size() ? list_one : list_two;
list<string> const& big_list = list_one.size() < list_two.size() ? list_two : list_one;
list<string> duplicates;
unordered_set<string> duplicate_finder;
duplicate_finder.reserve(small_list.size());
duplicate_finder.insert(begin(small_list), end(small_list));
copy_if(begin(big_list), end(big_list), back_inserter(duplicates), [&](string const& v) { return (duplicate_finder.find(v) != end(duplicate_finder)); });
return duplicates;
}
EDIT 2
AK_'s algorithm is the fastest. After performances tests, it runs about 10 times faster than mine. You can find full code for performance test here. If you need to avoid the collision risk, a set can be used instead of the unordered_set, it is still a bit faster.

Display Vector elements in a reverse order

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;
}

Vector point to another vector

What I have here is two arrays of different types that I'm converting to vectors.
int ham_array[] = {32,71,12,45,26};
char word_array[] = {"cat", "bat", "green", "red", "taxi"};
vector < int > hamvector (ham_array, ham_array + 5);
vector < char > wordvector(word_array, word_array + 5);
I am going to call a sort function to sort the elements of ham_array from least to greatest. At the same time, I would like the word_array to also get sorted the same way ham_vector gets sorted using references.
For example,
after I call sort(hamvector)
ham_array[] = {12, 26, 32, 45, 71}
and sort(wordvector)
word_array[] = {"green", "taxi", "cat", "red", "bat"};
Is there an easy way to do this?
Well for one thing, that would be char *word_array[], the way you declared it would be a string.
Anyway the way to do this is you declare a structure to keep these things paired:
struct t {string name; int number;};
vector<t> list;
// fill in list
// comparer to compare two such structs
bool comparer(t &a, t &b) { return a.number>=b.number; }
// and to sort the list
sort(list.begin(), list.end(), comparer);
If by simple, you mean a more direct way then yes. The std::sort() does support sorting of raw arrays as well:
sort(word_array, word_array + 5, wordcmp);
As Blindy showed, you need a comparator function to tell sort how the ordering is suppose to be done for your list of words. Otherwise you'll end up sorting by the memory address that the string resides at instead of by the letters in your string. Something like this should work:
int wordcmp(const char *lhs, const char *rhs)
{
return strncmp(lhs, rhs, 256) < 0;
}
One other note, in practice you'll want to prefer std::vector over just raw pointer arrays since the latter isn't as safe.
I've tried to find a solution to a similar problem before and ultimately had to sort it manually. Another way I imagine you could do this would be to write a sorter functor that can somehow figure out, based on which string is being sorted, which integer is associated, and sort based on that. This is terribly inefficient, so I would highly advise doing your own manual sorting using std::swap.
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
template<typename KeyType, typename ValueType>
class CMappedSorter
{
std::map<KeyType, ValueType>* const m_Mappings;
public:
CMappedSorter(std::map<KeyType, ValueType>* Mappings) : m_Mappings(Mappings)
{
}
bool operator()(KeyType& LHS, KeyType& RHS)
{
const ValueType LHSSortingValue = m_Mappings->find(LHS)->second;
const ValueType RHSSortingValue = m_Mappings->find(RHS)->second;
return (LHSSortingValue < RHSSortingValue);
}
};
int main(int argc, char* argv[])
{
std::vector<int> Integers;
std::vector<std::string> Strings;
Integers.push_back(3);
Integers.push_back(1);
Integers.push_back(2);
Strings.push_back("Apple");
Strings.push_back("Banana");
Strings.push_back("Cherry");
std::map<std::string, int> Mappings;
if(Integers.size() == Strings.size())
{
const unsigned int ElementCount = Strings.size();
// Generate mappings.
auto StringsIterator = Strings.begin();
auto IntegersIterator = Integers.begin();
for(unsigned int i = 0; i < ElementCount; ++i)
{
Mappings[*(StringsIterator)] = *(IntegersIterator);
++StringsIterator;
++IntegersIterator;
}
// Print out before sorting.
std::cout << "Before Sorting" << std::endl;
std::cout << "Int\tString" << std::endl;
StringsIterator = Strings.begin();
IntegersIterator = Integers.begin();
for(unsigned int i = 0; i < ElementCount; ++i)
{
std::cout << *(IntegersIterator) << '\t' << *(StringsIterator) << std::endl;
++StringsIterator;
++IntegersIterator;
}
// Sort
std::sort(Strings.begin(), Strings.end(), CMappedSorter<std::string, int>(&(Mappings)));
std::sort(Integers.begin(), Integers.end());
// Print out after sorting.
std::cout << "After Sorting" << std::endl;
std::cout << "Int\tString" << std::endl;
StringsIterator = Strings.begin();
IntegersIterator = Integers.begin();
for(unsigned int i = 0; i < ElementCount; ++i)
{
std::cout << *(IntegersIterator) << '\t' << *(StringsIterator) << std::endl;
++StringsIterator;
++IntegersIterator;
}
}
else
{
std::cout << "Error: Number of elements in each container are not equivalent." << std::endl;
}
}