[comp.lang.c++] Questions on I/O in 2.0

holmes@bthpyd.UUCP (Jim Holmes) (09/29/89)

Questions about i/o under 2.0

I am converting a medium sized project written in 1.2 to 2.0.

One of the modules is produced by a well-known scanner generator
and then passed through sed to make it valid food for CC.  So far
the i/o in this module has only cooperated with <stdio.h> while
all other modules are happy with either <iostream.h> or <stream.h>.

Naturally the output from the scanner is produced *along with*
output from the various other modules.  Unfortunately, all the 
scanner output is either printed  prior to any other output or
it is saved up until the (iostream) output from the
other modules is totally flushed from the buffer.  Is there
a way to coordinate the various outputs so that things are 
displayed in the order computed?

Also, is the fact that form() lives only in <stream.h> significant?
The Book had over one page on it.  I couldn't find anything in Lippman
about it.  Has it fallen out of favor?

--------
Simple Example of the problem: main module
________

#include <iostream.h>

extern void mod1();
extern void mod2();

main() {
	cout << "illustrating message synchronizing problem\n";
	mod1();
	mod2();
}

--------
	Offending module:
________

#include<stdio.h>
//because output by lex and conversion to iostream is a mess

void mod1() {
	printf("hello from mod1\n");
}

--------
	Cooperative modules:
________

#include<stream.h>
//files containing c++ stuff or stuff generated by yacc

void mod2() {
	cout << "hello from mod2\n";
}

--------
sample run
________

Script started on Thu Sep 28 14:13:41 1989
% a.out
hello from mod1
illustrating message synchronizing problem
hello from mod2
% ^D
script done on Thu Sep 28 14:13:51 1989


--------
Jim Holmes                              INTERNET    holmes@bethel.edu
Bethel College				UUCP	    amdahl!bungia!bthpyd!holmes
St. Paul, MN 55112			ATT	    (612) 638-6315

jss@jra.ardent.com (Jerry Schwarz (Compiler)) (10/03/89)

In article <499@bthpyd.UUCP> holmes@bthpyd.UUCP (Jim Holmes) writes:
>Questions about i/o under 2.0
>
>Naturally the output from the scanner is produced *along with*
>output from the various other modules.  Unfortunately, all the 
>scanner output is either printed  prior to any other output or
>it is saved up until the (iostream) output from the
>other modules is totally flushed from the buffer.  Is there
>a way to coordinate the various outputs so that things are 
>displayed in the order computed?
>

The problem is that both stdout and cout have internal buffers
that are only flushed under certain circumstances.  The simplest 
way to address the problem is to call ios::sync_with_stdio() 
before you do any output to cout.  

Ios::sync_with_stdio() does two things: 

	1. It turns cout into an ostream that uses stdout (the 
	   default writes directly to file descriptor 1) 

	2. It puts cout into unit buffering mode. This causes 
	   flushes of stdout to be done before insertions into cout
	   and flushes of cout to be done after insertions.  
	   
There is a performance penalty for doing this, which is why it 
isn't the default.  

Alternatively you can be careful about always flushing stdout 
before using cout, and always flushing cout before using stdout.

>Also, is the fact that form() lives only in <stream.h> significant?
>The Book had over one page on it.  I couldn't find anything in Lippman
>about it.  Has it fallen out of favor?
>

Yes it is significant. "form" is not a good C++ interface for I/O.  
It isn't type safe and it isn't easily extensible.  If you like
a stdio interface. The same effect is easily accomplished by sprintf'ing 
into a buffer and using the char*.  (Which is all form ever did anyway.)  
The 2.0 iostream library contains a much larger variety of formatting support 
than does the 1.x stream library, so I think the need for form is much 
decreased.  

I urge people to become familiar with I/O manipulators. They are a 
little complicated to write, but once they are written, they are very 
easy to use.  And since they follow a fixed pattern, once you've 
written one its easy to write more.

Jerry Schwarz
jss@ardent.com

carroll@paul.rutgers.edu (V. I. Lenin) (10/03/89)

In article <8496@ardent.UUCP> jss@jra.ardent.com (Jerry Schwarz (Compiler)) writes:

> ..."form" is not a good C++ interface for I/O.  
> It isn't type safe and it isn't easily extensible.  If you like
> a stdio interface. The same effect is easily accomplished by sprintf'ing 
> into a buffer and using the char*...

I think Jerry missed a good opportunity to brag about his iostreams.
The reason you don't need "form" in 2.0 is not because you can emulate
it with sprintf, but rather because you can do it much better with
ostrstreams.  Example:

        int i;
        char *s;
        T t;
        char *printString;

Using form:
        printString = form("i is %d, s is %s", i, s);

Using an ostrstream:
        ostrstream os;
        os << "i is " << i << ", s is " << s << ", t is " << t;
        printString = os.str();

Notice that using an ostrstream makes in-core I/O just as uniform and
extensible as external I/O.  And as Jerry points out, you don't need
all that printf-style "%-5s" field qualifier stuff, you can do it all
much more cleanly with iostream manipulators.

martin