Convert std::string_view to float - c++

I am trying to convert std::string_view to float without an intermediate conversion to std::string (which will cause extra heap allocation) with a C++20 compiler.
#include <iostream>
#include <charconv>
int main() {
std::string_view s = "123.4";
float x;
std::from_chars(s.data(), s.data() + s.size(), x);
std::cout << x << std::endl;
}
But I am unable to compile this code:
error: no matching function for call to 'from_chars(std::basic_string_view<char>::const_pointer, std::basic_string_view<char>::const_pointer, float&)'
What I am doing wrong?

GCC's C++ standard library implementation first supported std::from_chars for float in GCC 11.1. 10.x won't support it.
Since you're not checking for success, and you know your string is null-terminated, you can use atof() instead, which is similarly unsafe. If you want proper checking for parsing errors, use strtof, which will give you similar information to from_chars as to whether the input matched properly:
#include <iostream>
#include <cstdlib>
int main() {
std::string_view s = "123.4";
char * end;
float x = std::strtof(s.data(), &end);
if (end != s.data() + s.size())
{
std::cout << "Parse error";
}
else
{
std::cout << x << std::endl;
}
}

If and only if you know that your string view is null terminated, you can use this
float x = static_cast<float>(atof(s.data()));

Look into charconv header. For example GCC have next guard in it
#if defined __cpp_lib_to_chars || _GLIBCXX_HAVE_USELOCALE
So it can be not implemented, or your compiler not configured to use at least C++ 17 standard. I.e. no -std=c++20 for GCC and Clang or /std:c++latest for Microsoft VC++ command line options passed to your compiler, or your implementation i.e. port not implementing this functionality and not fully implement a standard.
You always can replace from_chars with strtof c function.
For example:
#include <iostream>
#include <string_view>
#include <system_error>
#include <cmath>
#include <charconv>
#include <cstdlib>
int main(int argc, const char** argv)
{
std::string_view sv("12.345678");
#ifdef __cpp_lib_to_chars
float result = NAN;
auto conv_ret = std::from_chars(sv.data(), (sv.data() + sv.size()), result);
std::error_code ec = std::make_error_code(conv_ret.ec);
#else
char *endp = nullptr;
float result = std::strtof(sv.data(), &endp);
std::error_code ec;
if (errno == ERANGE) {
ec = std::make_error_code(std::errc::result_out_of_range);
}
#endif
if(ec) {
std::cerr << ec.message() << std::endl;
return ec.value();
}
std::cout << "Float: " << result << std::endl;
return 0;
}

error: no matching function for call to 'from_chars(std::basic_string_view<char>::const_pointer, std::basic_string_view<char>::const_pointer, float&)'
Tried following code based on above error:
#if defined(CYGWIN_NT) || defined(AIX71) || defined(SUNOS)
#include <iostream>
using namespace std;
#elif defined(LINUX) || defined(HPUX11)
#include <iostream.h>
#else
#error handle iostream/iostream.h error.
#endif
#include <charconv>
int main()
{
string_view s = "123.4";
// Always better to initialize.
float x = 0.0f;
from_chars(s.data(), s.data() + s.size(), x);
cout << x << endl;
return 0;
}
// Sample compilation:
// echo g++ -Wall 73333331.cpp -D$(uname -s | sed "s/-[0-9].*.[0-9].*-[0-9].*//;") -std=c++20 -o ./a.out
// g++ -Wall 73333331.cpp -DCYGWIN_NT -std=c++20 -o ./a.out
// ./a.out
// 123.4

Related

Can I use a const char* or std::string variable containing grammar as argument to libfmt?

