A stream io problem.


R. Clayton (rclayton@clayton.cs.monmouth.edu)
(no date)


I found that g++ in these two platform are different even though I used the
same arguments as you used to compile the files.

For example, I want to set the cout to display the float in fixed format. I
used 'fixed' manipulator on SOLARIS, but there is no 'fixed' on LINUX. Then I
use setf() function of cout. But they are still different:

On SOLARIS:
#include <ios>
cout.setf(ios_base::fixed, ios_base::floatfield);

On LINUX:
#include <streambuf>
cout.setf(ios::fixed, ios::floatfield);

  The important thing to remember is that you're dealing with the standard c++
  library. That has several consiquences, which the code fragments don't deal
  with, and that's causing all the problems.

  But first, I'm not sure how to interpret the code fragments. In particular,
  neither of them work on the respective hosts:

    cl uname -s
    SunOS

    cl cat s.cc
    #include <ios>

    int main() {
      cout.setf(ios_base::fixed, ios_base::floatfield);
      }

    cl g++ -c s.cc
    s.cc: In function `int main()':
    s.cc:4: `cout' undeclared (first use this function)
    s.cc:4: (Each undeclared identifier is reported only once for each function
       it appears in.)
    s.cc:4: `ios_base' undeclared (first use this function)
    s.cc:4: parse error before `::' token

    cl

    ro uname -s
    Linux

    ro cat l.cc
    #include <streambuf>

    int main() {
      cout.setf(ios::fixed, ios::floatfield);
      }

    ro g++ -c l.cc
    l.cc: In function `int main()':
    l.cc:4: `cout' undeclared (first use this function)
    l.cc:4: (Each undeclared identifier is reported only once for each function
       it appears in.)
    l.cc:4: `ios' undeclared (first use this function)
    l.cc:4: parse error before `::' token

    ro

  Even though I don't understand the code fragments, their error messages give
  several valuable clues. First, cout is undefined, which you would expect
  because cout is defined in <iostream>, which the code doesn't include:

    cl cat s.cc
    #include <ios>
    #include <iostream>

    int main() {
      cout.setf(ios_base::fixed, ios_base::floatfield);
      }

    cl g++ -c s.cc
    s.cc: In function `int main()':
    s.cc:5: `cout' undeclared (first use this function)
    s.cc:5: (Each undeclared identifier is reported only once for each function
       it appears in.)
    s.cc:5: `ios_base' undeclared (first use this function)
    s.cc:5: parse error before `::' token

    cl

  But cout is still undefined. Here's where the standard c++ library comes in.
  Because the iostream system is part of the standard c++ library, it is, like
  all parts of the standard c++ library, part of the std name space. Dealing
  with that in the code gives:

    cl cat s.cc
    #include <ios>
    #include <iostream>

    int main() {
      std::cout.setf(ios_base::fixed, ios_base::floatfield);
      }

    cl g++ -c s.cc
    s.cc: In function `int main()':
    s.cc:5: `ios_base' undeclared (first use this function)
    s.cc:5: (Each undeclared identifier is reported only once for each function
       it appears in.)
    s.cc:5: parse error before `::' token

    cl

  That takes care of cout, but what about ios_base? It's the same story:
  ios_base is part of the io stream library, which is part of the standard
  c++ library, which is in the std namespace. Dealing with that in the code
  gives

    cl cat s.cc
    #include <ios>
    #include <iostream>

    int main() {
      std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
      }

    cl g++ -c -ansi -pedantic -Wall s.cc

    cl

  That fixes up the problem (on solaris, anyway), but the code still needs to
  be cleaned up a bit. In class I briefly sketched the bottom half of the file
  stream class hierarchy; now we have to look at the upper half of the stream
  class hierarchy:

          ios_base
             |
             |
            ios
            / \
           / \
      istream ostream
           \ /
            \ /
         iostream

  The first thing to note about this diagram is that it's not right. The
  stream hierarchy actually constists of template classes (except for
  ios_base); what I've shown here is the instantiations of the template classes
  for the basic c++ type char.

  The second thing to note, although it's difficult to see in this diagram, is
  that ios is a specialization of ios_base for the char template parameter.
  Some of the things defined in ios_base may be redefined in ios to make them
  appropriate for the char data type. You should use ios:: rather than
  ios_base:: to access stream entities to make sure you're accessing the right
  entities. In this case it probably doesn't make any difference because
  you're accessing bit flags, which don't need to change from one data type to
  the next, but other entities may change depending on the template parameter
  type.

  The third thing to note is that iostream has ios has a parent, so it's
  unnecessary to include ios explicitly if you include iostream (and there's no
  reason to just include ios). This may seem a trivial point, but it's not:
  good programmers write code that can be easily changed, and changing one
  thing (for example, changing iostream to wiostream) is easier than changing
  two things (for example, changing both iostream and ios to wiostream and
  wios).

  What we're left with is some small, compact code that's standards conformant
  (I hope), which means it should be compilable on any standards conformant
  compiler, whether it be on solaris

    cl cat s.cc
    #include <iostream>

    int main() {
      std::cout.setf(std::ios::fixed, std::ios::floatfield);
      }

    cl g++ -c -ansi -pedantic -Wall s.cc

    cl CC -c s.cc

    cl

  or linux

    ro g++ -c -ansi -pedantic -Wall s.cc

    ro



This archive was generated by hypermail 2.0b3 on Fri May 10 2002 - 12:45:04 EDT