Here is the question I have to solve and the code I've written so far.
Write a function named printDuplicates that accepts an input stream and an output stream as parameters.
The input stream represents a file containing a series of lines. Your function should examine each line looking for consecutive occurrences of the same token on the same line and print each duplicated token along how many times it appears consecutively.
Non-repeated tokens are not printed. Repetition across multiple lines (such as if a line ends with a given token and the next line starts with the same token) is not considered in this problem.
For example, if the input file contains the following text:
hello how how are you you you you
I I I am Jack's Jack's smirking smirking smirking smirking smirking revenge
bow wow wow yippee yippee yo yippee yippee yay yay yay
one fish two fish red fish blue fish
It's the Muppet Show, wakka wakka wakka
My expected result should be:
how*2 you*4
I*3 Jack's*2 smirking*5
wow*2 yippee*2 yippee*2 yay*3
\n
wakka*3
Here is my function:
1 void printDuplicates(istream& in, ostream& out)
2 {
3 string line; // Variable to store lines in
4 while(getline(in, line)) // While there are lines to get do the following
5 {
6 istringstream iss(line); // String stream initialized with line
7 string word; // Current word
8 string prevWord; // Previous word
9 int numWord = 1; // Starting index for # of a specific word
10 while(iss >> word) // Storing strings in word variable
11 {
12 if (word == prevWord) ++numWord; // If a word and the word 13 before it are equal add to word counter
14 else if (word != prevWord) // Else if the word and the word before it are not equal
15 {
16 if (numWord > 1) // And there are at leat two copies of that word
17 {
18 out << prevWord << "*" << numWord << " "; // Print out "word*occurrences"
19 }
20 numWord = 1; // Reset the num counter variable for next word
21 }
22 prevWord = word; // Set current word to previous word, loop begins again
23 }
24 out << endl; // Prints new line between each iteration of line loop
25 }
26 }
My result thus far is:
how*2
I*3 Jack's*2 smirking*5
wow*2 yippee*2 yippee*2
I have tried adding (|| iss.eof()), (|| iss.peek == EOF), etc inside the nested else if statement on Line 14, but I am unable to figure this guy out. I need some way of knowing I'm at the end of the line so my else if statement will be true and try to print the last word on the line.
I am trying to formulate a regular expression to match strings with a certain length, but not counting the "-" character (but may have more than one.
For example:
123-45 12345 123456 abc 123a4... (very long string)
desired results:
123-45
12345
To match 5-digit words, allowing any number of intervening, but not leading/trailing, dashes:
(?<!-)\b(\d-*){4}\d\b(?!-)
See demo showing matching each of:
123-45 12345 1-2-3-4-5 1----2345
but none of:
1234a5 123456 1234 -12345 123-45-
You don't need a regex here. You could do the below which is in pseudo-code.
var len = str.replace("-", "").length;
if(len > 5 || len < 7){
// valid
}
Just remove every - and then check for length
89 int Student::loadStudents() {
90 Student newStudent;
91 string comma;
92 string line;
93 ifstream myfile("student.dat");
94 string name,email="";
95 string status="";
96 int id;
97 if (myfile.is_open()){
98 while ( getline (myfile,line) ) {
99 //parse line
100 string myText(line);
101 istringstream iss(myText);
102 if(!(iss>>id)) id=0;
103
104 std::ignore(1,',');
105 std::getline(iss,name,',');
106 std::getline(iss,status,',');
107 std::getline(iss,email,',');
108 cout<<name<<endl;
109 Student newStudent(id,name,status,email);
110 Student::studentList.insert(std::pair<int,Student>(id,newStudent));
Above is the method I am defining. When the cout is executed the output is:
John Doe
Matt Smith
Before I added in the second getline(iss,name,',') the cout did nothing.
Can anyone explain why it works with the line repeated and why the same code won't work for status and email?
example line from file:
1,john doe,freshman,jd#email.com
EDIT:
I used std::ignore(1,',') before the first getline(iss,name,',') and received the error 'ignore' is undeclared in this namespace 'std'.
Can anyone explain why it works with the line repeated and why the same code won't work for status and email?
Because your first operation on isa is iss>>id.
Presumably your input file is of the form id,name,status,email. That first operation reads up to but not including the first comma. That first comma is still in the input stream. This means your first std::getline(iss,name,',') reads all the stuff remaining before that first comma and that first comma. All the stuff remaining before that first comma -- that's an empty string.
It's best not to mix parsing concepts. Split the line along the commas, then parse each of those split elements.
Edit
Another way to deal with this issue: call std::ignore instead of that first call to std::getline. The next character to be read should be a comma, so just ignore it. This is okay if you can assume a properly formatted input file. It is not okay if you have to deal with the vagaries of input files created by humans.
Another issue: Suppose someone's name is "John Doe, PhD" or the email address is "John Doe, PhD "?
Edit 2
Just to clarify, suppose the line contains "1234,John Doe,freshman,jdoe#college_name.edu".
Input pointer prior to iss>>id:
1234,John Doe,freshman,jdoe#college_name.edu
^
The call to iss>>id sets id to 1234 and advances the input pointer to the first non-numeric character -- the first comma.
Input pointer after iss>>id (prior to first call to std::getline):
1234,John Doe,freshman,jdoe#college_name.edu
____^
The first std::getline(iss,name,',') sees the input pointer is at a comma. It sets name to the empty string and advances the input pointer to just after the comma.
Input pointer after first call to std::getline (prior to second call to std::getline):
1234,John Doe,freshman,jdoe#college_name.edu
_____^
The second std::getline(iss,name,',') reads up to the second comma. It sets name to "John Doe" empty string and advances the input pointer to just after the second comma.
Input pointer after second call to std::getline (prior to third call to std::getline):
1234,John Doe,freshman,jdoe#college_name.edu
______________^
I have a text file
0 Po Tom Mr 123AlphabetStreet Netherlands Wulu 123456 D01 Malaysia SmallAdventure 231112
0 Liu Jack Mr 123AlphabetStreet Italy Spain 123456 D02 Afghanistan TriersAdventure 030214
I am trying to read the txt file:Form.txt, store each line using getline into the variable foo
This is the working program
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
fstream afile;
afile.open("Form.txt",ios::in);
string foo;
while (getline(afile,foo,'\n') );
{
cout<<foo
<<endl;
}
}
Nothing gets printed to the console output , I am expecting
0 Po Tom Mr 123AlphabetStreet Netherlands Wulu 123456 D01 Malaysia SmallAdventure 231112
0 Liu Jack Mr 123AlphabetStreet Italy Spain 123456 D02 Afghanistan TriersAdventure 030214
Instead i get
What is wrong with my code ??
You have a semicolon at the end of your while loop:
while (getline(afile, foo, '\n'));
// ^
This causes the extraction to be performed but only the when the loop ends does foo get printed. The last extraction doesn't extract anything which is why foo is empty, hence the empty output.
char word[10];
int n=5;
while(n--)
{
cin>>word;
cout<<n<<" "<<word<<" ";
}
Output:
ABC DEF GHI JKL MNO
4 ABC 3 DEF 2 GHI 1 JKL 0 MNO
Now, my question is what happens when input buffer encounters a blankspace(' ')? It is seen that n is being decremented after every white space but the cout << word does not display anything on screen.
I am confused as i think that the output should be displayed as soon as one word is input. Eg.
ABC 4 ABC DEF 3 DEF GHI 2 GHI JKL 1 JKL MNO 0 MNO
Not sure I understand your question, but if I'm reading you right: The stream extraction operator reads until it encounters whitespace, and then consumes the whitespace. You don't get a new word consisting of just the whitespace characters.
A few minutes later: I went back and re-read again, and now I think I understand what you're asking: the two streams are not synchronized, so the input and output can't be interleaved in the way you suggest.
cin read strings separated by space but space are discarded in the process
Try doing
cout << flush;
Or
cout << endl;
(inside the while)