Hopefully this is a silly question. I have the following code:
#include <iostream>
#include <fmt/format.h>
#include <string>
int main(){
double f = 1.23456789;
std::cout << fmt::format( "Hello {:f} how are you?\n", f ) << "\n";
return 0;
}
And this works as expected --Hello 1.234568 how are you?
But if I want to encapsulate the string passed into fmt::format as a variable, I run into a compiler error:
#include <iostream>
#include <fmt/format.h>
#include <string>
int main() {
double f = 1.23456789;
const char* m = "Hello {:f} how are you?\n"; //can't be constexpr, generated at run time
std::cout << fmt::format( m, f ) << "\n";
return 0;
}
However, on MSVC 2022 using #include <format>, this works perfectly...
#include <iostream>
//#include <fmt/format.h>
#include <format>
#include <string>
int main() {
double f = 1.23456789;
const char* m = "Hello {:f} how are you?\n";
std::cout << std::format( m, f ) << "\n";
return 0;
}
Is this possible using libfmt? It appears libfmt wants a constexpr value passed in whereas msvc's <format> evaluates this at runtime. What silly mistake am I making here?
Since libfmt 8.1, you can wrap the format string in fmt::runtime to enable runtime formatting:
#include <iostream>
#include <fmt/format.h>
#include <string>
int main() {
double f = 1.23456789;
const char* m = "Hello {:f} how are you?\n"; //can't be constexpr, generated at run time
std::cout << fmt::format(fmt::runtime(m), f ) << "\n";
return 0;
}
You can use fmt::vformat for run-time string
#include <iostream>
#include <fmt/format.h>
#include <string>
int main() {
double f = 1.23456789;
const char* m = "Hello {:f} how are you?\n"; //can't be constexpr, generated at run time
std::cout << fmt::vformat( m, fmt::make_format_args(f)) << "\n";
return 0;
}
Demo
Is this possible using libfmt? It appears libfmt wants a constexpr
value passed in whereas msvc's evaluates this at runtime.
P2216R3 makes std::format only accept compile-time format string. If you want to use run-time format string you need to use std::vformat. I suspect this is just because MSVC has not implemented P2216R3 yet.

z3 gmp support and type conversion

I have to convert an mpq_t into a z3::expr. The z3 README says: "It is optionally possible to use GMP [...]." How exactly would this look like? I couldn't find anything gmp related in the API documentation and the following does not work:
#include <z3++.h>
#include <gmp.h>
#include <iostream>
int main()
{
z3::context c;
mpq_t gmp_frac;
mpq_init(gmp_frac);
mpq_set_str(gmp_frac, "22/7", 10);
z3::expr z3_frac = c.real_val(gmp_frac);
std::cout << z3_frac << std::endl;
return 0;
}
It is possible to first convert the mpq_t into an char array (see below), but I am not very satisfied with that. Is there a more direct way?
#include <z3++.h>
#include <gmp.h>
#include <iostream>
int main()
{
z3::context c;
mpq_t gmp_frac;
mpq_init(gmp_frac);
mpq_set_str(gmp_frac, "22/7", 10);
char char_frac[mpz_sizeinbase(mpq_numref(gmp_frac), 10)+mpz_sizeinbase(mpq_denref(gmp_frac), 10)+3];
mpq_get_str(char_frac, 10, gmp_frac);
z3::expr z3_frac = c.real_val(char_frac);
std::cout << z3_frac << std::endl;
return 0;
}

Calling function by its name as string [duplicate]

