C++ std::from_chars is ignoring expontens <10 - c++

I am trying to convert strings to double with std::from_chars, but I cannot get alignment with strtod when it comes to exponential numbers. The reproducer:
#include <string>
#include <iostream>
#include <charconv>
void xxx(std::string const A){
double x;
std::from_chars(&A[0],&A.back(),x,std::chars_format::scientific);
printf("%s,%.17g\n",A.c_str(),x);
}
void yyy(std::string const A){
printf("%s,%.17g\n",A.c_str(),strtod(&A[0],NULL));
}
int main(){
xxx(std::string("0.9226e-01"));
yyy(std::string("0.9226e-01"));
xxx(std::string("0.9226e-10"));
yyy(std::string("0.9226e-10"));
}
which produces output
0.9226e-01,0.92259999999999998
0.9226e-01,0.092259999999999995
0.9226e-10,0.092259999999999995
0.9226e-10,9.226e-11
I would say that strtod produces the correct results.
Happy to learn that I got it wrong.
Platform: linux
g++ version: 12.2
Thanks and merry christmas

Analyzes the character sequence [first,last) for a pattern described below.
The closing parenthesis means last is excluded. Thus, the actual data that std::from_chars(&A[0], &A.back(), ...) is processing are
"0.9226e-0"
"0.9226e-1"
The correct invocation:
void xxx(std::string const A){
double x;
std::from_chars(A.begin(), A.end(), x,std::chars_format::scientific);
printf("%s,%.17g\n", A.c_str(),x);
}
or
void xxx(std::string const A){
double x;
std::from_chars(&A[0], &A[0] + A.size(), x,std::chars_format::scientific);
printf("%s,%.17g\n", A.c_str(),x);
}

Related

Segmentation error in simple inheritance related code

Shortened code I wrote for learning purposes. Still the way it is, it doesn't work properly.
Removing last line (&&) it works OK, but with it, code doesn't reach line noted as ##, expressing
segmentation error, after the "BazOnly" text displayed.
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
namespace nek{
class Baz{
int num;
std::string str;
public:
Baz(){cout<<"BazOnly"<<endl;}
string setstr(string& val){
//str.assign(val);
num= 7;
}
};
}
namespace drg{
class Deriv: nek::Baz{
public:
Deriv(char ch){cout<<"DerivChar"<<endl;}
};
};
int main(){
nek::Baz b;
string priv{"zik"};
b.setstr(priv);
cout<<"Passed here"<<endl; //##
drg::Deriv dc{'A'}; // &&
}
Compiled with g++ (option std=gnu++11), Ubuntu 16 on Virtual Box.
Question is what could be the reason for such behavior ?
string setstr(string& val){
//str.assign(val);
num= 7;
}
This method is declared as returning a std::string, but nothing actually gets returned from it. This is undefined behavior.
Most modern C++ compilers will warn you about this. If yours' did, this is an example of why you cannot ignore warning messages from your compiler, even if it did successfully compile your code.

program to capitalize all lowercase not working

