C++ finding uint8_t in vector<uint8_t> - c++

I have the following simple code. I declare a vector and initialize it with one value 21 in this case. And then i am trying to find that value in the vector using find. I can see that the element "21" in this case is in the vector since i print it in the for loop. However why the iterator of find does not resolve to true?
vector<uint8_t> v = { 21 };
uint8_t valueToSearch = 21;
for (vector<uint8_t>::const_iterator i = v.begin(); i != v.end(); ++i){
cout << unsigned(*i) << ' ' << endl;
}
auto it = find(v.begin(), v.end(), valueToSearch);
if ( it != v.end() )
{
string m = "valueToSearch was found in the vector " + valueToSearch;
cout << m << endl;
}

are you sure it doesn't work?
I just tried it:
#include<iostream> // std::cout
#include<vector>
#include <algorithm>
using namespace std;
int main()
{
vector<uint8_t> v = { 21 };
uint8_t valueToSearch = 21;
for (vector<uint8_t>::const_iterator i = v.begin(); i != v.end(); ++i){
cout << unsigned(*i) << ' ' << endl;
}
auto it = find(v.begin(), v.end(), valueToSearch);
if ( it != v.end() )
{// if we hit this condition, we found the element
string error = "valueToSearch was found in the vector ";
cout << error << int(valueToSearch) << endl;
}
return 0;
}
There are two small modifications:
in the last lines inside the "if", because you cannot add directly a
number to a string:
string m = "valueToSearch was found in the vector " + valueToSearch;
and it prints:
21
valueToSearch was found in the vector 21
while it's true that you cannot add a number to a string, cout
support the insertion operator (<<) for int types, but not uint8_t,
so you need to convert it to it.
cout << error << int(valueToSearch) << endl;
This to say that the find is working correctly, and it is telling you that it found the number in the first position, and for this, it != end (end is not a valid element, but is a valid iterator that marks the end of your container.)
Try it here

Related

Get value from iterator.first

I've started a little toy project as a way to teach myself C++ and have hit a wall. In the code below the highlighted line is causing a build error saying:
welcome.cc:65:26: error: cannot convert
'std::_Rb_tree_iterator >' to 'char' in
assignment
current = result.first;
and I'm not sure why. The goal is to create a Markov chain for English placenames, the intent of the line in question is meant to update the current letter in the generated placename with a randomly selected value of the previous one, my random selection method is taken from this question. As I say, new to C++ and no idea what I've done wrong.
int main(int argc, char**argv) {
string line;
ifstream myfile;
std::multimap<char, char> m;
myfile.open ("C:\\Users\\james\\Desktop\\placenames.txt");
if (myfile.is_open()){
while ( getline (myfile,line) )
{
for(std::string::size_type i = 0; i < line.size(); ++i) {
std::cout<<line[i]<<std::endl;
m.insert(std::pair<char, char>(line[i], line[i+1]));
}
}
for (std::multimap<char, char>::iterator it = m.begin();it != m.end(); ++it)
cout << " [" << (*it).first << ", " << (*it).second << "]" << endl;
myfile.close();
// for( auto it = m.begin(), end = m.end();it != end; it = m.upper_bound(it->first))
// cout << (*it).first << ' ' << m.count( (*it).first) << endl;
auto current = 'A';
std::string name = "A";
typedef std::multimap<const char, char>::iterator MMAPIterator;
for (int j=0; j<8; ++j){
std::pair<MMAPIterator, MMAPIterator> result = m.equal_range(current);
std::size_t sz = std::distance(result.first, result.second);
std::size_t idx = std::rand() % sz;
std::advance(result.first, idx);
current = result.first; <------THIS LINE
//name+=current;
}
cout << name;
}
else cout << "Unable to open file";
return 0;
}
I'm aware its a pretty naive implementation of a markov chain, btw. As I say, intent was to play around with c++ rather than anything else.
You have a dual layer of pairs here, firstly the equal_range function returns a range, so your
std::size_t sz = std::distance(result.first, result.second);
Tells you how many items are in the range, to get an element of that range (your pair of chars) you need to
auto random_element = result.first;
auto the_const_char = random_element.first;
auto the_non_const_char = random_element.second;

vector element compare c++

