2

I'm trying to format output using the NTL library (a number theory library). One of the objects is the GF2X object, which is a polynomial represented as a string of coefficients. A quick example:

GF2X a = GF2X(5,1);
a++;
cout<<a;

will yield [1 0 0 0 0 1] which is the same as x^5 + 1. My question is about formatting this output using setw. I want to be able to output various length GF2X objects, prepended by a number, and appended with a string. I'd like my output to look like the following:

  1:    [x x x x x x x x]       string here
 15:    [x x x]                 string here

I would also settle for the right ] to be aligned, which is what I should probably expect if I'm using setw. However, when i use the code (variable names ommitted for simplicity):

    cout << setw(3)<< int <<": "<< setw(35) << GF2X << setw(15) << string << endl;

I get output more like this (some white space removed for compactness)

  1:            [x x x x x x x x]   string here
 15:            [x x x]   string here

In other words, the setw function seems to be treating the entire output of <<GF2X as a single character, and doesn't seem to actually account for the size of the output string. As you can see from the output I've shown you, the left side of the GF2X output is aligned, but the right side isn't, whereas typically, setw seems to align the right side of outputs.

Teofrostus
  • 1,506
  • 4
  • 18
  • 29
  • one approach can be to overload the << operator for GF2X – nims Jul 29 '12 at 18:48
  • @nims: He appears to have done that. io manipulators are poorly suited to their job. I much prefer to use custom classes that format my objects as strings, and pass those to streams, and functions which create those objects. Would look something like this: `cout << FormatWidth(35, GF2X);` – Benjamin Lindley Jul 29 '12 at 18:50
  • Have you tried passing `std::left`? – jrok Jul 29 '12 at 18:53
  • 3
    @jrok: I have a feeling that's going to leave him with an open bracket, followed by a bunch of spaces, and then the rest of his output. The problem is of course that setw only works on the next element output, and his operator is probably written as a combination of output statements. – Benjamin Lindley Jul 29 '12 at 19:04
  • I don't actually want to mess with the files in the NTL library, since this is a highly advanced library for manipulating numbers and polynomials and gets into mathematics which I don't understand. I'll look into std::left. – Teofrostus Jul 29 '12 at 19:08
  • @BenjaminLindley I don't think he has overloaded the operator<< for GF2X looks like he is using the one supplied by the library. – oz10 Jul 29 '12 at 19:11
  • @jrok std::left does exactly what Benjamin said. It gives me a left bracket, a bunch of space, and then some elements. Maybe I could do something like store the string in a ostringstream, and then try setw again. – Teofrostus Jul 29 '12 at 19:14

2 Answers2

2

You can do it with a modification to the output operator. I imagine it's written something like this (I don't know anything about this GF2X class, so this is partially psuedo-code:

std::ostream & operator<<(std::ostream & os, const GF2X & x)
{
    os << '[';
    for (int i=0; i<x.num_elements; ++i)
        os << x.get_element(i) << ' ';
    return os << ']';
}

The problem is that setw will only operate on that first '[', it doesn't operate on the whole object (it doesn't know what the whole object is). You can fix the operator by writing the whole thing to a string (using stringstream or some other means), and then outputting the string. If modifying the operator is not an option for you, then you will need to use a separate helper function to first convert the object to a string (using a stringstream), then output that string to the stream.

Actually, boost::lexical_cast would come in really handy for you here, since it will do that last for you:

cout << setw(35) << boost::lexical_cast<std::string>(GF2X);
Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • I see by your latest comment that you already thought of this. – Benjamin Lindley Jul 29 '12 at 19:18
  • Yes, unfortunately, there aren't actually member functions to access each individual element of the GF2X class either. But the workaround of using a temporary ostringstream buffer worked. Would it be prudent to answer my own question with the solution I found? Or should I just close this question? – Teofrostus Jul 29 '12 at 19:21
  • @Teofrostus: Answer the question. – Benjamin Lindley Jul 29 '12 at 19:23
0

You can use a temporary ostringstream object to hold the output, and then use setw on the string provided (variable names omitted).

    ostringstream oss;
    oss << GF2X;
    cout << setw(3) << x << ": "<< setw(35) << oss.str() << setw(15) << string <<endl;

This formats the entire ostream object, rather than just the first character, and gives the proper output.

Teofrostus
  • 1,506
  • 4
  • 18
  • 29