An assignment wants me to make a function that makes all lowercase characters uppercase.
Here's my code:
main.cpp:
#include <iostream>
#include "Function.h"//Includes function file in main file
using namespace std;
int main(){
char a;
cout<<"Enter some words:";
cin.get(a);//Collects info from user
strcap(a);
cout<<a;
}
function.cpp:
#include <iostream>
#include "Function.h"
using namespace std;
char strcap(char a){
while (a!='\n'){
if (a>='a' && a<='z'){
a-=32;//
}
cin.get(a); //get the next letter
}
}
function.h:
#include <iostream>
char strcap(char a);
While the approach you have taken approximates a standard C approach, you have not provided adequate storage to read more than a single character. You could wrap your cin.get(a); strcap(a); cout << a; in a while loop, that would be an approach that is about a decade out of place in C++. Using std::basic::string provides automatic memory management for your input and std::transform makes it simple to apply a transformation to all elements of a container.
The example for std::transform provides exactly what you need, but it doesn't explain how to split the operation up into a separate header and source file. If after reading the documentation you are still stuck, the you can do something similar to the following.
Your header for function.h as you have it simply needs to provide for the declaration of strcap, e.g.
#include <string>
void strcap (std::string& s);
Your implementation for function.cpp likewise just needs to provide for the definition of strcap:
#include <cctype>
#include <algorithm>
#include "function.h"
void strcap (std::string& s)
{
std::transform (s.begin(), s.end(), s.begin(),
[](unsigned char c) -> unsigned char { return std::toupper(c); });
}
(note: the trailing-return-type "-> unsigned char" can be omitted above and it will be deduced properly)
Your main.cpp would then be:
#include <iostream>
#include "function.h"
int main (void) {
std::string s;
std::cout << "enter string: ";
if (getline (std::cin, s)) {
strcap(s);
std::cout << s << '\n';
}
}
Example Use/Output
Compile as you normally would, but you will require the language standard of at least -std=c++11, and then, e.g.
$ ./main
enter string: My dog has fleas
MY DOG HAS FLEAS
Also note, if you do not want to use std::transform, you can use a range-based-for loop to iterate over each character in your string converting to uppercase as well. Your strcap() function would then be:
void strcap (std::string& s)
{
for (auto& c : s)
c = toupper(c);
}
And if for some reason your compiler doesn't support the range-based for loop, then you can also use basic std::string:iterator to iterate over the string providing the conversion, e.g.
void strcap (std::string& s)
{
for (std::string::iterator it = s.begin(); it != s.end(); it++)
*it = toupper(*it);
}
There are several different approaches you can take.
Look things over and let me know if you have any further questions.
Code::Blocks Compiler Options
Just to make sure we are on the same sheet of paper, you should see:

A strange error when trying to scanf into a global int

Here is the code
#include "stdafx.h"
#include <string>
#include <clocale>
#include <stdio.h>
#include <cstdlib>
using namespace std;
int souls;
void userInput(char situation[20]) {
if (situation == "souls") {
scanf("%i", souls);
printf("%i", souls);
}
}
void main() {
setlocale(LC_CTYPE, "rus");
userInput("souls");
system("pause");
}
It brakes after I input something in my scanf() (trying to change a global int) via the console (int number for example) and drops me into an "unhandled exception"
Why is it so? I am using MS Visual Studio 2005.
In your code
scanf("%i", souls);
should be
scanf("%i", &souls);
^
scanf() needs a pointer to type as the argument to store the scanned value corresponding to the supplied format specifier.
That said, if (situation=="souls") is wrong, too. You cannot compare the contents of strings using the == operator. You need to use strcmp() for that.
Your code has several issues:
You cannot compare C strings this way: if (situation == "souls"): you are comparing the addresses of the char arrays, not their contents. You need to use strcmp (and include <cstring>) for this:
if (!strcmp(situation, "souls"))
The signature void userInput(char situation[20]) is confusing: the size 20 information is ignored and your are actually passing the address of a shorter string literal, this signature would be more appropriate:
void userInput(const char *situation)
You need to pass the address of the output variable to scanf and check the return value: scanf("%i", souls); invokes undefined behavior, it should be changed to:
if (scanf("%i", &souls) == 1) {
/* souls was assigned a value */
} else {
/* scanf failed to parse an integer */
}
The signature for main should not be void main(), it should be either:
int main()
or
int main(int argc, char *argv[])

Read string math-formula into cpp as double from external input-file

