seeking within ostringstream's

A

Adrian

What is a stringsteam supposed to do when you seek past the end of
existing buffer. I can seek past the end of a file stream (my
implementation fills the space will nulls but I cannot find if this is
guaranteed either)

Below code fails for a stringstream. Any good ways of dealing with
this.

Reason for doing this is that I am modify old C code for screen output
that positions fields based on a row. I wanted to use a stringstream
and just seek to the correct place.

I have tried basically filling the stream with X spaces first. But
then I am never sure there is enough space.

Any help appreciated.



Adrian

#include <iostream>
#include <sstream>
#include <fstream>

int main(int argc, char *argv[])
{
std::eek:fstream out("test.txt");

out.seekp(500);
out << "some text\n";

std::eek:stringstream out2;

out2.seekp(500);
out2 << "some text\n";

if(!out2)
{
std::cout << "bad out2\n";
}
return 0;
}
 
B

BobR

Adrian said:
What is a stringsteam supposed to do when you seek past the end of
existing buffer. I can seek past the end of a file stream (my
implementation fills the space will nulls but I cannot find if this is
guaranteed either)

Below code fails for a stringstream. Any good ways of dealing with
this.

Reason for doing this is that I am modify old C code for screen output
that positions fields based on a row. I wanted to use a stringstream
and just seek to the correct place.

I have tried basically filling the stream with X spaces first. But
then I am never sure there is enough space.

Any help appreciated.
Adrian

#include <iostream>
#include <sstream>
#include <fstream>

int main(int argc, char *argv[]){
std::eek:fstream out("test.txt");

out.seekp(500);
out << "some text\n";

std::eek:stringstream out2;

out2.seekp(500);

if( not out2 ){
std::cout << "out2 in failure\n";
}
else{
std::cout << "out2 position=" <<out2.tellp()<<'\n';
}
out2 << "some text\n";

if(!out2)
{
std::cout << "bad out2\n";
}
return 0;
}

Your result?
 
B

BobR

Adrian said:
The stringstream is not in a good state. I tried it with exceptions on
and I get
"basic_ios::clear" from what()

I think a safer way to move to a position might be:

std::eek:stringstream out2;
// ....

size_t pos( out2.tellp() );
std::string Space( ( 500 - pos ), ' ' );

// > out2.seekp(500);
out2<<Space;

// ....
 
J

James Kanze

What is a stringsteam supposed to do when you seek past the end of
existing buffer. I can seek past the end of a file stream (my
implementation fills the space will nulls but I cannot find if this is
guaranteed either)

I can't find anything really specifying it either, but I suspect
that it's undefined behavior (or unspecified). It also depends
on whether you are using the two argument form of seek, or the
one argument form. (With the one argument form, it's actually
impossible to obtain a position which you haven't already
visited without involving undefined or unspecified behavior.
With the possible exception of start of file.)

Logically, one might say that a good implementation would
generate an error on an attempt to seek beyond end of file, but
in practice, this would have significant run-time cost on some
systems.
Below code fails for a stringstream. Any good ways of dealing with
this.
Reason for doing this is that I am modify old C code for
screen output that positions fields based on a row. I wanted
to use a stringstream and just seek to the correct place.
I have tried basically filling the stream with X spaces first.
But then I am never sure there is enough space.
#include <iostream>
#include <sstream>
#include <fstream>
int main(int argc, char *argv[])
{
std::eek:fstream out("test.txt");
out.seekp(500);

The above line is not even guaranteed to compile, much less do
anything useful.
out << "some text\n";
std::eek:stringstream out2;
out2.seekp(500);

And the same holds true here.
out2 << "some text\n";
if(!out2)
{
std::cout << "bad out2\n";
}
return 0;
}

I'm not too sure what you're doing, but it sounds like what you
want is something like std::string or std::vector<char>, using
resize( ' ' ) as needed.
 
A

Adrian

I'm not too sure what you're doing, but it sounds like what you
want is something like std::string or std::vector<char>, using
resize( ' ' ) as needed.

I am trying to clean up and rewrite some old code that is creating
rows for screen display that uses cursor position and printf type
args.

Thing is I can never tell exactly how long the row could be. And the
version of snprintf on this platform returns -1 if printed string is
longer then buffer rather then what should be then length.

I was hoping with seeking in a stringstream I could keep almost the
same arguments

