Inserting and extracting numeric_limits<T>::infinity in a stream - c++

The following program apparently shows an inconsistency when writing and reading on a std::stringstream a double set to "infinity", using std::numeric_limits<double>::infinity.
#include <string>
#include <sstream>
#include <iostream>
#include <limits>
#include <iterator>
int main() {
std::stringstream stream;
double d;
// Part 1
d=4;
stream << d << " ";
d=std::numeric_limits<double>::infinity();
stream << d << " ";
d=5;
stream << d;
stream.seekg(std::ios_base::beg);
std::string s = stream.str();
std::cout << "string : " << s << std::endl;
// Part 2
std::cout << "Extraction of data 1:" << std::endl;
stream.seekp(std::ios_base::beg);
stream >> d;
std::cout << d << std::endl;
stream >> d;
std::cout << d << std::endl;
stream >> d;
std::cout << d << std::endl;
// Part 3
std::cout << "Extraction of data 2:" << std::endl;
std::istringstream stream2(s);
std::istream_iterator<double> iter(stream2);
std::istream_iterator<double> eos;
while (iter != eos)
{
std::cout << (*iter) << std::endl;
iter++;
}
return 0;
}
See it live.
The output is
string : 4 inf 5
Extraction of data 1:
4
0
0
Extraction of data 2:
4
In part 1 a double "infinity" is written to a stringstream and the string extracted from it shows an "inf" corresponding to such an infinity.
In part 2, however, the substring "inf" is apparently extracted to 0. Moreover, the stream appears to be in a bad state, since successive extractions give again 0.
Similarly, in part 3 a istream_iterator is used to extract the doubles from the string. The iterator reaches an end-of-stream before reading "inf".
Obviously, one could easily fix the problem by extracting words instead of double and converting each of them to a "normal" double, or to std::numeric_limits<double>::infinity when a "inf" is encountered. However, this seems like reinventing the wheel, given that the standard library already contains a lot of code to extract data from a stream....
Why is there a difference when inserting and extracting a std::numeric_limits<double>::infinity?
Within the standard library, is there a possibility of extracting a double which could also be infinity, without resorting to write a function that extracts words and convert them to double?
Additional note
According to the c++ reference, std::stod and similar functions already convert "inf" to an infinite expression. Hence, it looks like std::stringstream::operator<< does not use std::stod or similar to convert a piece of string to a double.

Related

C++: strod() and atof() are not returning double as expected

