sringstream never hitting eof()

Hi guys,

I'm following Bjarnes book practices and principles chapter 11 page 400, here we are creating a punct stream which basically parses a sentence to eliminate any punctuation. the code is practically a mirror image to the code wrote in the book

but for some reason the while loop never ends, I'm not entirely sure why, I would expect for the stringstream buffers eof() to be set to true eventually but it seems like this never happens, also same thing with source I would expect to eventually hit and eof no?

**edit the buffers eof does indeed get set to true I just moved the test for eof out of the while loop, but this still didn't fix the problem the program is stuck in an infinite loop

any ideas?

thanks


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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>

using namespace std;


class PuncStream{

   private:
       istream& source;
       stringstream buffer;
       string white;

   public:


       PuncStream(istream& src): source(src){}

       void add_whitespace(string wt){

            white = wt;
       }

       bool isWhiteSpace(char& ch){

         for(int i = 0; i < white.size(); i++){

            if(ch == white.at(i)){
                return true;
            }
         }
         return false;
       }

       PuncStream& operator>>(string& sentence){

           while(!(buffer >> sentence)){

              cout << "while" << endl;

             if(buffer.bad() || !source.good())
                return *this;

             buffer.clear();

             getline(source,sentence);

             for(int i = 0; i < sentence.size(); i++){

                if(isWhiteSpace(sentence[i])){

                    sentence[i] = ' ';
                }

             }
             if(buffer.eof()){
                cout << "end" << endl; // line never executes
             }
             buffer.str(sentence);

           }

           return *this;

       }

       operator bool(){

            return !(source.fail() || source.bad())&& source.good();
       }
};

int main()
{
    PuncStream ps(cin);
    ps.add_whitespace(";,:.!()");
    string word;
    vector<string> words;

    while(ps >> word){

            words.push_back(word);
    }

    return 0;
}
Last edited on
The code seems overly complicated. Your main loop is while (ps >> word). How exactly do you want the stream loop to end?

It's prompting you for data. I can make it end by pressing Ctrl + Z and Enter in windows. Otherwise, why would it not be an infinite loop? You need std::cin (your "source") to be in a bad state for it to fail and stop looping.

If you pipe stuff into the program instead of running the program directly, it will also not go into any infinite-prompting loop.
e.g. >echo 1 2 3 4 5 | program_name


Edit:
Are you going for something like this?

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
#include <iostream>
#include <string>

using namespace std;

bool is_punct(char ch)
{
    return std::string(";,:.!()").find(ch) != std::string::npos;
}

std::string punct_removed(std::string token)
{
    std::string out;
    for (char ch : token)
    {
        if (!is_punct(ch))
        {
            out += ch;
        }
    }
    return out;
}

int main()
{
    std::string token;
    if (cin >> token)
    {
        std::cout << punct_removed(token);
    }
    while (cin >> token)
    {
        std::cout << ' ' << punct_removed(token);
    }
}


>>>echo hello;,world:   .!(hello)   world | main2
helloworld hello world
Last edited on
thanks Ganado that is much more concise

believe it or not Bjarne Stoustrup wrote the code, it's quite a headache to look at to be honest.

I changed

1
2
3
4
operator bool(){

            return !(source.fail() || source.bad())&& source.good();
       }


to

1
2
3
4
5
6

operator bool(){

            return !buffer.fail();
       }


it worked but the only problem is it discards the last word, so if I type " Hello world, hey"

it will discard hey and only hello and world will be pushed back into the vector

reason I used buffer.fail() is because eventually buffer's eof() state will be true
Registered users can post here. Sign in or register to post.