Example of old stuff below:
pn1(0, row, "%-10s", HemName_of(obj));
pn1(11, row, "%-2s",
Area_sh_nms[Mt_AreaFromCnum(Mt_Cnum_of(obj))]);
pn1(14, row, "%-8d", Mt_Cnum_of(obj));
pn1(23, row, "%-6s", Mt_ObjTypeName_of(obj));
pn1(30, row, "%-7s", Mt_CmdtyName_of(obj));
if (Mt_ObjType_of(obj) == EQUITY_TYPE)
pn1(38, row, "%-25s", Mt_Name_of(obj));
else {
strcpy(XSymb, Mt_Name_of(obj));
if (strlen(XSymb) > 14) {
XSymb[14] = '*';
XSymb[15] = '\0';
}
pn1(38, row, "%-15s", XSymb);
}
if (Mt_ObjType_of(obj) == FUTURE_TYPE)
{
pn1(54, row, "%-.6ld", Mt_dtoymd(Mt_ExpDate_of(obj)));
pn1(62, row, "%-6s",
HemName_of(Mt_FindByLdOptIndx(Mt_RelLdOpt_of(obj))));
}
else if (Mt_ObjType_of(obj) == BOND_TYPE)
{
pn1(54, row, "%-.6ld", Mt_dtoymd(Mt_ExpDate_of(obj)));
pn1(62, row, "%-6s", Mt_SymAlias_of(obj));
}
if (((Mt_ObjType_of(obj) == FX_TYPE) ||
(Mt_ObjType_of(obj) == CASH_VOL_TYPE))
&& (Mt_HeFlags_of(Mt_Cmdty_of(obj)) & CASH_SCALE_MSK))
{
pn1(69, row, "%-7s", Display_scale_of(Mt_CshScale_of(obj)));
}
else
pn1(69, row, "%-7s", Display_scale_of(Mt_Scale_of(obj)));
pn1(77, row, "%-3s", TransExchangeName(obj));
if (Mt_ObjType_of(obj) == BOND_TYPE)
{
if ((Mt_HeFlags_of(obj) & ALIAS_MSK) != 0)
pn1(76, row, "%c", 'A');
}
break;
 
B

BobR

Adrian said:
I am trying to clean up and rewrite some old code that is creating
rows for screen display that uses cursor position and printf type
args.

Thing is I can never tell exactly how long the row could be. And the
version of snprintf on this platform returns -1 if printed string is
longer then buffer rather then what should be then length.

size_t rows(25);
size_t cols(80);
std::vector<std::string> vScrn( rows, std::string( cols, ' ' ) );

So, now you have an 25x80 "screen". But, now you can change it's size at
will.

// add a row
vScrn.push_back( std::string( cols, ' ' ) );

// make all cols 90
for( size_t i(0); i < vScrn.size(); ++i ){
vScrn.at(i).append( 10, ' ' ); // add 10 spaces
} // for(i)

// make it 20x50
vScrn.resize( 20 );
for( size_t i(0); i < vScrn.size(); ++i ){
vScrn.at(i).resize( 50 );
} // for(i)

// Change the char at row 3, col 22, to "A":
vScrn.at(2).at( 21 ) = 'A';

// send the whole thing to cout:
std::copy( vScrn.begin(), vScrn.end(),
std::eek:stream_iterator<std::string>( std::cout, "\n" ) );

Etc..

You could put it all in one std::string, but then you'd need to keep track
of the new-line chars ('\n').
std::string( " line one.\n line two.\n line three.\n ....." );

I much prefer the vector of strings. Use the power of the standard C++
library.
I was hoping with seeking in a stringstream I could keep almost the
same arguments

For a learning excersize, go ahead. Otherwise, re-design it from the ground
up. I'm still fighting an C_to_C++ project I started years ago, a real mess.
(if only I knew then what I know now! said:
Example of old stuff below:
pn1(0, row, "%-10s", HemName_of(obj));

Without knowing what declaration of 'pn1' is, it's hard to give you an
example.

Think it over, and come back here if/when you need help.
 
J

James Kanze

I am trying to clean up and rewrite some old code that is creating
rows for screen display that uses cursor position and printf type
args.

But that doesn't really tell me much. The obvious way to
represent rows in a screen display would be something like:
typedef std::vector< char > Row ;
std::vector said:
Thing is I can never tell exactly how long the row could be. And the
version of snprintf on this platform returns -1 if printed string is
longer then buffer rather then what should be then length.

What I'd probably do is use something like the above. Then,
given a request to insert an int 'value' at position i, j, I'd
write something like:

std::eek:stringstream tmp ;
tmp << value ;
if ( display.size() <= i ) {
display.resize( i + 1 ) ;
}
Row& r = display[ i ] ;
std::string s( tmp.str() ) ;
size_t lastCol = j + s.size() ;
if ( r.size() <= lastCol ) {
r.resize( lastCol + 1, ' ' ) ;
}
std::copy( s.begin(), s.end(), r.begin() + j ) ;
I was hoping with seeking in a stringstream I could keep almost the
same arguments
Example of old stuff below:
pn1(0, row, "%-10s", HemName_of(obj));
pn1(11, row, "%-2s", Area_sh_nms[Mt_AreaFromCnum(Mt_Cnum_of(obj))]);
pn1(14, row, "%-8d", Mt_Cnum_of(obj));
pn1(23, row, "%-6s", Mt_ObjTypeName_of(obj));
pn1(30, row, "%-7s", Mt_CmdtyName_of(obj));

The only real problem will be handling the formatting strings.
And it shouldn't be too difficult to parse them, mapping them to
fmtflags, width and precision arguments for the ostringstream.
Or check out boost::format, which I think can handle about 95%
of the formatting flags---only a few of the more exotic cases
aren't handled. (The syntax of boost::format is rather wierd,
since it uses %, rather than <<, as the inserter, which rapidly
leads to fairly unreadable code. But if you're only inserting
one value at a time, and that value is always a parameter to the
function, it shouldn't be too bad. I used to have a Format
class myself; as a result of a challenge, I'd actually
implemented 100% of the printf formatting, plus the X/Open
extensions, along with all sorts of hooks to make it easy for
user defined types to do as well, if they had semantics more or
less like those of a floating point or integral number. I
stopped maintaining it sometime back, however, because I never
used it; the ostream formatting is so much more readable.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,077
Latest member
SangMoor21

Latest Threads

Top