I am relatively new to c++ coding and try to write a program to solve differential equations numerically. I use codeBlocks as the compiler for that and work under windows. The numeric solver already works well.
My program contains of some very long formulas which are created by mathematica and converted into cpp-language. Then the formulas are stored in a .txt-file.I can already read the formula as a string, but not use it to calculate things because the program has to interpret the formula as a double-type math and not as a string. The problem here is, that my formula does not contain only numbers, but letters as variables (their value is set in the program) and other mathematical symbols. That is why I think I cannot just use "atof" (http://www.cplusplus.com/reference/cstdlib/atof/?kw=atof) or other conversion functions. (If I am wrong at this point, I would be glad to learn how to use the function for this problem!)
Here is some example code from my little program:
//Program to solve ODEs
#include <iostream>
#include <math.h>
#include <cmath>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <time.h> //to measure the time
#include <stdio.h>
#include <conio.h>
using namespace std;
int main(void)
{
double k1=0;
ifstream file("Formelvu1.txt");//file with the fromula
string line;
stringstream longform;
while(getline(file, line)){ //read the formula and store them
longform << line; //store the string in "longform"
cout << longform;
}
return 0;
for(double t=0; t<10; t++){
k1 = (longform) * t; //simple operation with the formula
}
return 0;
}
This code doesn't work, becuase longform is no double...
longform is a string with something like: ab+pow(t,3)-sin(tb)/x.
I already found several questions related to this topic, but none of them was easy enough for me to understand or the right thing I want to do:
How can I convert string to double in C++?
From what I understand is this guy trying the nearest from what I wish to do:
Evaluate math formula from String using ScriptEngine
But I don't understand the code completely.
If it is useful for my problem: What does this part do?
try{
return (Double)engine.eval(tmp);
}
catch(Exception fexp)
{
}
I also heard about parser which can interpret the xpressions line muparser:
http://muparser.beltoforion.de/mup_eval.html
But I don't know if this would be more than I need...
I appreciate every answer/response and help with this problem.
Thank you!
You have to study carefully what is included in the basic C/C++ language and standard library and what not.
However, if you get a C++ compatible expression from mathematica, then you can let the C++ compiler do its work as in
double myfunc(double a, double b, double c, double t, double x) {
return
#include "Formelvu1.txt"
;
}

String to float conversion and formatting

Currently I have something like this
float a = SomeQString.toFloat(); //QString has 2.37
Now float is 2.3690000031..
What I want is 2.3700000000.. any suggestion on how i could do that ? Also why am i getting 2.369 instead of 2.37?
(Has been asked and explained so many times.) It is not possible to get 2.37 in a float. It is not possible to get 2.37 in a double. It is not possible to get 2.37 in any IEEE-754 style binary floating-point format. 2.37 is not representable precisely in such binary floating-point formats.
Read What Every Computer Scientist Should Know About Floating-Point Arithmetic
One viable way to "obtain" 2.37 is actually to store that 2.369... in a float (which is what you do already) and then round it to 2.37 at the time when you'll need to generate the decimal representation, i.e. at the time when you have to present/output the value to the user.
#include <string>
#include <sstream>
int main(void)
{
std::string QString = "2.37";
std::istringstream StrToFloat(QString );
float floatVar;
StrToFloat >> floatVar;
return 0;
}
If you insist on using Qt, this is the appropriate code for you:
#include <QString>
#include <QTextStream>
#include <QDebug>
using namespace std;
int main()
{
QString floatString = "2.37";
QTextStream floatTextStream(&floatString);
float f;
floatTextStream >> f;
qDebug() << f;
return 0;
}
Run the following command with gcc for instance, and Qt 5 (or something similar if you have a different scenario):
Command: g++ -I/usr/include/qt -I/usr/include/qt/QtCore -lQt5Core -fPIC main.cpp && ./a.out
Output: 2.37
However, You do not need QString for doing this. See the code below which generates the output 2.37 as expected.
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
string floatString = "2.37";
istringstream floatStringStream(floatString);
float f;
floatStringStream >> f;
cout << f;
return 0;
}
Run the following command with gcc for instance (or something similar if you have a different scenario):
Command: g++ main.cpp && ./a.out
Output: 2.37