Home c++ How to read a string from the console unknown in advance not...

How to read a string from the console unknown in advance not using String?

Author

Date

Category

I understand perfectly that you can use the String class and simply write CIN & GT; & GT; STR; And then get the number of items.
I even saw a fun solution using Malloc and Realloc functions from C.
But still, it is interesting, there is some kind of way using C++ funds, and specifically their input streams and standard strings in the form of an array of characters to read from the console, without having the concept of its size, it is subsequently obtained and put in dynamically selected An array of this size ??
The question is not to the robust and not for some kind of task, everything is clean for the sake of interest, so your answers, like “do not worry and use what they give” are also welcome)


Answer 1, Authority 100%

cin & gt; & gt; STR; Write only to the first separator: http://ideone.com/y5cjxd .

If a string is understood by a sequence that ends with a row translation ('\ n' ), then you: std :: getline () you need: http://www.cplusplus.com/reference/string/string/getLine/

And so, STD :: String This is so standard tool in C++. If you want to pervert, then you need to read blocks, check – whether there is a translation of the line and aggregate the code, but it is necessary to somehow stored between challenges. Either, which is easier, but slower – to read in prevail, checking the end of the line, for example, so:

iStream & amp; GetLine (Istream & Amp; Is, Char * & Amp; Buffer)
{
  Std :: Istream :: Sentry S (IS);
  if (s)
  {
    STD :: IStreamBuf_Iterator & LT; Char & GT; IT (IS);
    STD :: IStreamBuf_Iterator & LT; Char & GT; end;
    Size_t Size = 64;
    Size_t Grow = 64;
    Size_T Len = 0;
    Buffer = New Char [Size];
    While (IT! = End & amp; & amp; * it! = '\ n')
    {
      if (Len == (Size - 1))
      {
        Buffer = Buffer_Relloc (Buffer, Size, Size + Grow);
        Size + = Grow;
      }
      Buffer [Len ++] = * IT ++;
    }
    Buffer [Len] = '\ 0';
  }
  Return is;
}

Here I do not bring the buffer_realloc () – it is simple. Use something like this:

char * line = nullptr;
While (GETLINE (STD :: CIN, LINE))
{
  If (Line)
  {
    COUT & LT; & LT; Line & lt; & lt; Endl;
    DELETE [] LINE;
  }
}

Either here is an option where the vector uses:

iStream & amp; GetLine (Istream & amp; IS, Vector & LT; Char & GT; & Amp; Buffer)
{
  Std :: Istream :: Sentry S (IS);
  if (s)
  {
    STD :: IStreamBuf_Iterator & LT; Char & GT; IT (IS);
    STD :: IStreamBuf_Iterator & LT; Char & GT; end;
    Const Size_t Grow = 64;
    Buffer.Reserve (Grow);
    While (IT! = End & amp; & amp; * it! = '\ n')
    {
      if (buffer.size () == buffer.capacity () - 1)
      {
        buffer.reserve (buffer.size () + grow);
      }
      buffer.push_back (* IT ++);
    }
    buffer.push_back ('\ 0');
  }
  Return is;
}

Use something like this:

vector & lt; char & gt; Line;
While (GETLINE (STD :: CIN, LINE))
{
  if (! line.empty ())
  {
    COUT & LT; & LT; line.data () & lt; & lt; Endl;
    line.clear ();
  }
}

Realokation of memory falls on the shoulders of Vector. From you only to clean it (and you can bind to GaTline). Plus a bonus at once long string for O (1): line.size () - 1

Here are complete examples:

But I repeat: Std :: String Standards for C++. I have a weak idea of ​​the conditions where there are threads, but no lines 🙂


Answer 2, Authority 33%

In fact, the implementation of Cin looks like this (ignoring the fact that both streams and string patterns):

std :: iStream & amp; Operator & gt; & gt; (Std :: Istream & amp; In, Std :: String & Amp; Value) {
  Std :: Istream :: Sentry Cerberos (in);
  If (Cerberos) {
    Value.ERASE ();
    STD :: IStreamBuf_Iterator & LT; Char & GT; IT (IN), END;
    if (IT! = End) {
      STD :: CTYPE & LT; Char & GT; Const & amp; CType (STD :: Use_FACET & LT; STD :: CTYPE & LT; Char & gt; & gt; (in.getloc ()));
      STD :: back_insert_iterator & lt; std :: string & gt; TO (Value);
      std :: streamsize n (0), width (in.width ()? in.width (): Std :: String :: Max_size ());
      for (; it! = End & amp; & amp; n! = width & amp; & amp;! ctype.is (std :: ctype_base :: space, * it); ++ IT, ++ To) {
        * to = * it;
      }
    }
  }
  ELSE {
    In.SetState (STD :: IOS_BASE :: FAILBIT);
  }
  RETURN IN;
}

Conclusions I think you can do yourself.


Answer 3

A little strange question, because If you need to do the same thing that can be done using Std :: String – at least to see the implementation of Operator & GT; & GT; for the input flow and string argument.

The main point is that we read in prevail and predicately add. As a result, we will also get some semblance of the implementation of STD :: Vector for symbolic type.

Programmers, Start Your Engines!

Why spend time searching for the correct question and then entering your answer when you can find it in a second? That's what CompuTicket is all about! Here you'll find thousands of questions and answers from hundreds of computer languages.

Recent questions