I am trying to make strings into doubles using the values that I obtained from a .txt file.
The doubles I am obtaining have no decimals. I believe that this is because, in the .txt, the decimals of the numbers are separated by a comma instead of a dot. But I don't know how to solve that.
This is a simplification of my code:
#include <iostream>
#include <fstream> // read text file
#include <stdlib.h> // strtod, atof
int main() {
std::ifstream readWindData("winddata.txt");
// check that document has been opened correctly
if (!readWindData.is_open()) {
std::cout << "Wind data could not be opened." << std::endl;
return 1;
}
// skip headers of the table
std::string firstLine;
std::getline(readWindData, firstLine);
int numberOfRows = 0; // variable to count rows of the table
// initialise strings that separate each value
std::string time, string u10st, u40st, u60st, u80st, u100st,
u116st, u160st, dir10st, dir60st, dir100st, timeDecst;
// initialise doubles
double u10, u40, u60, u80, u100, u116, u160, dir10, dir60, dir100, timeDec;
std::string nextLine;
// Read strings and turn it into doubles line by line until end
while (readWindData >> time >> u10st >> u40st >> u60st >> u80st >> u100st
>> u116st >> u160st >> dir10st >> dir60st >> dir100st >> timeDecst) {
// try two different functions to turn strings into doubles:
u10 = strtod(u10st.c_str(), NULL);
u40 = atof(u40st.c_str());
// ensure numbers are displaying all their decimals
std::cout.precision(std::numeric_limits<double>::digits10 + 1);
// see what I am getting
std::cout << time << " " << u10st << " " << u10 << " " << u40 << "\n";
std::getline(readWindData, nextLine); // this line skips some crap on the side of some rows
numberOfRows++; // counts rows
}
std::cout << "Number of rows = " << numberOfRows << "\n";
readWindData.close();
return 0;
}
these are three lines of the file:
time (hour) u10(m/s)u40(m/s)u60 (m/s)u80(m/s)u100(m/s)u116(Um/s)u160(m/s)dir10 dir60 dir100 time decimal hours
00:00 4,25636 7,18414 8,56345 9,75567 10,9667 12,1298 13,8083 110,616 131,652 141,809 0 midnight
00:10 4,54607 7,40763 8,62832 9,91782 11,2024 12,2694 14,1229 114,551 133,624 142,565 0,166666667
And these are those lines outputted with the above code:
(reminder, I std::cout time (string), u10st (string), u10 (double), u40 (double)).
00:00 4,25636 4 7
00:10 4,54607 4 7
Any ideas on how to read that 4,25636 string into a double 4.25636? The file is too long to modify.
To avoid messing around with the global locale you can just replace , with . before calling strtod()
std::replace(u10st.begin(), u10st.end(), ',', '.');
u10 = strtod(u10st.c_str(), nullptr);
But in the program shown above you can also read from ifstream directly into double using operator >>, if you use a locale where comma is a decimal separator.
readWindData.imbue(std::locale("de_DE.UTF-8")); // or fr, nl, ru, etc.
double u10, u40, u60, u80, u100, u116, u160, dir10, dir60, dir100, timeDec;
while (readWindData >> time >> u10 >> u40 >> u60 >> u80 >> u100
>> u116 >> u160 >> dir10 >> dir60 >> dir100 >> timeDec) {
Live demo
The floating point numbers are using comma decimal separators, and you are expecting periods.
This is an indication that the data was serialized with a different locale than yours.
To address this, set your locale before parsing the numbers (and restore afterwards).
For example, here is some code that parses the number "12,34" with a default period separator, and then we set the locale to Denmark and try again:
const char* number = "12,34";
double parsed_number = 0;
parsed_number = std::strtod(number, nullptr);
std::cout << "parsed number in default locale: " << parsed_number << std::endl;
std::cout << "Setting locale to Denmark (comma decimal delimiter)" << std::endl;
std::locale::global(std::locale("en_DK.utf8"));
parsed_number = std::strtod(number, nullptr);
std::cout << "parsed number in Denmark locale: " << parsed_number << std::endl;
//restore default locale
std::locale::global(std::locale(""));
Output:
parsed number in default locale: 12
Setting locale to Denmark (comma decimal delimiter)
parsed number in Denmark locale: 12.34
Live Demo
Ask around to see who serialized this data, and get the correct locale.
You can find available locales in *nix systems with locale -a
On Windows it appears to be a little more difficult

removing namespace std specifically sprintf in a denary to hex C++ program

I have coded a denary to hex converter and am trying to find a way to remove the sprinf built in function as well as the stoi built in function that i used because as i am using c++ more i am told that using namespace std is bad practice but i cannot think of a way of doing this without breaking my program any help would be appreciated.
also i have left my comments in my code for future Questions should i remove these or leave them in when posting thankyou
#include <iostream>
#include <string>
#pragma warning(disable:4996)
using namespace std;
int DecToHex(int Value) //this is my function
{
char *CharRes = new (char); //crestes the variable CharRes as a new char
//sprintf is part of the standard library
sprintf(CharRes, "%X", Value);
//char res is the place the concerted format will go
//value is the value i want to convert
//%X outputs a hex number
//snprintf covers the formatting of a string
int intResult = stoi(CharRes); //stoi is a function in the library
std::cout << intResult << std::endl; //print int results to the screen
return intResult; //returns int result
}
int main()
{
int a;
std::cout << "Please enter a number" << std::endl;
std::cin >> a; //stores the value of a
DecToHex(a); //runs the function
system("pause"); //pauses the system
return 0; //closes the program
}
Stream in C++ already have built in function for converting format like decimal /hexa etc .. so you can just do this :
int main()
{
int a;
std::cout << "Please enter a number" << std::endl;
std::cin >> a; //stores the value of a
std::cout << std::hex; // Set the formating to hexadecimal
std::cout << a; // Put your variable in the stream
std::cout << std::dec;, // Return the format to decimal. If you want to keep the hexa format you don't havr to do this
std::cout << std::endl; // Append end line and flush the stream
/* This is strictly equivalent to : */
std::cout << std::hex << a << std::dec << std::endl;
system("pause"); //pauses the system
return 0; //closes the program
}
Using std::hex in the stream will print the value in hexa. Using std::dec will print the value in decimal format. Using std::octa will print the value in octal format.
You can call any function from the standard library without using using namespace std simply by prefixing the function with std::.
For example, std::snprintf, std::stoi etc..

Numeric input in C++ with trailing chars

I need to fetch user input from std::cin into a variable of type double. This is in the context of complex numbers, so it often happens to have a number input as 5i or 5.4565i.
Consider the following code in the main() function:
while (true) {
double c;
std::cin >> c;
std::cout << c << "\n\n";
}
Here's what happens:
In: 0.45
Out: 0.45
// OK
In: 5 0.45
Out: 5
0.45
// OK
In: 0.45i
Expected out: 0.45
Acutal out: 0
0
0...
I'm guessing this is because It's not recognizing 0.45i as a double. So how can I correctly fetch the value 0.45 from 0.45i, ignoring the trailing i?
Read a string first and then convert to double,
$ cat ans.cpp
#include <cstdlib>
#include <iostream>
int main()
{
std::string str;
double dbl;
while (std::cin >> str) {
dbl = std::strtod(str.data(), NULL);
std::cout << dbl << std::endl;
}
}
First you read each white space separated string into str. The strtod function will try to get as many as characters to form a floating point literate, including hex float. It returns the double parsed from this part of the string. The second parameter can be a char * pointer, which point to one pass the last character that is parsed. It is useful if you do not want to simply discard the trailing characters. It is ignored if it is null.
You can test the state of the input string. If input has failed, just get the offending token in a string and proceed. For example:
double d;
for(;;) {
std::string dummy;
std::cout << "Input :";
std::cin >> d;
if (std::cin.fail()) { // was input numeric?
std::cin.clear();
std::cin >> dummy;
if (dummy == "END") break; // out of the infinite loop...
std::cout << "Non numeric: >" << dummy << "<" << std::endl;
}
else {
std::cout << "Numeric: " << d << std::endl;
}
}
Try reading std::string and then parsing it manually.
One way could be you take input as a string and then analyse it character by character using a for loop. And then convert it into the double while ignoring the i.You could divide the string into three parts i.e integer part, decimal part and i.
And for separating these you could use conditions like if(c[i]=='.') and if(c[i]=='i').

How to force a preceding 0 to an int (without actually outputting it)

So I'm trying to force a preceding 0 to an int so it can be processed later on. Now, all the tutorials i've seen on SO, or any other website, all use something similar to this:
cout << setfill('0') << setw(2) << x ;
Whilst this is great, i can only seem to get it to work with cout, however, I don't want to output my text, i just want the number padded, for later use.
So far, this is my code..
#include <iostream>
#include <string>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <sstream>
/*
using std::string;
using std::cout;
using std::setprecision;
using std::fixed;
using std::scientific;
using std::cin;
using std::vector;
*/
using namespace std;
void split(const string &str, vector<string> &splits, size_t length = 1)
{
size_t pos = 0;
splits.clear(); // assure vector is empty
while(pos < str.length()) // while not at the end
{
splits.push_back(str.substr(pos, length)); // append the substring
pos += length; // and goto next block
}
}
int main()
{
int int_hour;
vector<string> vec_hour;
vector<int> vec_temp;
cout << "Enter Hour: ";
cin >> int_hour;
stringstream str_hour;
str_hour << int_hour;
cout << "Hour Digits:" << endl;
split(str_hour.str(), vec_hour, 1);
for(int i = 0; i < vec_hour.size(); i++)
{
int_hour = atoi(vec_hour[i].c_str());
printf( "%02i", int_hour);
cout << "\n";
}
return 0;
}
The idea being to input an int, then cast it to a stringstream to be split into single characters, then back to an integer. However, anything less than the number 10 (<10), I need to be padded with a 0 on the left.
Thanks guys
EDIT:
The code you see above is only a snippet of my main code, this is the bit im trying to make work.
Alot of people are having trouble understanding what i mean. so, here's my idea. Okay, so the entire idea of the project is to take user input (time (hour, minute) day(numeric, month number), etc). Now, i need to break those numbers down into corresponding vectors (vec_minute, vec_hour, etc) and then use the vectors to specify filenames.. so like:
cout << vec_hour[0] << ".png";
cout << vec_hour[1] << ".png";
Now, i know i can use for loops to handle the output of vectors, i just need help breaking down the input into individual characters. Since i ask users to input all numbers as 2 digits, anything under the number 10 (numbers preceding with a 0), wont split into to digits because the program automatically removes its preceding 0 before the number gets passed to the split method (ie. you enter 10, your output will be 10, you enter 0\n9, and your output will be a single digit 9). I cant have this, i need to pad the any number less than 10 with a 0 before it gets passed to the split method, therefore it will return 2 split digits. I cast the integers into stringstreams because thats the best way for splitting data types i found (incase you were wondering).
Hope i explained everything alot better :/
If I understand correctly your question, you can just use those manipulators with a stringstream, for instance:
std::stringstream str_hour;
str_hour << setfill('0') << setw(2) << int_hour;
String streams are output streams, so I/O manipulators affect them the same way they affect the behavior of std::cout.
A complete example:
#include <sstream>
#include <iostream>
#include <iomanip>
int main()
{
std::stringstream ss;
ss << std::setfill('0') << std::setw(2) << 10; // Prints 10
ss << " - ";
ss << std::setfill('0') << std::setw(2) << 5; // Prints 05
std::cout << ss.str();
}
And the corresponding live example.
int and other numeric types store values. Sticking a 0 in front of an integer value does not change the value. It's only when you convert it to a text representation that adding a leading 0 changes what you have, because you've changed the text representation by inserting an additional character.
X-Y Problem, I think
for ( int i = 0; i < POWER_OF_TEN; i++ )
{
vector<int>.push_back(num%10);
num /= 10
}
?
Then reverse the vector if you want
yes i know this is not real code
if you really want characters, vector<char>.push_back(num%10 + '0')?

Is there a TryParse equivalent in C++ (gcc)?

Is there a equivalent of TryParse in C++(gcc) ?
I would like to parse a string which may contain (+31321) and store it as long. I know phone numbers are stored as strings and string matched but for my needs , I would like to store them as long and sometimes they might contain pluses (+). What would parse it in C++?
The trouble with strtoul() and family there is no real way to test for failure.
If it fails to parse then it returns 0 without setting errno (which is only set on overflow).
boost lexical cast
#include <boost/lexical_cast.hpp>
int main()
{
try
{
long x = boost::lexical_cast<long>("+1234");
std::cout << "X is " << x << "\n";
}
catch(...)
{
std::cout << "Failed\n";
}
}
Doing it using streams
int main()
{
try
{
std::stringstream stream("+1234");
long x;
char test;
if ((!(stream >> x)) || (stream >> test))
{
// You should test that the stream into x worked.
// You should also test that there is nothing left in the stream
// Above: if (stream >> test) is good then there was content left after the long
// This is an indication that the value you were parsing is not a number.
throw std::runtime_error("Failed");
}
std::cout << "X is " << x << "\n";
}
catch(...)
{
std::cout << "Failed\n";
}
}
Using scanf:
int main()
{
try
{
char integer[] = "+1234";
long x;
int len;
if (sscanf(integer, "%ld%n", &x, &len) != 1 || (len != strlen(integer)))
{
// Check the scanf worked.
// Also check the scanf() read everything from the string.
// If there was anything left it indicates a failure.
throw std::runtime_error("Failed");
}
std::cout << "X is " << x << "\n";
}
catch(...)
{
std::cout << "Failed\n";
}
}
+31321 can be parsed as a long with the usual stream extraction operators.
#include <iostream>
#include <sstream>
int main()
{
std::istringstream s("+31321");
long n;
s >> n;
std::cout << n << '\n';
}
demo: http://ideone.com/4rmlp
Although parsing an actual phone number (with parentheses, dashes, extensions, etc) may not be as simple.
In fact, before convert the string into a number, the numbers should be "normalized" to a common format. This requires removing all symbols, and replace them with proper representation.
But you must be very care about representing telephone numbers (that are NOT numbers: they are not subjected to regular arithmetic) as string: Number beginning with one or more zeroes are not the same as the ones with the zeroes removed:
00 is the typical replacement for +, but a number without the 00 (or +) in front should be prefixed by 00c where c is the country code.
You need to do some pre-processing to come to a uniform string representation, before converting, otherwise you risk to "alias" different things.
the input extraction operator >> (i hope it's an acceptable name) applies and returns a stream&, that has a bool operator, meaning the extraction has been succesfully attempted. For instance, from the Cubbi answer:
...
std::istringstream s("+31321");
long n;
if (s >> n)
std::cout << n << '\n';
....
This will succed, of course, given the appropriate content of s.
Somewhat different (easier but not type safe) also the scanf family has practical tools available in c++ as well c. You could of course write the example this way:
...
long n;
if (sscanf("+31321", "%d", &n) == 1)
std::cout << n << '\n';
...
A subset of regular expressions make this rather powerful: for instance to match a comma separed multi fields with left space trimming:
if (sscanf("a,b,c", " [^,], [^,], [^,]", a,b,c) == 3) ...