From: DaRQsiDe on
Greetings all,

I got stuck at one point in this exercise. I actually wrote the code
for the exercise (for who has the book) but one thing I still
wonder...

5-1. Design and implement a program to produce a permuted index. A
permuted index is one in which each phrase is indexed by every word in
the phrase.

In one place of the code, there should be a rotator function that
rotates words. I tried to use two different approaches...

1- Using vector of vectors of strings

vector< vector<string> > GenerateRotamer (const vector<string>&
str_vec) {

typedef vector<string>::size_type str_vec_size;
vector<string> str_vec_copy (str_vec);
vector< vector<string> > rot_vec;

str_vec_size i = 0;
while (i < str_vec_copy.size()) {
rot_vec.push_back(str_vec_copy);
string rotated = *(str_vec_copy.begin());
str_vec_copy.erase(str_vec_copy.begin());
str_vec_copy.push_back(rotated);
i++;
}

return rot_vec;

} -> This works perfectly.

2- (First trial actually) I tried to use a vector of vectors of string
vector iterators

typedef vector<string>::iterator str_vec_iter;
vector< vector<str_vec_iter> > GenerateRotamer (const vector<string>&
str_vec) {

vector<str_vec_iter> str_vec_iter;
vector< vector<str_vec_iter> > rot_vec_iter;

for (str_vec_iter i = str_vec.begin() ; i < str_vec.end() ; i++) {
str_vec_iter.push_back(i);
}

vector<str_vec_iter>::size_type j = 0;
while (j < str_vec_iter.size()) {
rot_vec_iter.push_back(str_vec_iter)
str_vec_iter temp_iter = *(str_vec_iter.begin())
str_vec_iter.erase(str_vec_iter.begin());
str_vec_iter.push_back(temp_iter);
j++;
}
} -> In essence the two codes should do the same work but this code
using the iterator vectors didnot worked.

So my question is - cannot we use iterators synonymous to pointers in
C? I didnot wanted to use pointers sine that would discard the purpose
of Accelerated C++ imo.

Thanks,

Cihan
From: DaRQsiDe on
Greetings to all again,

As I worked with the code and tried to experiment with it I got two
more questions...

This is the complete code. Works nicely.

#include <iostream>
#include <string>
#include <vector>
#include <cctype>
#include <algorithm>
#include <iomanip>

using namespace std;

vector<string> SplitStringBySpace (const string& str_in) {

typedef string::size_type str_size;
vector<string> str_vec;

str_size i = 0;
while (i != str_in.size()) {

while (i != str_in.size() && isspace(str_in[i])) {
i++;
}

str_size j = i;
while (j != str_in.size() && !isspace(str_in[j])) {
j++;
}

if (i != j) {
str_vec.push_back(str_in.substr(i, (j - i)));
i = j;
}

}

return str_vec;

}


vector< vector<string> > GenerateRotamer (const vector<string>&
str_vec) {

vector<string> str_vec_copy (str_vec);
vector< vector<string> > rot_vec;

str_vec_copy.push_back("END_OF_LINE");
vector<string>::iterator iter = str_vec_copy.begin();

while (*(str_vec_copy.begin()) != "END_OF_LINE") {
rot_vec.push_back(str_vec_copy);
string rotated = *(str_vec_copy.begin());
str_vec_copy.erase(str_vec_copy.begin());
str_vec_copy.push_back(rotated);
}

return rot_vec;

}

bool CompareWord (const vector<string>& str_vec_1, const
vector<string>& str_vec_2) {

vector<string>::const_iterator iter_1 = str_vec_1.begin();
vector<string>::const_iterator iter_2 = str_vec_2.begin();

while (*iter_1 == *iter_2) {
iter_1++;
iter_2++;
}

string str_1 = *iter_1;
string str_2 = *iter_2;

transform (str_1.begin(), str_1.end(), str_1.begin(), ::tolower); //
Question 1
transform (str_2.begin(), str_2.end(), str_2.begin(), ::tolower);

return str_1 < str_2;

}

string::size_type VectorToString (vector< vector<string> >& rot_vec,
vector<string>& left_output, vector<string>& right_output) {

for (vector< vector<string> >::iterator i = rot_vec.begin() ; i <
rot_vec.end() ; i++) {
string left_line;
string right_line;

vector<string>::iterator j = (*i).begin();
while (j != (*i).end()) {
while (*j != "END_OF_LINE") {
right_line += *j;
right_line += " ";
j++;
}
if (*j == "END_OF_LINE") {
j++;
}
while (j != (*i).end()) {
left_line += *j;
left_line += " ";
j++;
}
}

/* -> Question 2...
// Remove trailing spaces...
left_line.erase(left_line.end());
right_line.erase(right_line.end());
*/

left_output.push_back(left_line);
right_output.push_back(right_line);
}

string::size_type max_length = 0;
vector<string>::iterator j = left_output.begin();
while (j < left_output.end()) {
max_length = max (max_length, (*j).size());
j++;
}

return max_length;

}

int main () {

string input;
vector< vector<string> > all_rotamers;

while (getline(cin, input)) {
vector<string> input_words;
vector< vector<string> > input_rotamers;

input_words = SplitStringBySpace (input);
input_rotamers = GenerateRotamer (input_words);

all_rotamers.insert (all_rotamers.end(), input_rotamers.begin(),
input_rotamers.end());
}

sort (all_rotamers.begin(), all_rotamers.end(), CompareWord);

vector<string> left_out;
vector<string> right_out;

string::size_type left_offset = VectorToString (all_rotamers,
left_out, right_out);

cout << endl;

for (int i = 0 ; i < left_out.size() ; i++) {
cout << setw(left_offset+1) << left_out[i];
cout << "\t" << right_out[i] << endl;
}

cout << endl;

}

Now questions...

1- At line 71 in function transform, I had to include "::tolower" to
convert the string to lowercase. Instead of "::tolower" when I put
"tolower" (without the two semicolons) compiler (icpc) complained :

5-1.cpp(71): error: no instance of overloaded function "transform"
matches the argument list
argument types are: (__gnu_cxx::__normal_iterator<char *,
std::basic_string<char, std::char_traits<char>,
std::allocator<char>>>, __gnu_cxx::__normal_iterator<char *,
std::basic_string<char, std::char_traits<char>,
std::allocator<char>>>, __gnu_cxx::__normal_iterator<char *,
std::basic_string<char, std::char_traits<char>,
std::allocator<char>>>, <unknown-type>)
transform (str_1.begin(), str_1.end(), str_1.begin(), tolower); //
Question 1
^
I saw many examples using tolower without the semicolons on internet.
Why do you think is the reason of this complaint? (g++ also
complains...)

2- At line 101, i tried to delete the trailing space resulting from
string concatenation. The program compiles with the code, but the
output I get from the program is a segmentation fault if i try to
erase the last character in the string with string.erase(string.end).
Why is the reason for this behavior?

Thank you,

Cihan
From: n00m on
Weird. Must work.


int main() {
string s = "aBcDDeT";

s.erase(s.size() - 1);
cout << s << endl;
//aBcDDe

transform(s.begin(), s.end(), s.begin(), tolower);
cout << s << endl;
//abcdde