C++ stringstreams with std::hex - c++

I am looking into code at work. I am having following code. In following code what is the meaning of the last statement?
bOptMask = true;
std::string strMask;
strMask.append(optarg);
std::stringstream(strMask) >> std::hex >> iMask >> std::dec;
In addition to the above question: I have string input and I need to know how to convert it to an integer using C++ streams as above instead of atoi().
The problem I am facing is if I give input
strOutput.append(optarg);
cout << "Received option for optarg is " << optarg << endl;
std::stringstream(strOutput) >> m_ivalue ;
cout << "Received option for value is " << m_ivalue << endl;
For the above code, if I am running with argument "a" I am having an output with first line as "a" and a second line output as 0. I am not sure why, can any one explain?

The last statement creates a temporary stringstream and then uses it to parse the string as hexadecimal format into iMask.
There are flaws with it though, as there is no way to check that the streaming succeeded, and the last stream achieves nothing as you are dealing with a temporary.
Better would be to create the stringstream as a non-temporary, ideally using istringstream as you are only using it to parse string to int, and then checking whether the conversion succeeds.
std::istringstream iss( strMask );
iss >> std::hex;
if(!( iss >> iMask ))
{
// handle the error
}
You only need to set the mode back to decimal if your stringstream is now about to parse a decimal integer. If it is going to parse more hex ones you can just read those in too, eg if you have a bunch of them from a file.
How you handle errors is up to you.
std::hex and std::dec are part of the <iomanip> part of streams that indicate the way text should be formatted. hex means "hexadecimal" and dec means "decimal". The default is to use decimal for integers and hexadecimal for pointers. For reasons unknown to me there is no such thing as a hex representation for printing float or double, i.e. no "hexadecimal point" although C99 sort-of supports it.

The code takes the string optarg and, treating it as hex, converts it to an integer and stores it in iMask.
If you remove the std::hex modifier you can parse the input as decimal. However, I usually use boost's lexical_cast for this. For example:
int iMask = boost::lexical_cast< int >( strMask );

This code uses manipulators to set the stream to expect integers to be read in base 16 (hexadecimal, using the digits 0123456789ABCDEF), then extracts a hexadecimal number from the string, storing it in iMask, and uses another manipulator to set the string stream back to the default of expecting integers to be written in decimal form.

Related

C++ Why diff EOF checks recommended for text vs numeric?

