Reading numbers from strings using streams

The cin object, an instance of the istream class (in the <istream> library), can input characters from the console and convert them to the numeric form you specify. The ifstream class (in the <ifstream> library) will also allow you to input characters from a file and convert them to numeric form. As with outputting streams, you can use the stream classes with a string buffer so that you can convert from a string object to a numeric value.

The basic_istringstream class (in the <sstream> library) is derived from the basic_istream class, so you can create stream objects and extract items (numbers and strings) from these objects. The class provides this stream interface on a string object (the typedefs keyword istringstream is based on a string and wistringstream is based on a wstring). When you construct objects of this class you initialize the object with a string containing a number and then you use the >> operator to extract objects for the fundamental built-in types, just as you would extract those items from the console using cin.

It is important to reiterate that the extraction operators treat whitespaces as the separators between items in a stream, and hence they will ignore all leading whitespaces, read the non-whitespaces characters up to the next whitespaces and attempt to convert this substring into the appropriate type as follows:

    istringstream ss("-1.0e-6"); 
double d;
ss >> d;

This will initialize the d variable with the value of -1e-6. As with cin, you have to know the format of the item in the stream; so if, instead of extracting a double from the string in the preceding example, you try to extract an integer, the object will stop extracting characters when it comes to the decimal point. If some of the string is not converted, you can extract the rest into a string object:

    istringstream ss("-1.0e-6"); 
int i;
ss >> i;
string str;
ss >> str;
cout << "extracted " << i << " remainder " << str << "n";

This will print the following at the console:

    extracted -1 remainder .0e-6

If you have more than one number in the string you can extract these with several calls to the >> operator. The stream also supports some manipulators. For example, if the number in the string is in hex format you can inform the stream that this is the case using the hex manipulator as follows:

    istringstream ss("0xff"); 
int i;
ss >> hex;
ss >> i;

This says that the number in the string is in hexadecimal format and the variable i will be initialized with a value of 255. If the string contains non-numeric values, then the stream object will still try to convert the string to the appropriate format. In the following snippet you can test if such an extraction fails by calling the fail function:

    istringstream ss("Paul was born in 1942"); 
int year;
ss >> year;
if (ss.fail()) cout << "failed to read number" << "n";

If you know that the string contains text, you can extract it into string objects, but bear in mind that whitespace characters are treated as delimiters:

    istringstream ss("Paul was born in 1942"); 
string str;
ss >> str >> str >> str >> str;
int year;
ss >> year;

Here, there are four words before the number, so the code reads a string four times. If you don't know where in the string the number is but you know there is a number in the string, you can move the internal buffer pointer until it points to a digit:

    istringstream ss("Paul was born in 1942"); 
string str;
while (ss.eof() && !(isdigit(ss.peek()))) ss.get();
int year;
ss >> year;
if (!ss.fail()) cout << "the year was " << year << "n";

The peek method returns the character at the current position, but does not move the buffer pointer. This code checks to see if this character is a digit, and if not, the internal buffer pointer is moved by calling the get method. (This code tests the eof method to ensure that there is no attempt to read a character after the end of the buffer.) If you know where the number starts then you can call the seekg method to move the internal buffer pointer to a specified position.

The <istream> library has a manipulator called ws that removes whitespace from a stream. Recall earlier that we said that there is no function to remove whitespace from a string. This is true because the ws manipulator removes whitespace from a stream and not from a string, but since you can use a string as the buffer for a stream it means that you can use this function to remove white space from a string indirectly:

    string str = "  hello  "; 
cout << "|" << str1 << "|n"; // | hello |
istringstream ss(str);
ss >> ws;
string str1;
ss >> str1;
ut << "|" << str1 << "|n"; // |hello|

The ws function essentially iterates through the items in the input stream and returns when a character is not whitespace. If the stream is a file or the console stream then the ws function will read in the characters from those streams; in this case, the buffer is provided by an already-allocated string and so it skips over the whitespaces at the beginning of the string. Note that stream classes treat subsequent whitespaces as being separators between values in the stream, so in this example the stream will read in characters from the buffer until there is a whitespace, and will essentially left-and right-trim the string. However, this is not necessarily what you want. If you have a string with several words padded by whitespace, this code will only provide the first word.

The get_money and get_time manipulators in the <iomanip> library allow you to extract money and time from strings using the money and time facets for a locale:

    tm indpday = {}; 
string str = "4/7/17";
istringstream ss(str);
ss.imbue(locale("french"));
ss >> get_time(&indpday, "%x");
if (!ss.fail())
{
cout.imbue(locale("american"));
cout << put_time(&indpday, "%x") << "n";
}

In the preceding code, the stream is first initialized with a date in the French format (day/month/year) and the date is extracted with get_time using the locale's standard date representation. The date is parsed into a tm structure, which is then printed out in standard date representation for the American locale using put_time. The results is:

    7/4/2017
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset