27 Formatted Input-Output Operations in C++
Jyoti Pareek
Introduction
This module introduces the techniques to perform formatted input/output operations from standard devices using member functions of stream classes and using manipulators. In previous module, we learnt text I/O using operators (insertion, extraction)and member functions (put, get, getline) without specifying format. When format is not specified, it uses default values for formatting. Formatting is the process of transforming a byte sequence into a human-readable character sequence. The objective of this module is to learn formatting dataas per need of the users. We will also study details about errors in input/output operations.
- Formatting
Internal representation of numeric data is in binary; need not be in human readable form. Text I/O involves formatting or converting the data into the external representation as a sequence of characters.
For example, a value 00000000 01000001 is read from memory as short int. When this number is written to output stream, it is transformed into characters ‘6’ and ‘5’ and stored in the stream. In the same way, when reading a number from keyboard, if user have entered integer number using keys ‘6’ and ‘5’, these two characters are read from input stream and are converted to the binary representation of a number 65 for storage in the program.
Simple input and output of items using extraction and insertion operators is notsufficient in many cases. For example, in case of tabular output of student’s result statement; names should be left aligned, marks should be right aligned, decimal point should be aligned in percentage of marks and the columns should be of specific width and so on. Iostreams allow controllingsuch formatting features inmany ways with the help of formatting flags.
With iostreams, one can specify:
- The width of the field and the adjustment of the outputwithin this field;
- The decimal point to be aligned;
- The precision and format of floating point numbers;
- Whether to skip white spaces when reading from aninput stream;
- Whether integral values are displayed in decimal, octal or hexadecimal format;
- … many more
1.1. Formatting Flags
Formatting control is possible via a stream’s format state. Associated with each stream, there are a number of format state variables that control the details of formatting. These variables are defined in ios class. Three format state variables are used to store the values of width, precision and fill character. In additional to these variables, an enum variable is used for formatting flags. Formatting flags are represented by one or more bits in a data member of type fmtflags in class ios_base. It is defined as enumerated data type. The bits act as on/off switches that specify various formats as shown below.
Format | Group | Default | i/o | Effect |
flag | ||||
left | adjustfield | right | o | Left-align, padding with fill character on right |
right | Right-align, padding with fill character on left | |||
internal | padding between sign or base indicator and number [- | |||
12.34] | ||||
dec | basefield | dec | i,o | integer to decimal form |
oct | integer to octal form | |||
hex | integer to hexadecimal form | |||
fixed | floatfield | fixed | o | Floating point in fixed point notation [123.45] |
scientific | Floating point in scientific notation [1.2345E2] | |||
skipws | 1 | i | When unset to 0, white spaces are not ignored | |
boolalpha | 0 | i,o | When set to 1, bool values converted to string “true” or | |
“false” | ||||
showpos | 0 | o | When set, show + sign before non-negative integers | |
showpoint | 0 | o | Always show decimal point in floating point o/p [123.00] | |
showbase | 0 | o | Show base indicator (0 for octal, 0x for hex) | |
uppercase | 0 | o | Use uppercase X, E, and hex output letters (ABCDEF) | |
unitbuf | 0 | o | Flush o/p stream after each formatting operation |
The bits of formatting flag and the values of format state variables can be set/reset or get using member functions of ios class and also by using manipulators.
- Formatting using ios functions
The ios class contains a number of functions that can be used to set/unset the formatting flags and perform other tasks using format state variables.
Function | Default | Effect | ||
width() | 0 | Minimum field with to be used | ||
precision() | 6 | Precision for number of digits after decimal point | ||
fill() | Space character | Fill character to be used for padding | ||
setf() | 0 | Set bit of format flag | ||
unsetf() | 0 | Reset bit of format flag |
First three functions can be used to set the value of the format state variables with specified argument and they all return the old the value of the corresponding variable. For example, w=width(5); sets the value of format state variable width to 5 and returns its old value.These functions can also be used without specifying argument. In this case, it simply returns the value of the format state variables. Ex. w=width(); returns the value of width.Functions setf() and unsetf() takes bits of format flags as arguments and set/unset corresponding bits.
The effect of setting a format parameter (format state variables and format flag) is usually permanent. Thus, the parameter setting is in effect until the setting is explicitly changed. The only exception to this rule is the field width. The width is automatically reset to its default value 0 after each input or output operation that uses the field width..
2.1. Function width():
Function width() is used to get/set width variable. Width specifies number of characters or positions to be used during input/output. Even though it can be used during input, it is more meaningful to use it for output purpose.
Syntax: int ios::width (int num=0)
- · Sets the field width to num
- · Returns the previous value of width parameter.
- · Default is 0, which means to use as many characters as necessary.
- · Thewidth setting is not permanent. The value of the width format variableis reset to zero (the default) after its use.
- · For output, num is the minimum width to be used.
o If the specified width is less than the required width, width specification is ignored. Output is not truncated. Output is written using as many characters as needed.
- If the specified width is larger than required, extra positions are padded with fill character. Default fill character is space.
- For input, num is the maximum width to be used.
- While extracting number or string, if invalid character or white space appears before num characters, extraction is terminated ignoring specified width.
For example:
int i=1234; char* str[10]=”Hello”;
cout.width(7);
cout<<i << str;
In the above example, value of the first item i will be displayed using a width of 7 positions and the width parameter will be reset to its default value 0. Now, value of str will be displayed using minimum width 0; i.e 5 positions as necessary. When used with extraction operator, width is maximum to be used. For example,
cin.width(7); cin >> i;
cin.width(7); cin>> str;
Let the input be: 1234GujaratHello
Here, extraction for integer i is independent of width parameter. Characters 1234 are extracted and transformed to binary number to be stored in variable i. Next, 7 characters will be extracted and stored in variable str. Thus specified width will be applied first time to item str and reset to 0.
Remember the following:
- All format parameter variables are different for different streams. Thus, different width variables for cin and cout streams.
- Width parameter is reset after its use.
- Specified width is the minimum to be used for ostream. If the item requires more width, output will be written using as many characters as required; ignoring the specified width.
- · With istream, width is the maximum to be used. Extraction stops at white space or any invalid character.
2.2. Function fill():
Function fill() is used to get/set fill character used as padding character to fill extra positions.Syntax: char ios::fill (char padding = ‘ ’)
- Set the padding character to be used to fill extra positions
- Default: blank; a space character
- Permanent setting, remain in effect until changed
For example:
cout.width(7);
cout.fill (‘*’);
cout << 1234;
cout.width(7);
cout << “Hello”;
Output will be: ***1234**Hello
Note that unlike width, the value of fill format variable is retained.
2.3. Function precision():
This function is used to specify number of significant digits in case of floating point numbers. It also returns the old value of precision.
Syntax: int ios::precision (int num = 6)
- Set the number of significant digits to num for input and output of floating point numbers
- Default precision is of 6 significant digits
- Remains in effect until changed
- When specified precision is shorter than required
- o Performs rounding of digits after decimal point
- o If not enough to accommodate integral part, it uses scientific format
For example:
cout.fill (‘*’);
cout.precision(7);
cout.width(10);
cout << 1234.567<< endl;
cout.precision(8);
cout.width(10);
cout << 1234.567<< endl;
cout.precision(5);
cout.width(10);
cout << 1234.567<< endl;
cout.precision(3);
cout.width(10);
cout << 1234.567<< endl;
Output is:
**1234.567
**1234.567
****1234.6
*1.23e+003
With precision 7 and 8, result remains same as the number have only seven significant digits.Note the output of number 1234.567 with precision 5 and 3.
- With precision 5, there is no problem to accommodate integral part 1234. Digits in fractional part are rounded as only 5 significant digits are specified for output.
- With precision 3, there is a problem to accommodate even integral part 1234. So a number is transformed into scientific format and written using e notation.
Now try the following code.
cout.set(ios::fixed);
cout.precision(2);
cout.width(10);
cout << 1234.567 << endl;
The result is ***1234.57. Here, the precision is 2; shorter than required. But, format flag is set to fixed point notation. Due to this, a number is formatted using fixed point notation instead of scientific notation. Also note that it has considered precision 2 as two significant digits after decimal point in fixed point notation.
2.4. Function setf():
Format flags (bits of format flag variable) can be set using setf() function in two forms as follows.
Syntax:
fmtflags ios::setf (fmtflags flg)
fmtflags ios::setf (fmtflags flg, fmtflags mask)
- Sets format flags as specified in first argument
- Returns old value of format flags
- To specify format flags, precede flag name with the class name ios and the scope-resolution operator (for example, ios::fixed)
- To set multiple flags, use OR (|) operator to combine them (for example, ios::fixed | ios_base::uppercase )
- Two-argument version of setf()
- o Some format flags are grouped, because they are mutually exclusive. For example, the adjustment of the output within an output fieldcan be either left or right or internal. One and only one of these three format flags can be set at a time. To set one of these bits to 1, it requires other two to reset to 0. To make this easier, a two-argument version of setf() can be used. It first resets all the bits of the group fieldspecified in second argument and then set the necessary bit as specified in first argument. This makes it easier to reset the relevant flags before setting a new one. For example, cout.setf(ios::left, ios::adjustfield); clears all the flags dealing with text justification and then sets the left flag for left-justified output.
First argument: Flag to set | Second argument: group to reset all its flags |
left, right, internal | Adjustfield |
dec, oct, hex | Basefield |
scientific, fixed | Floatfield |
2.5. Function unsetf():
Format flags can be reset using unsetf() function.
Syntax:fmtflags ios::unsetf (fmtflags flg)
- Reset flags as specified in argument
- Returns the old values oftheflags
2.6. Function flag():
A complete collection of flags (bits) can be set or get using flag() function. There are two forms of flag() function; with and without parameter.
Syntax:fmtflags ios::flags ()
fmtflags ios::flags (fmtflags value)
- Call to flag() without argument returns the current value of the complete collection of flags. For example, int flg = flags();
- Call to flag() with argument sets entire collection of flags with a specified argument
Note: Use ios::setf() or ios::unsetf() to change one format flag (bit) at a time.
- Formatting using manipulators
Like member functions of ios class, manipulators are also used to perform the task of formatting input/output. Manipulators are special type of non-member functionsthat can be included in an insertion or extraction chain.
The formatting member functions explained above return the format control parameters like width, precision, fill character and format flag. Because they do not return a reference to a stream, they cannot be cascaded with insertion (<<) or extraction (>>) operator. Being member functions of ios class, they require objects of stream class to invoke them.
Manipulators are non-member functions returning a reference to a stream. So they can be used with shift operator in cascaded fashion. Manipulators are non-member functions, so they do not require to be called using dot operator with stream objects. In many examples, we have used manipulator endl with << operatorto have newline or to insert line break.
Following table lists the manipulators equivalent to ios functions.
Manipulator | Equivalent ios member function |
setw() | width() |
setprecision() | precision() |
setfill() | fill() |
setiosflags() | setf() |
resetiosflags() | unsetf() |
To use manipulators, it requires to include <iomanip> in C++ program.
Following code is written using ios function members. See how it can be written in a single statement using manipulators.
cout<<“Numbers left justified in width 10 : ” << endl;
cout.setf(ios_base::left,ios_base::adjustfield);
cout.width(10);
cout<<12;
cout.width(10);
cout<<123<< ‘\n’;
The above C++ statements can be written in a single statement using manipulators as follows:
cout<< “Numbers left justified in width 10 : ” << endl << left << setw(10) << 12 << setw(10) << 123 << ‘\n’ ;
Note the following:
· Use of manipulator name‘left’ instead of manipulator call setiosflags(ios::left) which is equivalent to cout.setf(ios_base::left,ios_base::adjustfield);
· Use of setw(10) instead of cout.width(10);
· Use of manipulators cascaded with << operator
Thus manipulators can be considered as non-member operator overloaded functions with shift operators and returning a reference to a stream. Hence a manipulatorcan be extracted from or inserted into a stream together with otherobjects that have the shift operators defined. Users can also define their own manipulators. (Explained later)
3.1. Shorthand manipulators:
Shorthand manipulators are the short names that can be used to set/reset ios format flags as a replacement to calling function setiosflags() or resetiosflags(). Some such manipulators are provided in pairs to have toggle effect.
Manipulator | i/o | Effect | equivalent to |
left | o | Left-align, padding with fill character | ios::setf(ios::left) or |
on right | setiosflags(ios::left) | ||
right | Right-align, padding with fill character | ios::setf(ios::right) or | |
on left | setiosflags(ios::right) | ||
internal | padding between sign or base indicator | ios::setf(ios::internal) or | |
and number [- 12.34] | setiosflags(ios::internal) | ||
dec | i,o | integer to decimal form | ios::setf(ios::dec) or |
setiosflags(ios::dec) | |||
oct | integer to octal form | ios::setf(ios::oct) or | |
setiosflags(ios::oct) | |||
hex | integer to hexadecimal form | ios::setf(ios::hex) or | |
setiosflags(ios::hex) | |||
fixed | o | Floating point in fixed point notation | ios::setf(ios::fixed) or |
[123.45] | setiosflags(ios::fixed) | ||
scientific | Floating point in scientific notation | ios::setf(ios::scientific) or | |
[1.2345E2] | setiosflags(ios:: scientific) | ||
skipws | i | Skips leading white spaces | ios::setf(ios::skipws) or |
setiosflags(ios:: skipws) | |||
noskipws | i | Do not skip leading white spaces | ios::unsetf(ios::skipws) or |
resetiosflags(ios:: skipws) | |||
boolalpha | i,o | bool values converted to string “true” or | ios::setf(ios::boolalpha) or |
“false” | setiosflags(ios:: boolalpha) | ||
noboolalpha | i,o | bool values not converted to string | ios::unsetf(ios::boolalpha) or |
“true” or “false” | resetiosflags(ios:: boolalpha) | ||
showpos | o | Generate + sign before non-negative | ios::setf(ios::showpos) or |
numbers | setiosflags(ios:: showpos) | ||
nohowpos | o | Do not generate + sign before non- | ios::unsetf(ios::showpos) or |
negative numbers | resetiosflags(ios:: showpos) | ||
showpoint | o | Always generate a decimal point in | ios::setf(ios::showpoint) or |
floating point o/p [123.00] | setiosflags(ios:: showpoint) | ||
noshowpoint | o | Do not generate a decimal point in | ios::unsetf(ios::showpoint) or |
floating point o/p [123] | resetiosflags(ios:: showpoint) | ||
showbase | o | Generate prefix indicating base of an | ios::setf(ios::showbase) or |
integer (0 for octal, 0x for hex) | setiosflags(ios:: showbase) |
noshowbase | o | Do not generate base indicator for an | ios::unsetf(ios::showbase) or |
integer | resetiosflags(ios:: showbase) | ||
uppercase | o | Use uppercase X, E, and hex output | ios::setf(ios::uppercase) or |
letters (ABCDEF) | setiosflags(ios:: uppercase) | ||
nouppercase | o | Use lowercase x, e, and hex output | ios::unsetf(ios::uppercase) or |
letters (abcdef) | resetiosflags(ios:: uppercase) | ||
unitbuf | o | Flush o/p stream after each formatting | ios::setf(ios::unitbuf) or |
operation | setiosflags(ios:: unitbuf) | ||
nounitbuf | o | Do not flush o/p stream after each | ios::unsetf(ios::unitbuf) or |
formatting operation | resetiosflags(ios:: unitbuf) | ||
ws | i | Skip any white space stored in stream. | |
ends | o | Inserts end of string character | |
endl | o | Inserts new line character and flushes | |
output buffer | |||
flush | o | Flushes output buffer | flush() |
3.2. User-defined manipulators
User can define manipulators as per need. For example, define manipulator km to print KiloMeter, define manipulator prhead to print header in a report, define manipulator dash to print dash line etc.The code structure for user-defined manipulator is as follows:
ostream &<manipulator_name> (ostream &<parameter_name)
{
- // code for formatting … return <parameter_name>;}
In the above structure, use istream& in place of ostream& for defining input manipulator.For example, define manipulator km to print KiloMeter as follows:
ostream& km (ostream & pout) { pout << “ KiloMeter” ; return pout;}
Using cout << 200 << km; will output 200 KiloMeter
Another example, define manipulator to print dashline as follows:
ostream & dash (ostream & pout)
{
pout << setw(80) << left << setfill(‘-‘) << ” ” << endl;
pout << setfill(‘ ‘); reset back to space character
return pout;
}
Now using cout << dash; will print a line with 80 dash (-) characters.
Consider one more example. Suppose the numbers are to be formatted to be in fixed point notation with a precision of two significant digits after decimal point and to be aligned on right, then it requires three format settings to be used as
cout << setprecision(2) << fixed << right;
User can define manipulator named fixed2 as follows to perform above task:
ostream & fixed2 (ostream & pout)
{
pout <<setprecision(2) << fixed << right;
return pout;
}
Using cout << setw(8) << fixed2 << 123.456; will print 123.46 using fixed2 manipulator.
3.3. Difference between formatting using ios function and manipulator:Using ios functions
Functions are members of ios class Require only <iostream> file to be included Return the previous status of format parameters like width, precision, fill character and format flags Used as a standalone statement, ex. cout.width(10); cout.fill(‘*’); For some manipulators, there is no equivalent function available, for example, endl No shorthand names to use Not possible to define user-defined member functions in ios class, one may create another class inheriting from ios and add user-defined functions Function calls always requires use of (), example:
int w = width();
Need to use setf() and unsetf() with same format flag to have toggle effect
4. The State of Streams
Using manipulatorsManipulators are non-member functions Require <iomanip> file to be included additionally Does not return previous status of format parameters, Return a reference to stream Can be cascaded with shift operator, ex. cout << setw(10) << setfill(‘*’); Manipulators available corresponding to all ios functions Can use shorthand names User-defines manipulators can be easily created Manipulators without argument can be called without (), example: left, hex, endl Paired manipulators with toggle effect, Ex.boolalpha, noboolalphaEach stream has an error state that identifies whether an I/O operation was successful or not. If unsuccessful, it shows thereason for the failure. The state of a stream is determined by the settings of a number of flags. These error-status flagsare enum member constants of type iostate defined in the base class ios_base.
Error-Status Flags are as follows: | |||
Name of the flag | Meaning | ||
goodbit | No errors, not flags set, value 0 | ||
eofbit | Encountered end of file while input | ||
Error due to an attempt to read past end of | |||
input sequence | |||
failbit | Operation failed, may be user error or | ||
premature EOF, but the stream is ok. | |||
Example: An input failed to read expected | |||
character ( a number is to be read, but next | |||
character is a letter) , or an output failed to | |||
generate desired character | |||
badbit | If stream has somehow become corrupted or | ||
data is lost |
Flag eofbit is set when it is attempted to read past end of input sequence. Consider following two cases:
1. Assume extraction of characters from input stream. Remember that when the lastcharacter is read, the stream is still in good state; eofbit is not yetset. Any subsequent extraction, however, will be an attempt toread past the end of the input sequence. Thus, eofbit will be set.
2. Assume extraction of an integer or astring.Here, the input operators read characters until they find a separator, or hit the end of the input sequence. If the input contains the sequence 912749<eof> and an integer is extracted, eofbit will be set.Flag failbit is set as the result of a read (or write)operation that fails. For example, when extracting an integer, ifthe input sequence contains only white spaces, then the extractionof an integer will fail and the failbit will be set. Let us consider above two cases:
1. Assume extraction of characters from input stream. After reading the last available character, the extraction not onlyreads past the end of the input sequence; it also fails to extractthe requested character. Hence, both failbit and eofbit are set.
2. Assume extraction of integers from input stream containing 912749<eof>. Here, although the end of the input sequence willbe reached by extracting the integer, the input operation doesnot fail. The desired integer will indeed be read. Hence, in thissituation, only the eofbit will be set.There are othersituations that can trigger failure. For example, file streams setfailbit if the associated file cannot be opened.
Flag badbit indicates problems with the underlyingstream buffer. There might be memory shortage while creating stream buffer itself, or code conversion may fail, or an unrecoverable readfrom (write to) external device occurs. Such failures indicate loss of integrity.Generally, badbit indicates an errorsituation that is likely to be unrecoverable, whereas failbitindicates a situation that might be recoverable on retrying the failedoperation. The flag eofbit just indicates that the end of the inputsequence was reached.
To detect stream errors, there are two possibilities:
1. Handle an exception raisedonce an error occurs in any input or output operation
2. Check the stream state after each input oroutput operation by calling various boolean returning member functions
Following table shows boolean returning stream member functions for error checking:
ios member function | Effect | |
operator ! () | Returns true when operation has failed, | |
Ex. if (!cout) { // error } | ||
fail() | Same as operator !(), Returns true if failbit or badbit is set | |
operator void * () | Returns false if fail() and true otherwise, | |
Ex. if (cout) {//no error } | ||
good() | Returns true if no error flag is set, i.e. goodbit is set | |
eof() | Returns true if eofbit is set | |
bad() | Returns true if badbit is set | |
iostate rdstate() | Returns enum value of stream state | |
clear() | Clears all flags, set state as good | |
clear (iostate state) | Set the stream state to the argument state | |
#include <iostream> | ||
int main() | ||
{ | ||
int x; | ||
cout << “Enter an integer: “; |
cin >> x;
ios::iostate flags = cin.rdstate(); //get stream state
if (flags & ios::failbit) // if cin.fail()
cout << “failbit set.” << endl;
else
cout << “failbit not set.” << endl;
if (flags & ios::badbit) | // if cin.bad() |
cout << “badbit set.” << endl; | |
else | |
cout << “badbit not set.” << endl; | |
if (flags & ios::eofbit) | // if eof() |
cout << “eofbit set.” << endl;
else
cout << “eofbit not set.” << endl;
// test the bits directly: if (cin.good())
cout << “Stream state is good.” << endl; else
cout << “Stream state is not good.” << endl; if (cin.fail())
cout << “Are you sure you entered an integer?” << endl; else
cout << “You entered: ” << x << endl;
}
Remember that once the failbit is set while performing input/output, it remains in effect. To reset all bits of error-status flag, one should use clear() function.
Summary
- User specified formattingallows alignment, decimal-point alignment, width specification etc.
- Formatting is controlled using state variables (for width, fill character and precision) and format flag.
- The bits of formatting flag acts as on/off switches. Different bits are used to specify alignment, integer number representation, floating point representation, forced decimal point, showing + sign before number etc.
- The bits of formatting flag and the values of format state variables can be set/reset or get using member functions of ios class and also by using manipulators.·
- Using member functions of ios class
- Values of state variables can be set/get using width(), fill() and precision().
- The bits of formatting flag can be set/reset using setf(), unsetf() and flag().
- Function setf() and unsetf() can be used to set/reset specific bits of formatting flag; whereas function flag() can be used to set/get all bits of formatting flag at a time.
- The effect of setting a format is permanent except in case of the field width. The width is automatically reset to its default value 0 after each use.
· Width parameter
- It specifies the minimum width to be used. If an item requires more width, the specified width argument is ignored.
- Default width is zero.
- While reading numbers, it does not use width parameter. Extraction stops at white space or any invalid character.
- Fillparameter specifies the character to be used as padding character to fill extra positions. Default fill character is space.
- Precision parameter
- It specifies the number of significant digits in case of floating point numbers.
- Default precision is 6.
- When specified precision is not enough to accommodate number of digits after decimal point, the value is rounded
- When specified precision is not enough to accommodate integral portion of a number, it uses scientific format.
- Formatting using manipulators
- o Manipulators setw(), setfill() and setprecision() are used to set the values of format state variables; whereas setiosflags(), resetiosflags() are used to set and reset formatting flags.
- o Advantages
- Can be used with shift operator in cascaded fashion
- Do not require to be called using dot operator with stream objects
- Can be defined by users
- Error-status falg
- o Each stream has an error state that identifies whether an I/O operation was successful or not.
- o Some of the error-status flags are goodbit, badbit, failbit, eofbit.
- o Status bits can be tested using stream member functions like good(), bad(), fail(), eof().
- Once the error bit is set, it remains in effect. Function clear() should be used to clear/reset all bits of error-status flags.
Additional References
1) Stanley Lippmann, “C++ Primer”, Pearson Education.
2) Bjarne Stroustrup, “The C++ Programming Language”, Pearson Education.
3) Scott Mayer, “Effective C++”, Addison Wesley.
4) Bhushan Trivedi , Programming with ANSI C++, 2/e , Oxford University Press.
5) Yashavant P. Kanetkar “Let Us C++” , Bpb Publications.
6) Abhiram G. Ranade, “An Introduction to Programming through C++” , McGraw Hill
7) Ellis and B. Stroustrup “Annotated C++ Reference Manual”, http://www.stroustrup.com/arm.html
8) Herbert Schildt, “Complete Reference C++”, McGraw Hill Publications.
9) Ashok Kamthane, “Object Oriented Programming with ANSI and Turbo C++”, Pearson Education
10) E Balaguruswami, “Object Oriented Programming With C++”, Tata McGraw Hill
11) “C++ FAQs”, Pearson Education.