My textbook recommends using the member accessor method iStreamVar.eof() when dealing with textual data and while (iStreamVar) when dealing with numeric data.
Can someone please explain why it would matter?
Quote from book:
Using the function eof to determine the end-of-file status works best if the input is text. The earlier method of determining the end-of-file status works best if the input consists of numeric data.
That is the only thing mentioned on the topic. After this, it just explains how the process works.
Which method you use for determining the end of data depends on how you use it. My guess is, both methods which your textbook mentions are used wrong, so they fail in different situations. That's why it recommends using different methods in different situations.
The correct method is not trivial, and it depends on how important error resilience is for you.
If you want to read a space-delimited stream with numbers in it, and you are sure the file contains no errors, the code is simplest:
int value;
while (iStreamVar >> value)
{
...
}
Note that it's not any of the two original options.
If your file contains space-delimited textual data, and you are sure there are no errors, use the same code (but declare the temporary variable as string instead of int).
If you want to detect and recover from errors, use more elaborate code. But I cannot recommend you any specific code structure - it depends on what exactly you want to do in case of errors. Also:
Are text records delimited by space or newline?
What if the input text-file contains an empty line?
Numbers - floating-point or not?
Numbers - if there is a stray character like a among number data, what to do?
So there is no single correct recipe for doing proper input with error resilience.
Unless there is something significant in the context that isn't shown in the question, that quote is nonsense.
The way to read from a file and check for success is to read from the file:
int data;
if (std::cin >> data)
std::cout << "read succeeded, value is " << data << '\n';
std::string data;
if (std::cin >> data)
std::cout << "read succeeded, value is " << data << '\n';
std::string data;
if (std::getline(std::cin, data)
std::cout << "read succeeded, value is " << data << '\n';
If an attempted read fails you can call .eof() to find out whether the failure was because the input was at the end of the file. Contrary to what some beginners expect (and what some languages do), if .eof() returns false it does not mean that there is data remaining in the input stream. The stream might be at the end of the file after a successful read consumed the remaining input. .eof() will return false, but the next attempted read will fail, and after that, .eof() will return true.
std::stringstream input("1234");
int data;
input >> data; // succeeds
std::cout << input.eof() << '\n'; // outputs 0, no failure
input >> data; // fails, no more input
std::cout << input.eof() << '\n'; // outputs 1, failed because at end of file

String stream output compare

I want to compare output of stringstream with some string.
Problem is when I use fill and width on stringstream I cant compare resulting string with preloaded string.
std::stringstream sstr;
sstr.fill(' ');
sstr.width(4);
sstr << 4 << std::endl;
if(" 4" == sstr.str()){
std::cout << "Equal" << std::endl;
}
It's not equal. My educated guess would be that width somehow use some kind of flag or other kind of indicator to replace bunch of spaces in string. But I am not sure and didn't find anything useful on google. Does anyone know why I cannot compare that (sstream.str() and targeted string)?
Goal is to test what will stringstream (which is heart of my component) print on console.
You also inserted a std::endl into the string. That's going to add a newline character to the string.
Remove the std::endl from your output.

Insert values into a string without using sprintf or to_string

Currently I only know of two methods to insert values into a C++ string or C string.
The first method I know of is to use std::sprintf() and a C-string buffer (char array).
The second method is to use something like "value of i: " + to_string(value) + "\n".
However, the first one needs the creation of a buffer, which leads to more code if you just want to pass a string to a function. The second one produces long lines of code, where a string gets interrupted every time a value is inserted, which makes the code harder to read.
From Python I know the format() function, which is used like this:
"Value of i: {}\n".format(i)
The braces are replaced by the value in format, and further .format()'s can be appended.
I really like Python's approach on this, because the string stays readable, and no extra buffer needs to be created. Is there any similar way of doing this in C++?
Idiomatic way of formatting data in C++ is with output streams (std::ostream reference). If you want the formatted output to end up in a std::string, use an output string stream:
ostringstream res;
res << "Value of i: " << i << "\n";
Use str() member function to harvest the resultant string:
std::string s = res.str();
This matches the approach of formatting data for output:
cout << "Value of i: " << i << "\n";

How to move through each line in getline()

Whenever I run my code, I get the first line pulled out of the file, but only the first. Is there something I am missing? I ran into the issue when I implemented stringstream to try and more easily read in the lines of hex from the file and more quickly convert between a string to a hex value. It read in each line accordingly before, but now it is not. Am I missing something in the understanding of how getline() works?
ss is stringstream, fileIn is the file, hexInput is a string, memory[] is an array of short int, instruction is a short int, opCounter is an int...
string hexInput;
stringstream ss;
short int instruction;
ifstream fileIn ("proj1.txt");
if (fileIn.is_open())
{
while ( getline(fileIn, hexInput) )
{
ss << hex << hexInput;
ss >> instruction;
memory[opCounter] = instruction;
cout << hex << memory[opCounter] << '\t';
cout << opCounter << '\n';
ss.str("");
opCounter++;
}
fileIn.close();
}
else cout << "Unable to open file";
Above is the entire function (which was working before using stringstream) and below are the contents of the file.
4000
0033
0132
2033
4321
2137
D036
A00F
B003
C00C
3217
6217
E044
FFFF
6016
1013
FFFF
0
0
0
0
1
2
3
4
5
There are 26 lines and the last opCounter output says "19" in hex which makes me assume the file is being read line-by-line, but the stringstream never updated. This is my first C++ program and am new to a few of these features I am trying to implement.
Thanks for any help...
Your stringstream is created correctly from the first line. After outputting the number into instruction it will be eof though (you can check this with ss.eof()) because there is no data after the first number inside the stringstream.
replace ss.str(""); (which you don't need) by ss.clear(); which will reset the eof flag. Inputting the new line and reading from the stream will then work as expected.
Of course there is absolutely no need for a stringstream in the first place.
while ( fileIn.good() ) {
fileIn >> hex >> instruction;
[...]
}
works fine. It will read short ints in hexadecimal representation until one line cannot be interpreted as such. (Which incidentally is line 7 because D036 is too large to fit inside a short int - admittedly that is different from your current behaviour, but did you really want a silent failure? very useful at this point are again fileIn.eof() to check whether the read failed due to the stream being at the end of the file and fileIn.clear() to reset other fail-bits)
As requested:
The loop is commonly abbreviated as
while ( fileIn >> hex >> instruction ) {
[...]
}
but note, that if you want to check why the read failed, and continue if it was not an eof, the aforementioned loop is more suited to the task.

Convert string to int and get the number of characters consumed in C++ with stringstream

I am new to C++ (coming from a C# background) and am trying to learn how to convert a string to an int.
I got it working by using a stringstream and outputting it into a double, like so:
const char* inputIndex = "5+2";
double number = 0;
stringstream ss(inputIndex);
ss >> number;
// number = 5
This works great. The problem I'm having is that the strings I'm parsing start with a number, but may have other, not digit characters after the digits (e.g. "5+2", "9-(3+2)", etc). The stringstream parses the digits at the beginning and stops when it encounters a non-digit, like I need it to.
The problem comes when I want to know how many characters were used to parse into the number. For example, if I parse 25+2, I want to know that two characters were used to parse 25, so that I can advance the string pointer.
So far, I got it working by clearing the stringstream, inputting the parsed number back into it, and reading the length of the resulting string:
ss.str("");
ss << number;
inputIndex += ss.str().length();
While this does work, it seems really hacky to me (though that might just be because I'm coming from something like C#), and I have a feeling that might cause a memory leak because the str() creates a copy of the string.
Is there any other way to do this, or should I stick with what I have?
Thanks.
You can use std::stringstream::tellg() to find out the current get position in the input stream. Store this value in a variable before you extract from the stream. Then get the position again after you extract from the stream. The difference between these two values is the number of characters extracted.
double x = 3435;
std::stringstream ss;
ss << x;
double y;
std::streampos pos = ss.tellg();
ss >> y;
std::cout << (ss.tellg() - pos) << " characters extracted" << std::endl;
The solution above using tellg() will fail on modern compilers (such as gcc-4.6).
The reason for this is that tellg() really shows the position of the cursor, which is now out of scope. See eg "file stream tellg/tellp and gcc-4.6 is this a bug?"
Therefore you need to also test for eof() (meaning the entire input was consumed).