I wonder if there is a simple way to call a function from a string. I know a simple way, using 'if' and 'else'.
int function_1(int i, int j) {
return i*j;
}
int function_2(int i, int j) {
return i/j;
}
...
...
...
int function_N(int i, int j) {
return i+j;
}
int main(int argc, char* argv[]) {
int i = 4, j = 2;
string function = "function_2";
cout << callFunction(i, j, function) << endl;
return 0;
}
This is the basic approach
int callFunction(int i, int j, string function) {
if(function == "function_1") {
return function_1(i, j);
} else if(function == "function_2") {
return function_2(i, j);
} else if(...) {
} ...
...
...
...
return function_1(i, j);
}
Is there something simpler?
/* New Approach */
int callFunction(int i, int j, string function) {
/* I need something simple */
return function(i, j);
}
What you have described is called reflection and C++ doesn't support it. However you might come with some work-around, for example in this very concrete case you might use an std::map that would map names of functions (std::string objects) to function pointers, which in case of functions with the very same prototype could be easier than it might seem:
#include <iostream>
#include <map>
int add(int i, int j) { return i+j; }
int sub(int i, int j) { return i-j; }
typedef int (*FnPtr)(int, int);
int main() {
// initialization:
std::map<std::string, FnPtr> myMap;
myMap["add"] = add;
myMap["sub"] = sub;
// usage:
std::string s("add");
int res = myMap[s](2,3);
std::cout << res;
}
Note that myMap[s](2,3) retrieves the function pointer mapped to string s and invokes this function, passing 2 and 3 to it, making the output of this example to be 5
Using a map of standard string to standard functions.
#include <functional>
#include <map>
#include <string>
#include <iostream>
int add(int x, int y) {return x+y;}
int sub(int x, int y) {return x-y;}
int main()
{
std::map<std::string, std::function<int(int,int)>> funcMap =
{{ "add", add},
{ "sub", sub}
};
std::cout << funcMap["add"](2,3) << "\n";
std::cout << funcMap["sub"](5,2) << "\n";
}
Even better with Lambda:
#include <functional>
#include <map>
#include <string>
#include <iostream>
int main()
{
std::map<std::string, std::function<int(int,int)>> funcMap =
{{ "add", [](int x, int y){return x+y;}},
{ "sub", [](int x, int y){return x-y;}}
};
std::cout << funcMap["add"](2,3) << "\n";
std::cout << funcMap["sub"](5,2) << "\n";
}
You can also put your functions into a shared library. You will load such library dynamically with dlopen() and then just make the calls to the functions with a std::string. Here an example:
hello.cpp
#include <iostream>
extern "C" void hello() {
std::cout << "hello" << '\n';
}
main.cpp
#include <iostream>
#include <dlfcn.h>
int main() {
using std::cout;
using std::cerr;
cout << "C++ dlopen demo\n\n";
// open the library
cout << "Opening hello.so...\n";
void* handle = dlopen("./hello.so", RTLD_LAZY);
if (!handle) {
cerr << "Cannot open library: " << dlerror() << '\n';
return 1;
}
// load the symbol
cout << "Loading symbol hello...\n";
typedef void (*hello_t)();
// reset errors
dlerror();
std::string yourfunc("hello"); // Here is your function
hello_t hello = (hello_t) dlsym(handle, yourfunc.c_str());
const char *dlsym_error = dlerror();
if (dlsym_error) {
cerr << "Cannot load symbol 'hello': " << dlsym_error <<
'\n';
dlclose(handle);
return 1;
}
// use it to do the calculation
cout << "Calling hello...\n";
hello();
// close the library
cout << "Closing library...\n";
dlclose(handle);
}
compilation:
g++ -fPIC -shared hello.cpp -o hello.so
and:
g++ main.cpp -o main -ldl
run:
C++ dlopen demo
Opening hello.so...
Loading symbol hello...
Calling hello...
hello
Closing library...
The example was stolen from here. There you can find more detailed explanation on dlopen() and c++
There is another possibility which hasn't been mentioned yet, which is true reflection.
An option for this is accessing functions exported from an executable or a shared library using operating system functions for resolving names to addresses. This has interesting uses like loading two 'contestant' dlls into an 'umpire' program, so that people can slug it out by having their actual codes fight each other (playing Reversi or Quake, whatever).
Another option is accessing the debug information created by the compiler. Under Windows this can be surprisingly easy for compilers that are compatible, since all the work can be off-loaded to system dlls or free dlls downloadable from Microsoft. Part of the functionality is already contained in the Windows API.
However, that falls more into the category of Systems Programming - regardless of language - and thus it pertains to C++ only insofar as it is the Systems Programming language par excellence.

Lexical cast Partial conversion - Is it possible?

