Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 11 months ago.
Improve this question
#define FIRST 'a'
#define LAST 'd'
#define ALL ((1 << (LAST-FIRST+1)) - 1)
int main()
{
string s1, s2;
s1 = "aabcd";
s2 = "caabd";
// getline(cin, s1);
// getline(cin, s2);
// Build masks
int mask[1 << CHAR_BIT] = {};
for (char c = FIRST; c <= LAST; ++c)
{
auto it1 = s1.begin(), it2 = s2.begin();
bool done = false, fail = false;
int count[1 << CHAR_BIT] = {};
mask[c] = ALL;
// cout << "c:" << c << " " << ALL << " " << mask[c] << '\n';
do {
// Count characters until next match for c
while (it1 != s1.end() && *it1 != c) ++count[(unsigned char)*it1++];
Can someone explain how the last sentence works (while (it1 != s1.end() && *it1 != c) ++count[(unsigned char)*it1++]; in layman terms. Also, count[1 << CHAR_BIT]. How do I print the contents of the count[] out?
I wrote that code as part of this answer.
The part you're asking about is this:
auto it1 = s1.begin();
int count[1 << CHAR_BIT] = {};
do {
while (it1 != s1.end() && *it1 != c) ++count[(unsigned char)*it1++];
} while (...);
First, it obtains an iterator to the beginning of string s1. It will be used to walk through the string.
auto it1 = s1.begin();
Then it intitializes a histogram as the array count which holds one integer for every possible character, and all values are initialized to zero.
int count[1 << CHAR_BIT] = {};
Let's break down the while-loop in parts:
it1 != s1.end() tests that the iterator has not reached the end of the string
*it1 != c dereferences the iterator (obtaining the character at that position) and compares it to c
++count[(unsigned char)*it1++]; increases the count array at the index given by the current character, and also moves the iterator to the next position in the string.
So what this does is read characters until reaching the end of the string or encountering the character c, and counts all the characters it visited (not including c).
This is only the first half of the Dynamic Programming algorithm I outlined in the original answer. The second half is to then walk through the second string using the same rules and "uncount" all characters visited.
After both strings have been walked to the next occurrence of c, the count array will contain up-to-date information about whether the number of each character seen so far in each string is equal. The mask is then updated, and the outer loop continues stepping through those two strings until the iterators reach the end.
Regarding your other question:
how do i print the content of the count[] out?
Like this:
for (char c = FIRST; c <= LAST; ++c)
{
cout << "count(" << c << ") = " << count[(unsigned char)c] << "\n";
}
it1++: this is a post-increment statement. This means that the returned value from the operation it1++ would be the previous value held by it1 (meaning, before the increment).
*it1++: the * operator, when applied to iterators, accesses its contents. So, here we're accessing the contents of the previous iterator (meaning, the one before the increment took place).
(unsigned char)*it1++: cast the value contained in the previous iterator to unsigned char (probably from char; this is to avoid negative values as an array index).
count[(unsigned char)*it1++]: use the previous value as an index for the count array.
++count[(unsigned char)*it1++]: this is a pre-increment statement. This means that the return value will be the result of incrementing the value contained at the given index. Since the array is default initialized using braces ({}), all values will initially evaluate to 0. So, adding:
cout << ++count[(unsigned char)*it1++] << "\n"; will print the actual count for that letter, with a minimum of 1 since it starts at 0 and it's a pre-increment.
Related
I am trying to truncate beginning zeros from a string, so I used sequence erase function
string& erase (size_t pos = 0, size_t len = npos);
This is my implementaion:
string str="000010557";
for(char c:str){
cout<<c<<" "<<str<<" "<<"\n";// for debug purpose
if(c=='0')
str.erase(0,1);
else
break;
}
cout<<str;
the output string that I got is 0010557 instead of10557 and debug statements prints:
0 000010557
0 00010557
1 0010557
I read the documentation of erase and this post thinking might there be some iterator invalidation but implementing the code snippet recommended in the accepted answer also gave the same output, please help me understand where is the problem.
I am new to using stl library functions, so please forgive any negligence of mine,Thanks.
Your for loop is incrementing the position from which c is extracted, even if you erase a leading zero. Thus, after two runs of the loop, you have erased the first and third of the leading zeros, then the c value will be the first 1.
Here's an attempt at following what happens in your code:
Start of first loop:
"000010557"
^
c is '0', so erase is called, making the string:
"00010557"
At the end of this first loop, the position is incremented, so...
Start of second loop:
"00010557"
^ (Note that we've skipped a zero!)
c is '0', so erase is called, making the string:
"0010557"
End of loop, position increment, and we skip another zero, so...
Start of third loop:
"0010557"
^
c is not '0', so we break out of the loop.
Instead, you should use a while loop, testing only the first character:
int main()
{
string str = "000010557";
char c;
while ((c = str.at(0)) == '0') {
cout << c << " " << str << " " << "\n";// for debug purpose
str.erase(0, 1);
}
cout << str;
}
Output:
0 000010557
0 00010557
0 0010557
0 010557
10557
Of course, you only need the c variable for your 'debugging' line so, without that, you can just have:
int main()
{
string str = "000010557";
while (str.at(0) == '0') str.erase(0, 1);
cout << str;
}
Even if you get this code to work, it's not a good solution. Removing a single character from the front of a string means moving all of the subsequent characters down one position, and the code does that for every leading zero. Instead, count the leading zeros and remove them all at once:
std::string::size_type non_zero_pos = 0;
while (non_zero_pos < str.size() && str[non_zero_pos] == '0')
++non_zero_pos;
str.erase(0, non_zero_pos);
That way, the (expensive) erase operation is only done once.
Or use iterators:
auto non_zero_it = std::find_first_not_of(std::begin(str), std::end(str), "0");
str.erase(std::begin(str), non_zero_it);
Edit: fixed search for non-0 iterator.
I am working on a lab assignment where the user inputs a string and a starting and stopping point for a substring within the string to be reversed. For example, if a user inputs the string "go bobcats", and the numbers 3 (for starting index) and 7 (for ending index), the output should be "go acbobts". I was able to write a recursive function that reverses an entire string ("go bobcats" becomes "stacbob og"), but I am having trouble with the substring aspect.
code for full string reverse:
void reversing(string s, int start, int end){
if(s.size() == 0){return;}
else{
reversing(s.substr(1), start + 1, end);
cout << s[0];
}
}
For the starting and ending index for this I just entered 0 and 9 because that would be the full length of the string.
How can I adjust the function so that it only reverses the string starting and ending at the indexes the user inputs? Also, with my current function I have to use an endl in the main to make a new line at the end of the output of the string. Is there a way I can do this inside the function? If I put an endl after cout << s[0]; it puts in a new line after each iteration making the output vertical:
s
t
a
c
b
o
b
o
g
Implementation in main:
string s;
int start, end;
cout << "Enter a string: ";
while(cin.peek() == '\n' || cin.peek() == '\r'){
cin.ignore();
}
getline(cin,s);
cout << "Now enter two numbers that are within the bounds of the string. ";
cin >> start >> end;
cout << "This is how your words look now:\n";
reversing(s,start,end);
cout << endl;
A function to reverse the string can swap the elements at both ends of the range and decrease the range by one on both sides.
void reversing(string& s, int start, int end) {
if (start >= end)
return;
swap(s[start], s[end]);
reversing(s, start + 1, end - 1);
}
And then inside main():
// ...
cout << "This is how your words look now:\n";
reversing(s, start, end);
cout << s << endl;
Sometimes it is sad to see how C++ is used to teach everything but not C++. The following is sort of an experiment to see if we can somehow approach std::reverse (the algorithm you should actually use) by actually ignoring the requirements of your homework and doing small digestable steps.
Lets start with a small variation on the solution presented in this answer. Instead of passing the string together with indices we can use iterators. In a nutshell, iterators are the glue between algorithms and data structures, more specifically container. They can refer to elements in a container, just like an index or pointer can do.
void reversing2(std::string::iterator first, std::string::iterator last) {
if (first >= last) return;
std::swap(*first,*last);
reversing2(++first,--last);
}
Iterators can be dereferenced like pointers to get a reference to the element (*first and *last). RandomAccessIterators can be incremented (++first), decremented (--last) and be compared (first >= last), just like you would do it with indices.
The next step is a difficult one, because it requires even more handwaving. Note that apart from the function signature nothing in the above function actually depends on first and last being iterators for elements in a std::string. For example to reverse a subarray of an int[] only the signature would have to change:
void reversing2(int* first, int* last) {
if (first >= last) return;
std::swap(*first,*last);
reversing2(++first,--last);
}
That makes a nice opportunity to get in touch with templates. I know that I am commiting a small crime here, because I cannot give a thorough intro, but will only present you a very narrow case. To make the same code usable for different containers we just have to modify it a little
template <typename IT>
void reversing(IT first,IT last) {
if (first >= last) return;
std::swap(*first,*last);
reversing(++first,--last);
}
This can now be called with any RandomAccessIterator. So this:
#include <string>
#include <iostream>
int main() {
std::string s{"Hello world"};
std::cout << s << '\n';
reversing2(s.begin()+3,s.begin()+7); // pass iterators to 4th and 8th character
std::cout << s << '\n';
reversing(s.begin()+3,s.begin()+7);
std::cout << s << '\n';
int x[]= {1,2,3,4,5,6};
reversing(&x[2],&x[5]); // pointers are iterators too
for (const auto e : x) std::cout << e;
}
Will produce this output:
Hello world
Helow olrld
Hello world
126543
Eventually, and this was the whole motivation for the preceding, we can see that the reversing is quite similar to std::reverse. Of course std::reverse is not recursive and there is one small caveat: standard algorithms typically work on half-open intervals, ie a range made from two iterators first and last where first is included in the interval, but last is one past the last element in the interval. Hence to get the same result, you would have to call it with the second iterator one position further than with the above function:
std::reverse(s.begin()+3,s.begin()+8); // pass iterators to 4th and one past the 8th character
Complete online example
In your function declaration the type of the first parameter is not a referenced type. So the function deals with a copy of an original string passed to the function as an argument.
However in any case your recursive function definition is invalid. At least there is no need to extract a sub-string.
Pay attention to that the second and the third parameters of the function should have the type std::string::size_type. Otherwise the user can supply a negative values for the parameters when they have the type int and the function will have undefined behavior.
Also it is better when the function returns reference to the reversed string itself.
In fact within the function you need to use only one check that the start position is less than the end position.
Here is a demonstrative program that shows how the function can be defined.
#include <iostream>
#include <string>
std::string & reversing( std::string &s, std::string::size_type start, std::string::size_type end )
{
if ( not s.empty() )
{
if ( not ( end < s.size() ) ) end = s.size() - 1;
if ( start < end )
{
std::swap( s[start], s[end] );
reversing( s, start + 1, end - 1 );
}
}
return s;
}
int main()
{
std::string s( "Hello bobaloogie" );
std::cout << s << '\n';
std::cout << reversing( s, 0, 4 ) << '\n';
std::cout << reversing( s, 6, s.size() ) << '\n';
return 0;
}
The program output is
Hello bobaloogie
olleH bobaloogie
olleH eigoolabob
well i also have a solution but without implementing library function just to give you a feel of implementation and it's pretty simple.
adjusting your function - swap the start and last position recursively instead of doing
exhaustively .
endl in the main - if you wish to save the answer in input string only then yes you have to do that in main . Else just before returning from function put 'endl '.
My code goes like this.
#include<bits/stdc++.h>
using namespace std;
void rev(string &str,int s,int l){ // s = start l = last
if(l<s) return ; // base condition when l precedes s
else {
char temp = str[s];
str[s] = str[l];
str[l] = temp;
rev(str,++s,--l);
}
return ;
}
int main(){
string str;
int s,l;
getline(cin,str);
cin>>s>>l;
assert(s<str.size() && l<str.size());
rev(str,s,l);
cout<<str;
}
There are different way to approach this problem, the greedy one is to use substring to pass the exact string to the reverse function:
void reversing(string s){
if(s.size() == 0){return;}
else{
reversing(s.substr(1));
cout << s[0];
}
}
void main(string s, int start, int end) {
string substring = reversing(s.substr(start, end - start + 1));
cout << s.substr(0, start) + substring + s.substr(end + 1);
}
else you need to edit your function that reverse to edit the string only when in such range
void reversing(string s, int start, int end, int index = 0, string output = ""){
if(s.length() == index){return output;}
else{
if (index >= start && index <= end) {
output = output + s[end - (index - start)];
} else {
output += s[index];
}
reversing(s, start, end, index+1, output);
cout << output[output.length()-1];
}
}
I have a list
list<pair<Zeitpunkt, double>> l_tempdiff;
And I only want to cout the first 5 elements.
I only know the way of couting the whole list with:
for (auto elem : l_tempdiff)
{
cout << elem.first << elem.second << endl;
}
I dont know how to acces my elements when I use:
for (it = l_tempdiff.begin(); it != l_tempdiff.end(); ++it)
{
}
And I guess I need to change the l_tempdiff.end() to some other value but it doesnt seem to take just the number5`. How can I do this?
Since std::list iterators are not random access you cannot just increment them like l_tempdiff.begin() + 5. What you can do is use std::next to increment the iterator the required number of times. That would looks like
for (auto it = l_tempdiff.begin(), end = std::next(l_tempdiff.begin(), 5); it != end; ++it)
{
// use `*it` here
}
Before doing this though you should make sure the list is big enough because if it isn't then you'll have undefined behavior.
You only want to output the first five elements?
Well, a for-range-loop is a good place to start, just add the additional constraint as a break-condition:
int i = 0;
for (auto&& elem : l_tempdiff)
{
if (5 < ++i) break;
cout << elem.first << elem.second << endl;
}
I change auto to auto&& to avoid needless copying.
As an aside, consider reading "Why is "using namespace std" considered bad practice?" and "C++: "std::endl" vs "\n"".
list<pair<Zeitpunkt,double> > :: iterator it;
int m = 0;
it = l_tempdiff.begin();
while( it != l_tempdiff.end() && m < 5)
{
cout<<it->second<<"\n";
m++;
it++;
}
Try
auto it = l_tempdiff.begin();
auto end = l_tempdiff.end();
for (int count = 0; count < 5 && it != end; ++count)
{
std::cout << it->first << it->second << std::endl;
std::advance(it);
}
This prints the first five pairs (or all the pairs, if there are less than 5).
count is used to control the maximum number of elements to be printed.
it is an iterator that, in each iteration of the loop, references the current pair.
Note that advancing an end iterator gives undefined behaviour. So it is necessary to terminate the loop if the end iterator is reached (hence the it != end test in the loop condition) or if the maximum number of elements (5) is reached.
What I'm confused about is that I have a map which is made up of size_t of string as the key, and strings as the value.
std::multimap<size_t, std::string> wordMap;
Then I have a pair that stores the equal_range for all strings with size of 4. Then I want to iterate through the start of that equal_range to the end of that equal_range. The start is my pair.first and end is my pair.second. How would I iterate through every character that my pair.first points too and then compare that to every word in between pair.first and pair.second ?
pair<multimap<size_t, string>::iterator, multimap<size_t, string>::iterator> key_range;
key_range = wordMap.equal_range(n);
Basically I want to compare every letter in word1 to every character in word2.
Advance itr2 which is word2 to the next word and compare every letter in that to every letter in word1. Do this for every word then advance itr1 which is word1 to another word and compare that to every word.
How would I get every character itr2 points to? I think the first for loop accomplishes this for the first iterator but I don't know how to do it for itr2.
for (word_map::iterator itr = key_range.first; itr != key_range.second; itr++) { //this loop will iterate through every word to be compared
for (word_map::iterator itr2 = next(key_range.first); itr2 != key_range.second; itr2++) { //this loop will iterate through every word being compared against itr1
int i = 0;
int hit = 0;
for (char& c1 : itr->first) {
char& c2{ (itr2)->first[i] };
if(c1 != c2)
hit++;
i++;
}
}
I'd like to compare every letter in every word against each other as long as they have the same string size. Then if hit == 1 that means the words are only off by 1 character and they should be mapped or stored in some type of STL container that groups them. I'm still new to STL so i'm thinking a set but I need to read more into it.
First, you'd be more likely to get assistance if you provided a minimal compilable example. I'm assuming your words are std::strings for this answer, but you know what they say about assuming.
There are algorithms like "zip" which is implemented in Boost specifically for iterating over mulitple collections simultaneously, but I don't think there's anything comparable in the standard library.
A simple but unpleasantly fiddly approach would be just to manually iterate through both strings. This will output each letter in the two words until either one word ends, or there's a difference.
Note all the fiddly bits: you need to make sure both iterators are valid at all times in case one word ends before the other, and working out what actually happened is a bit cumbersome.
#include <string>
#include <iostream>
int main()
{
std::string word1 = "capsicum";
std::string word2 = "capsicube";
std::string::iterator it1 = word1.begin();
std::string::iterator it2 = word2.begin();
while (it1 != word1.end() && it2 != word2.end())
{
// characters are different!
if (*it1 != *it2)
break;
// characters are the same
std::cout << "Both have: " << *it1 << std::endl;
// advance both iterators
++it1;
++it2;
}
if (it1 == word1.end() && it2 == word2.end())
{
std::cout << "Words were the same!" << std::endl;
}
else if (it1 == word1.end())
{
std::cout << "Word 1 was shorter than word 2." << std::endl;
}
else if (it2 == word2.end())
{
std::cout << "Word 1 was longer than word 2." << std::endl;
}
else
{
std::cout << "Words were different after position " << (it1 - word1.begin())
<< ": '" << *it1 << "' vs '" << *it2 << "'" << std::endl;
}
}
New answer, since the question was significantly updated. I'm still not sure this will do exactly what you want, but I think you should be able to use it to get where you want to go.
I've written this as a minimal, complete, verifiable example, which is ideally how you should pose your questions. I've also used C++11 features for brevity/readability.
Hopefully the inline comments will explain things sufficiently for you to at least be able to do your own research for anything you don't fully understand, but feel free to comment if you have any more questions. The basic idea is to store the first word (using the key_range.first iterator), and then start iterating from the following iterator using std::next(), until we reach the end iterator in key_pair.second.
This then gives us word1 outside of the loop, and word2 within the loop which will be set to every other word in the list. We then use the "dual interation" technique I posted in my other answer to compare each word character by character.
#include <map>
#include <string>
#include <iostream>
int
main()
{
std::multimap<size_t, std::string> wordMap;
wordMap.insert({4, "dogs"});
wordMap.insert({4, "digs"});
wordMap.insert({4, "does"});
wordMap.insert({4, "dogs"});
wordMap.insert({4, "dibs"});
// original type declaration...
// std::pair<std::multimap<size_t, std::string>::iterator, std::multimap<size_t, std::string>::iterator> key_range;
// C++11 type inference...
auto key_range = wordMap.equal_range(4);
// make sure the range wasn't empty
if (key_range.first == key_range.second)
{
std::cerr << "No words in desired range." << std::endl;
return 1;
}
// get a reference to the first word
std::string const& word1 = key_range.first->second;
std::cout << "Comparing '" << word1 << "' to..." << std::endl;
// loop through every iterator from the key_range, skipping for the first
// (since that's the word we're comparing everything else to)
for (auto itr = std::next(key_range.first); itr != key_range.second; ++itr)
{
// create a reference for clarity
std::string const& word2 = itr->second;
std::cout << "... '" << word2 << "'";
// hit counter; where hit is defined as characters not matching
int hit = 0;
// get iterators to the start of each word
auto witr1 = word1.begin();
auto witr2 = word2.begin();
// loop until we reach the end of either iterator. If we're completely
// confident the two words are the same length, we could only check
// one of them; but defensive coding is a good idea.
while (witr1 != word1.end() && witr2 != word2.end())
{
// dereferencing the iterators will yield a char; so compare them
if (*witr1 != *witr2)
++hit;
// advance both iterators
++witr1;
++witr2;
}
// do something depending on the number of hits
if (hit <= 1)
{
std::cout << " ... close enough!" << std::endl;
}
else
{
std::cout << " ... not a match, " << hit << " hits." << std::endl;
}
}
}
For an assignment, we have to do a large program that manipulates C++ strings in a variety of ways. Most of it is working, but this particular function is messing with me. I am trying to cycle through a string and remove all non-alphanumeric (tab, blank newline) characters before the first alphanumeric one occurs, and then end the string when the first non-alphanumeric character appears again. For example, " bob jon" would be saved as "bob". Something is going wrong where every string is considered empty. Most peers have been telling be that
*(point++) = *marker;
can't be done and that I should change this before trying anything else...is this a way to increment the iterator while assigning its value to another iterator's value? Is it that the problem or something else?
void clean_entry( const string& j, string& k )
{
string::iterator point = k.begin();
bool checker = false;
//cycle through the constant string and check for numbers and letters
for(string::const_iterator marker = j.cbegin(); marker!=j.cend(); ++marker)
{
if( isalnum(*marker) == true )
{
*(point++) = *marker; //copy to the new k string if alphanum, and increment iterator
cout << "I found a real letter!" << endl; //debugging
checker = true;
}
else if( checker == true )
break;
}
cout << "So far we have " << k << endl; //debugging
if (checker == false )
k = "(empty word)";
cout << "The new string is " << k << " apparently." << endl; //debugging
}
isalnum doesn't return bool. It returns int. The guarantee is that it returns nonzero if the character is alphanumeric and zero otherwise.This means that you can't compare the return value to true, as that comparison causes true to be converted to int, yielding 1, before the comparison is done.. if(isalnum(*marker)) is both idiomatic and actually works.Similarly, if( checker == true ) is bloated and should be if(checker), and if (checker == false ) should be if(!checker).
Your interface is questionable, since the caller must ensure that k's size is large enough to accommodate the resulting string. Better to clear k and then use push_back() or similar rather than an iterator.
On the assumption that k.size() is sufficiently large, there's nothing wrong with *(point++) = *marker;.