Well, it's pretty much there, but...
Using a istringstream as a pretend file for test purposes (see code following), I get the following with your hasDuplicates() function:
1 : Did you know this this message contains lots of redundant
2 : code code that does not make sense
4 : All bar two lines (with with text) have have duplicates
5 : in in them them them!
9 : This has no duplicates either but does have extra spaces
11 : The following following line is just just spaces!
12 :
13 : That's all all all, folks! |
where I've tweaked your example test file data a bit, adding an empty and a space only lines to your test data. Plus a line with no duplicates but extra spaces.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
bool hasDuplicates(string line)
{
stringstream ss(line);
string token = "";
string latestToken = "";
bool duplicateFound = false;
while (getline(ss, token, ' '))
{
if (token == latestToken)
{
duplicateFound = true;
}
latestToken = token;
}
return duplicateFound;
}
int main()
{
// Pretend file data - "q3.txt"
const char testData[] =
"Did you know this this message contains lots of redundant\n"
"code code that does not make sense\n"
"\n"
"All bar two lines (with with text) have have duplicates\n"
"in in them them them!\n"
"\n"
"This is one of the two lines with no-duplicates\n"
"\n"
"This has no duplicates either but does have extra spaces\n"
"\n"
"The following following line is just just spaces!\n"
" \n"
"That's all all all, folks!\n";
istringstream in_file(testData); // pretend file!
// cf. ofstream in_file("q3.txt");
int counter = 0;
string line;
while (getline(in_file, line))
{
counter++;
if(hasDuplicates(line)) // or whatever
{
cout << counter << " : " << line << endl;
}
}
return 0;
}
|
The problem is you use of getline, which isn't the right choice here. This is a program which (1) uses your approach to tokenize a string on spaces and (2) does the same thing but using operator>>
input: "one two three four five spaces!"
test_getline
1 = one
2 = two
3 =
4 = three
5 =
6 =
7 = four
8 =
9 =
10 =
11 = five
12 =
13 =
14 =
15 =
16 = spaces!
test_extract_op
1 = one
2 = two
3 = three
4 = four
5 = five
6 = spaces! |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
void test_getline(string line)
{
cout << "test_getline" << endl;
stringstream ss(line);
string token = "";
int counter = 0;
while (getline(ss, token, ' '))
{
++counter;
cout << counter << " = " << token << endl;
}
cout << endl;
}
void test_extract_op(string line)
{
cout << "test_extract_op" << endl;
stringstream ss(line);
string token = "";
int counter = 0;
while (ss >> token)
{
++counter;
cout << counter << " = " << token << endl;
}
cout << endl;
}
int main()
{
char test_data[] = "one two three four five spaces!";
cout << endl;
cout << endl;
test_getline(test_data);
test_extract_op(test_data);
return 0;
}
|
you can see that operator>> is a better fit here than getline (which returns a "token" for each and every space it find.)
So an improved version of you function would be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
bool hasDuplicates(string line)
{
stringstream ss(line);
string token = "";
string latestToken = "";
bool duplicateFound = false;
while (ss >> token) // now using extraction op
{
if (token == latestToken)
{
duplicateFound = true;
}
latestToken = token;
}
return duplicateFound;
}
|
(You could fix the getline version by (1) ignoring empty token (using string::empty()) or (2) eating the while space (ss >> ws), but these approaches don't make sense when you can just use the extraction operator.)
So using
ss >> token
rather then
getline(ss, token, ' ')
will get your function to behave as required.
To be continued...
Andy