lexical_cast throws an exception in the following case. Is there a way to use lexical_cast and convert the string to integer.
#include <iostream>
#include "boost/lexical_cast.hpp"
#include <string>
int main()
{
std::string src = "124is";
int iNumber = boost::lexical_cast<int>(src);
std::cout << "After conversion " << iNumber << std::endl;
}
I understand, I can use atoi instead of boost::lexical_cast.
If I'm understanding your requirements correctly it seems as though removing the non-numeric elements from the string first before the lexical_cast will solve your problem. The approach I outline here makes use of the isdigit function which will return true if the given char is a digit from 0 to 9.
#include <iostream>
#include "boost/lexical_cast.hpp"
#include <string>
#include <algorithm>
#include <cctype> //for isdigit
struct is_not_digit{
bool operator()(char a) { return !isdigit(a); }
};
int main()
{
std::string src = "124is";
src.erase(std::remove_if(src.begin(),src.end(),is_not_digit()),src.end());
int iNumber = boost::lexical_cast<int>(src);
std::cout << "After conversion " << iNumber << std::endl;
}
The boost/lexical_cast uses stringstream to convert from string to other types,so you must make sure the string can be converted completely! or, it will throw the bad_lexical_cast exception,This is an example:
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
#define ERROR_LEXICAL_CAST 1
int main()
{
using boost::lexical_cast;
int a = 0;
double b = 0.0;
std::string s = "";
int e = 0;
try
{
// ----- string --> int
a = lexical_cast<int>("123");//good
b = lexical_cast<double>("123.12");//good
// -----double to string good
s = lexical_cast<std::string>("123456.7");
// ----- bad
e = lexical_cast<int>("abc");
}
catch(boost::bad_lexical_cast& e)
{
// bad lexical cast: source type value could not be interpreted as target
std::cout << e.what() << std::endl;
return ERROR_LEXICAL_CAST;
}
std::cout << a << std::endl; // cout:123
std::cout << b << std::endl; //cout:123.12
std::cout << s << std::endl; //cout:123456.7
return 0;
}

Decode char UTF8 escapes in Boost Spirit

question asked: Spirit-general list
Hello all,
I'm not sure if my subject is correct, but the testcode will probably show
what I want to achieve.
I'm trying to parse things like:
'%40' to '#'
'%3C' to '<'
I have a minimal testcase below. I don't understand why
this doesn't work. It's probably me making a mistake but I don't see it.
Using:
Compiler: gcc 4.6
Boost: current trunk
I use the following compile line:
g++ -o main -L/usr/src/boost-trunk/stage/lib -I/usr/src/boost-trunk -g -Werror -Wall -std=c++0x -DBOOST_SPIRIT_USE_PHOENIX_V3 main.cpp
#include <iostream>
#include <string>
#define BOOST_SPIRIT_UNICODE
#include <boost/cstdint.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/phoenix/phoenix.hpp>
typedef boost::uint32_t uchar; // Unicode codepoint
namespace qi = boost::spirit::qi;
int main(int argc, char **argv) {
// Input
std::string input = "%3C";
std::string::const_iterator begin = input.begin();
std::string::const_iterator end = input.end();
using qi::xdigit;
using qi::_1;
using qi::_2;
using qi::_val;
qi::rule<std::string::const_iterator, uchar()> pchar =
('%' > xdigit > xdigit) [_val = (_1 << 4) + _2];
std::string result;
bool r = qi::parse(begin, end, pchar, result);
if (r && begin == end) {
std::cout << "Output: " << result << std::endl;
std::cout << "Expected: < (LESS-THAN SIGN)" << std::endl;
} else {
std::cerr << "Error" << std::endl;
return 1;
}
return 0;
}
Regards,
Matthijs Möhlmann
qi::xdigit does not do what you think it does: it returns the raw character (i.e. '0', not 0x00).
You could leverage qi::uint_parser to your advantage, making your parse much simpler as a bonus:
typedef qi::uint_parser<uchar, 16, 2, 2> xuchar;
no need to rely on phoenix (making it work on older versions of Boost)
get both characters in one go (otherwise, you might have needed to add copious casting to prevent integer sign extensions)
Here is a fixed up sample:
#include <iostream>
#include <string>
#define BOOST_SPIRIT_UNICODE
#include <boost/cstdint.hpp>
#include <boost/spirit/include/qi.hpp>
typedef boost::uint32_t uchar; // Unicode codepoint
namespace qi = boost::spirit::qi;
typedef qi::uint_parser<uchar, 16, 2, 2> xuchar;
const static xuchar xuchar_ = xuchar();
int main(int argc, char **argv) {
// Input
std::string input = "%3C";
std::string::const_iterator begin = input.begin();
std::string::const_iterator end = input.end();
qi::rule<std::string::const_iterator, uchar()> pchar = '%' > xuchar_;
uchar result;
bool r = qi::parse(begin, end, pchar, result);
if (r && begin == end) {
std::cout << "Output: " << result << std::endl;
std::cout << "Expected: < (LESS-THAN SIGN)" << std::endl;
} else {
std::cerr << "Error" << std::endl;
return 1;
}
return 0;
}
Output:
Output: 60
Expected: < (LESS-THAN SIGN)
'<' is indeed ASCII 60