Link to home
Start Free TrialLog in
Avatar of SuperSid
SuperSid

asked on

How to backtraec, or backread, or the reverse of (string_stream_s.read(&c,1))?

Hi all,

Is there a way to read back a character?

Say i have:




string t = "Hello world";

stringstream s;

s << t;

char c[100];
int index = 0;
char temp;

s.read(&c[index],1); //c[0] is now 'H'

temp = c[index]; //temp is now 'H'

index++;

s.read(&c[index],1); //c[1] is now 'e'
temp = c[index]; //temp is now 'e'

--------- stop point --------


Now is there a way to read back?   I want to re-read the letter 'H', or to be more specific, backtracing, or reversing (s.read(&c[index],1)), so s.read reads backward 1 character?  I hope my explanation isn't too confusing it's hard to explain hehe.

basicly:


H e l l o  W o r l d

s.read(&c[Index],1); reads H

HERE
|
|
V
H e l l o  W o r l d


now s.read(&c[Index],1); again,
it becomes:

 HERE
   |
   |
   V
H e l l o  W o r l d

But now I want to make it read back to H


HERE
|
|
V
H e l l o  W o r l d


whats the command to do this?
ASKER CERTIFIED SOLUTION
Avatar of Dariusz Dziara
Dariusz Dziara
Flag of Poland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
basic_istream has a putback method you can use.

e.g.
--------8<--------
#include <iostream>
#include <sstream>

// Typically process std::ifstream, using this
void process(std::istream& istr)
{
      int count = 0;
      std::string line;

      while (getline(istr,line)) {

            std::cout << "Line " << ++count << ": " << line << '\n';

            // Using read/putback
            char c;
            if (!istr.read(&c,sizeof(c)))
                  break;
            std::cout << "\t(Next line starts with '" << c << "')\n";
            if (!istr.putback(c))
                  break;

            // Using peek
            std::cout << "\t(Next line starts with '" << static_cast<char>(istr.peek()) << "')\n";
      }
}

int main()
{
      std::istringstream input(
            "Mary had a little lamb,\n"
            "Whose fleece was white as snow.\n"
            "Everywhere that Mary went\n"
            "Her lamb was sure to go.\n"
            );

      // For the illustration, we are processing std::istringstream
      process(input);
}
--------8<--------
Avatar of SuperSid
SuperSid

ASKER

hehe kinda cofused..

mrblue, how would

filestream.seekg(-1, ios::cur);

work in my above program?  where would i put my stringstream s?

rstaveley, how does istringstream work?  

your code has an 'input' as istringstream while mine has 's' as stringstream

so do i replace

stringstream s;

with

istringstream s;

?


and to how do you extract strings...

string t = "hello world";

s << t;  // like this still? or there's another way?
NM i got it!  Thx, mrblue

s.seekg(-1, ios::cur);  

was the key ;)

i'm still confused on how yours works, rstaveley
istringstream is a stringstream which is restricted to input extraction only. You can equally well use a stringstream, which would also permit output insertion.

i.e.

--------8<--------
int main()
{
      //std::istringstream input(
      std::stringstream input(
            "Mary had a little lamb,\n"
            "Whose fleece was white as snow.\n"
            "Everywhere that Mary went\n"
            "Her lamb was sure to go.\n"
            );

      // For the illustration, we are processing std::istringstream
      process(input);
}
--------8<--------

Here's a picture of istream: http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/classstd_1_1basic__istream.html. istream is basic_istream implemented for char characters and wistream is the same thing for wchar_t wide characters. If you write your code to provide an interface for istream (like process in my code example), it works for istringstream, ifstream and the all-powerful iostream, which also inherits from ostream, which therefore gives you output capability. stringstream is derived from iostream, which means that a istream interface works for it too.

My code illustrated two tricks you can perform with istream:

(1) putback - here you see me read a character from the istream and then put it back again. You can only reliably expect to be able to put one character back into an istream.

          // Using read/putback
          char c;
          if (!istr.read(&c,sizeof(c)))
               break;

          std::cout << "\t(Next line starts with '" << c << "')\n";
          if (!istr.putback(c))
               break;

(2) peek - this is not really relevant to your question, but it was in the code snippet in my archive, but it is similar to reading a character and putting it back in one go - i.e. the character is not extracted from the stream.

          static_cast<char>(istr.peek())

BrBlue's seekg is also defined for basic_istream and is therefore a great choice too. If the call was wrapped up in a function, you'd get the most function reuse (and greatest support for unit testing!) by making the function parameter take a reference to istream& rather than fstream&.

My feeling is that Java programmers are generally much better disciplined about programming to interfaces than we C++ programmers... no doubt because we lack the "interface" keyword.