This program takes a word from text and puts it in a vector; after this it compares every element with the next one.
So I'm trying to compare element of a vector like this:
sort(words.begin(), words.end());
int cc = 1;
int compte = 1;
int i;
//browse the vector
for (i = 0; i <= words.size(); i++) { // comparison
if (words[i] == words[cc]) {
compte = compte + 1;
}
else { // displaying the word with comparison
cout << words[i] << " Repeated : " << compte; printf("\n");
compte = 1; cc = i;
}
}
My problem in the bounds: i+1 may exceed the vector borders. How to I handle this case?
You need to pay more attention on the initial conditions and bounds when you do iteration and comparing at the same time. It is usually a good idea to execute your code using pen and paper at first.
sort(words.begin(), words.end()); // make sure !words.empty()
int cc = 0; // index of the word we need to compare.
int compte = 1; // counting of the number of occurrence.
for( size_t i = 1; i < words.size(); ++i ){
// since you already count the first word, now we are at i=1
if( words[i] == words[cc] ){
compte += 1;
}else{
// words[i] is going to be different from words[cc].
cout << words[cc] << " Repeated : " << compte << '\n';
compte = 1;
cc = i;
}
}
// to output the last word with its repeat
cout << words[cc] << " Repeated : " << compte << '\n';
Just for some additional information.
There are better ways to count the number of word appearances.
For example, one can use unordered_map<string,int>.
Hope this help.
C++ uses zero-based indexing, e.g., an array of length 5 has indices: {0, 1, 2, 3, 4}. This means that index 5 is outside of the range.
Similarly, given an array arr of characters:
char arr[] = {'a', 'b', 'c', 'd', 'e'};
The loop for (int i = 0; i <= std::size(arr); ++i) { arr[i]; } will cause a read from outside of the range when i is equal to the length of arr, which causes undefined behaviour. To avoid this the loop must stop before i is equal to the length of the array.
for (std::size_t i = 0; i < std::size(arr); ++i) { arr[i]; }
Also note the use of std::size_t as type of the index counter. This is common practice in C++.
Now, let's finish with an example of how much easier this can be done using the standard library.
std::sort(std::begin(words), std::end(words));
std::map<std::string, std::size_t> counts;
std::for_each(std::begin(words), std::end(words), [&] (const auto& w) { ++counts[w]; });
Output using:
for (auto&& [word, count] : counts) {
std::cout << word << ": " << count << std::endl;
}
My problem in the bounds: i+1 may exceed the vector borders. How to I
handle this case?
In modern C++ coding, the problem of an index going past vector bounds can be avoided. Use the STL containers and avoid using indices. With a little effort devoted to learning how to use containers this way, you should never see these kind of 'off-by-one' errors again! As a benefit, the code becomes more easily understood and maintained.
#include <iostream>
#include <vector>
#include <map>
using namespace std;
int main() {
// a test vector of words
vector< string > words { "alpha", "gamma", "beta", "gamma" };
// map unique words to their appearance count
map< string, int > mapwordcount;
// loop over words
for( auto& w : words )
{
// insert word into map
auto ret = mapwordcount.insert( pair<string,int>( w, 1 ) );
if( ! ret.second )
{
// word already present
// so increment count
ret.first->second++;
}
}
// loop over map
for( auto& m : mapwordcount )
{
cout << "word '" << m.first << "' appears " << m.second << " times\n";
}
return 0;
}
Produces
word 'alpha' appears 1 times
word 'beta' appears 1 times
word 'gamma' appears 2 times
https://ideone.com/L9VZt6
If some book or person is teaching you to write code full of
for (i = 0; i < ...
then you should run away quickly and learn modern coding elsewhere.
Same repeated words counting using some C++ STL goodies via multiset and upper_bound:
#include <iostream>
#include <vector>
#include <string>
#include <set>
int main()
{
std::vector<std::string> words{ "one", "two", "three", "two", "one" };
std::multiset<std::string> ms(words.begin(), words.end());
for (auto it = ms.begin(), end = ms.end(); it != end; it = ms.upper_bound(*it))
std::cout << *it << " is repeated: " << ms.count(*it) << " times" << std::endl;
return 0;
}
https://ideone.com/tPYw4a

How to compare elements of a vector against each other? C++

I am supposed to read some data (specifically string datatype) and store each element in a vector. Now I have to check if any of the different strings that were inputted match in size, and if they do I have to see if there are any matching letters. Now my question is how do I compare what's inside the vector (first the size and then the different letters). Is it possible?
Say I have
HELLO
and
HELLA
They have the same size, and 4 letters that match.
This is what I am trying to accomplish.
The code that I have does not work given my ignorance about the matter.
Thank you in advance.
vector <string> myVector;
//insert data insdide of the vector
myVector.push_back("Hello");
myVector.push_back("Hello");
myVector.push_back("Hello2");
myVector.push_back("Hello3");
myVector.push_back("Hello4");
//This is wrong
for (unsigned int i = 0; i < myVector.size(); i++) {
if (myVector[i].size == myVector[i+1].size()){
cout << "SAME SIZE" << endl;
}
}
return 0;
You just have make a simple mistake for size() function and you are trying to access the element which is not present by using i+1 for last iteration.
So just change your for loop just as below
for (unsigned int i = 1; i < myVector.size(); i++)
{
if (myVector[i].size() == myVector[i-1].size()) // .size() should be used
{
cout << "SAME SIZE" << endl;
}
}
Here's a way of writing it:
// returns true if #param s1 and #param s2 are equal in letters
bool isEqual(const string& s1, const string& s2) {
if(s1.size() != s2.size())
return false;
bool equal = false;
// iterates over all the characters in s1 and s2 and compare them
for(auto ch1 = s1.cbegin(), ch2 = s2.cbegin(); ch1 != s1.cend(),ch2!= s2.cend(); ch1++, ch2++) {
if(*ch1 == *ch2)
equal = true;
else
return false;
}
return equal;
}
// type of iter is vector<string>::const_iterator meaning it can only read the value
for (auto iter = myVector.cbegin(); iter != myVector.cend() - 1; iter++){
if(isEqual(*iter, *(iter + 1)))
std::cout << *iter << " equal " << *(iter + 1) << endl;
else
std::cout << *iter << " different " << *(iter + 1) << endl;
}
Here, I used iterators(you should write code in modern C++, avoid using subscript).

C++: Iterate Through Map

I'm trying to iterate through a map to read out a string and then all of the numbers in a vector to a file. I copied and pasted the typedef line, then adjusted it to my code, so I'm not positive it's correct. Anyways, Visual Studio is giving me errors on the use of iterator_variable in my loops. It says type name is not allowed. How can I fix this?
ofstream output("output.txt");
typedef map<string, vector<int>>::iterator iterator_variable;
for (iterator_variable iterator = misspelled_words.begin(); iterator != misspelled_words.end(); iterator++)
{
output << iterator_variable->first;
for (int i = 0; i < misspelled_words.size(); i++)
{
output << " " << iterator_variable->second[i];
}
output << endl;
}
You should access the iterator like iterator->first instead of iterator_variable->first.
And for the inner loop, you probably want to iterate through 0 to iterator->second.size() instead of misspelled_words.size().
ofstream output("output.txt");
typedef map<string, vector<int>>::iterator iterator_variable;
for (iterator_variable iterator = misspelled_words.begin(); iterator != misspelled_words.end(); iterator++)
{
output << iterator->first;
for (int i = 0; i < iterator->second.size(); i++)
{
output << " " << iterator->second[i];
}
output << endl;
}
You can use the the new range based for loop and auto for more concise and readable code too.
ofstream output("output.txt");
for ( auto const & ref: misspelled_words ) {
output << ref.first;
for (auto const & ref2 : ref.second ) {
output << " " << ref2;
}
output << "\n"; // endl force a stream flush and slow down things.
}

Reversing the contents of an std::list

class Print
{
public:
void PrintAll() {}
private:
std::list<int> mylist;
};
I see this example question from a C++ language book.
And I want to print the internal mylist elements.
How can it be done if mylist needs to be reversed, using C++ STL library and using to output the result.
Thanks you very much!
std::list<>::reverse()?
That said, if you only need to print the list in reverse, you can simply print it using list's reverse iterators (obtained by std::list<>::rbegin() and std::list<>::rend()) rather than by using list's normal iterators. E.g.:
// given std::list<int> l;
for (std::list<int>::const_reverse_iterator iter(l.rbegin()), iter_end(l.rend());
iter != iter_end;
++iter)
{
std::cout << *iter << '\n';
}
You can use the reverse() method on your list.
mylist.reverse();
will reverse the contents of your list and then you can print the same, using iterators.
list<int>::iterator it;
cout << "mylist contains:";
for (it=mylist.begin(); it!=mylist.end(); ++it)
cout << " " << *it;
You can wrap all the functionality up in your own member function.
You can also use reverse iterators provided by the container e.g. l.rbegin() and l.rend() and that will iterate through the list backwards.
Code example for list::reverse
// list_reverse.cpp
// compile with: /EHsc
#include <list>
#include <iostream>
int main( )
{
using namespace std;
list <int> c1;
list <int>::iterator c1_Iter;
c1.push_back( 10 );
c1.push_back( 20 );
c1.push_back( 30 );
cout << "c1 =";
for ( c1_Iter = c1.begin( ); c1_Iter != c1.end( ); c1_Iter++ )
cout << " " << *c1_Iter;
cout << endl;
c1.reverse( );
cout << "Reversed c1 =";
for ( c1_Iter = c1.begin( ); c1_Iter != c1.end( ); c1_Iter++ )
cout << " " << *c1_Iter;
cout << endl;
}
And the output will be
c1 = 10 20 30
Reversed c1 = 30 20 10
iterator simply point to the current element in the list. So, if we write a for loop going from end to beginning, we can print the list in reverse. in the code given below:
#include <iostream>
#include <list>
using namespace std;
int main()
{
std::list<int> ii;
ii.push_back(1);
ii.push_back(2);
ii.push_back(3);
ii.push_back(4);
ii.push_back(5);
for (std::list<int>::iterator it = (ii.begin()); it != (ii.end()) ; ++it)
{
cout << (*it) << " ";
}
cout << endl;
for (std::list<int>::iterator it = (--ii.end()); it != (--ii.begin()) ; it--)
{
cout << (*it) << " ";
}
return 0;
}
The first for loop prints out the list from front to back while the second one prints from back to front.