title: getline() until end of input C++
body: <p>Here is my code. It is supposed to get input until end of input and place that input into the string <strong>data</strong>. Then it is supposed to tokenize the input using the delimiter "<strong>#</strong>". I then repeatedly call my function nexttoken() to store the tokens in variables.</p>
  
  <pre><code>std::istream_iterator&lt;char&gt; it(std::cin);
  std::istream_iterator&lt;char&gt; end;
  std::string data(it,end);
  std::string delimiter = "#";
  StringTokenizer strtok(data,delimiter);
  std::string t1      = strtok.nextToken();
  std::string t2      = strtok.nextToken();
  </code></pre>
  
  <p>This all works when I pass a file through on command line like this:</p>
  
  <pre><code>program.exe &lt;testcase1.txt
  </code></pre>
  
  <p>testcase1.txt</p>
  
  <pre><code>S A B #
  S -&gt; a A #
  S -&gt; z B #
  A -&gt; b B c B #
  B -&gt; d A #
  ##
  </code></pre>
  
  <p>output</p>
  
  <pre><code>S A B 
  a: 1
  b: 1
  c: 1
  d: 1
  z: 1
  </code></pre>
  
  <p>everything checks out and works.</p>
  
  <p>My problem is this: When I push run in my IDE I can type the input in manually but when I do there is no way to make the program accept the input except if I press <kbd>ctrl-z</kbd>. This problem also persists in linux when I pass a file through in terminal, it just hangs there letting me type infinite lines.</p>
  
  <p>here is a smaller version of my code that only counts 3 tokens and only checks for a,b and c</p>
  
  <p>main.cpp</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;iostream&gt;
  #include &lt;string&gt;
  #include &lt;iterator&gt;
  #include &lt;algorithm&gt;
  #include &lt;cstddef&gt;
  #include "StringTokenizer.h"
  
  int countSubstring(const std::string&amp; str, const std::string&amp; sub)
  {
      if (sub.length() == 0) return 0;
      int count = 0;
      for (size_t offset = str.find(sub); offset != std::string::npos;
       offset = str.find(sub, offset + sub.length()))
      {
          ++count;
      }
      return count;
  }
  
  int main(int argc, char* argv[1])
  {
  
  int task;
  
  if (argc &lt; 2)
  {
      std::cout &lt;&lt; "Error: missing argument\n";
      return 1;
  }
  task = atoi(argv[1]);
  switch(task){
  
      case 0:
          {
  std::istream_iterator&lt;char&gt; it(std::cin);
  std::istream_iterator&lt;char&gt; end;
  std::string data(it,end);
  std::string delimiter = "#";
  StringTokenizer strtok(data,delimiter);
  
     int a = 0;
     int b = 0;
     int c = 0;
  
  //reading the first token and puting it in tk1
  std::string t1      = strtok.nextToken();
  std::string tk1(t1);
  tk1.erase(0, tk1.find_first_not_of(" "));
  tk1.erase(tk1.find_last_not_of(" ")+1);
  
  // token 2 and 3 are different because 1 is always the same format
  std::string t2      = strtok.nextToken();
  std::string tk2(t2);
  
              if(countSubstring(tk2,"a") &gt; 0)
      {
          a = a + 1;
      }
              if(countSubstring(tk2,"b") &gt; 0)
      {
           b=b  + 1;
      }
              if(countSubstring(tk2,"c") &gt; 0)
      {
           c=c  + 1;
      }
  
  std::string t3      = strtok.nextToken();
  std::string tk3(t3);
  if(countSubstring(tk3,"a") &gt; 0)
      {
          a = a + 1;
      }
              if(countSubstring(tk3,"b") &gt; 0)
      {
           b=b  + 1;
      }
              if(countSubstring(tk3,"c") &gt; 0)
      {
           c=c  + 1;
      }
  
  // this is where the output is
  std::cout &lt;&lt; tk1 &lt;&lt; std::endl;
  
  
      if(a &gt; 0)
    {
        std::cout &lt;&lt; "a: " &lt;&lt; a &lt;&lt;std::endl;
    }
      if(b &gt; 0)
    {
        std::cout &lt;&lt; "b: " &lt;&lt; b &lt;&lt;std::endl;
    }
      if(c &gt; 0)
    {
        std::cout &lt;&lt; "c: " &lt;&lt; c &lt;&lt;std::endl;
    }
  
            }
    break;
    //////////////////////////////////////////////////
      case 1:
          break;
      case 2:
          break;
  
      default:
          std::cout &lt;&lt; "Error: unrecognized task number " &lt;&lt; task &lt;&lt; "\n";
          break;
  }
  return 0;
  }
  </code></pre>
  
  <p>StringTokenizer.h</p>
  
  <pre><code>#ifndef INCLUDE_STRINGTOKENIZER_H
  #define INCLUDE_STRINGTOKENIZER_H
  
  
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;iostream&gt;
  #include &lt;string&gt;
  
  
  class StringTokenizer
  {
  public:
     StringTokenizer(const std::string&amp; _str, const std::string&amp; _delim);
    ~StringTokenizer(){};
  
  
     std::string nextToken();
     std::string nextToken(const std::string&amp; delim);
  
  
  private:
  
     std::string  token_str;
     std::string  delim;
  };
  
  #endif
  </code></pre>
  
  <p>StringTokenizer.cpp</p>
  
  <pre><code>#include "StringTokenizer.h"
  
  StringTokenizer::StringTokenizer(const std::string&amp; _str, const std::string&amp; _delim)
  {
     if ((_str.length() == 0) || (_delim.length() == 0)) return;
  
     token_str = _str;
     delim     = _delim;
  
     /*
       Remove sequential delimiter
     */
     unsigned int curr_pos = 0;
  
     while(true)
     {
        if ((curr_pos = token_str.find(delim,curr_pos)) != std::string::npos)
        {
           curr_pos += delim.length();
  
           while(token_str.find(delim,curr_pos) == curr_pos)
           {
              token_str.erase(curr_pos,delim.length());
           }
        }
        else
         break;
     }
  
     /*
       Trim leading delimiter
     */
     if (token_str.find(delim,0) == 0)
     {
        token_str.erase(0,delim.length());
     }
  
     /*
       Trim ending delimiter
     */
     curr_pos = 0;
     if ((curr_pos = token_str.rfind(delim)) != std::string::npos)
     {
        if (curr_pos != (token_str.length() - delim.length())) return;
        token_str.erase(token_str.length() - delim.length(),delim.length());
     }
  }
  
  
  
  
  std::string StringTokenizer::nextToken()
  {
     if (token_str.length() == 0)
       return "";
  
     std::string  tmp_str = "";
     unsigned int pos     = token_str.find(delim,0);
  
     if (pos != std::string::npos)
     {
        tmp_str   = token_str.substr(0,pos);
        token_str = token_str.substr(pos+delim.length(),token_str.length()-pos);
     }
     else
     {
        tmp_str   = token_str.substr(0,token_str.length());
        token_str = "";
     }
     return tmp_str;
  }
  
  
  std::string StringTokenizer::nextToken(const std::string&amp; delimiter)
  {
     if (token_str.length() == 0)
       return "";
  
     std::string  tmp_str = "";
     unsigned int pos     = token_str.find(delimiter,0);
  
     if (pos != std::string::npos)
     {
        tmp_str   = token_str.substr(0,pos);
        token_str = token_str.substr(pos + delimiter.length(),token_str.length() - pos);
     }
     else
     {
        tmp_str   = token_str.substr(0,token_str.length());
        token_str = "";
     }
  
     return tmp_str;
  }
  </code></pre>
  
  <p><strong>1: How do I change my code so that It will stop searching for input when I am done typing? or when it can see ## has been typed? (## marks the end of the input)</strong></p>
  
  <p><strong>2: Is this even possible with my current code?</strong></p>
  
  <p>Both Linux and my IDE compile with g++</p>