Boost spirit parser of Fortran printed doubles - c++

I am using num_list3.cpp from Boost Spirit examples. I am testing the variety of the double types it can parse. I used the following list:
1.2,0.2
.2,5.
1.e+23,.23E4
0e+10
1.3D+3
I noticed that it fails on parsing the last number 1.3D+3.
How could I set D as an exponent prefix of a double?

You can easily do that with Boost.Spirit. You just need to instantiate a real_parser with a custom policy that takes care of the "d|D" prefix. It could be as simple as:
template <typename Type>
struct fortran_policy : qi::real_policies<Type>
{
template <typename Iterator>
static bool parse_exp(Iterator& first, const Iterator& last)
{
if (first == last || (*first != 'e' && *first != 'E' && *first != 'd' && *first != 'D'))
return false;
++first;
return true;
}
};
Then you would simply need to use:
qi::real_parser<double,fortran_policy<double>> double_;
without needing to change anything else(although that semantic action seems rather unnecessary).
Live on ideone

You can't.
Although FORTRAN apparently uses this, it's not widely used in any other context, and is not ISO-standardised scientific notation.

Related

How do I use OR with if statements in regards to strings

I want to do an if statement to compare two strings to see if they match.
So:
if (TypedAnswerOne == CorrectAnswerOne)
The code works if the correct answer is typed EXACTLY as it is in the CorrectAnswerOne string value.
No problems at all.
However ... if the answer is typed slightly different as one word in stead of two words for example then it shows that the answer is wrong.
So I was wondering how do I can I do an "OR" with strings?
So:
if (TypedAnswerOne == CorrectAnswerOne or "dirtballs" or "Dirt Balls" or "dirt balls")
How can I define "or" in CPP with strings?
TY :-)
Many programming languages today (C, C++, Swift, C#, Java, JavaScript, PHP) share C's curly-brace syntax and operator syntax.
The syntax for a short-circuited logical OR is a double-pipe: ||.
The syntax for a non-short-circuited logical OR is a single-pipe: | (this is also used for bitwise OR operations).
Also, use && for a short-circuited logical AND and & for non-short-circuited logical AND or bitwise AND.
^ is XOR (and not to-the-power-of).
C++, like these other languages, does not have a built-in feature to let you compare a single left-hand value with multiple right-hand values, so you need to repeat the left-hand value.
Like so:
if( TypedAnswerOne == "dirtballs" || TypedAnswerOne == "Dirt Balls" || TypedAnswerOne
== "dirt balls" )
C and C++ do not support strings in switch statements unlike Java, C#, Swift and PHP, btw.
BTW, you should use a case-insensitive string comparison instead of defining all possible values yourself.
You have to define the OR between cases, not between strings. So, for example:
if (x == "dirtbag" || x == "dirt bag")
You can have as many ORs as you want, but it starts to get messy. When that happens, you might prefer a switch case:
switch(x) {
case "dirtbag" : ...; // do something
case "dirt bag" : ...; // do something
}
If you're open to using pre-existing libraries and don't want to handle all of the cases (it sounds like there could be a lot!) you could always find one that suits your needs and maybe handles the string before comparing (setting it to lowercase, removing whitespace, etc). Good luck!
If you don't care about upper or lower case, or extra whitespace, then you want to first remove all white space and then compare strings on a case-insensitive basis.
You can remove whitespace like this.
Then case-insensitive string compare like this.
In general, the strategy to solving programming problems is to google it. For example:
Google: "c++ remove whitespace from string"
Google: "c++ string compare case insensitive"
For more than a couple of possible values, I tend to put them in a container and use an algorithm:
#include <algorithm>
#include <iterator>
#include <array>
#include <string>
#include <iostream>
template <typename T, std::size_t N, typename U>
bool includes(const std::array<T, N>& arr, const U& value)
{
return std::find(std::cbegin(arr), std::cend(arr), value) != std::cend(arr);
}
struct in_tag {} in;
template <typename U>
struct in_op_temporary { const U& value; };
template <typename U>
in_op_temporary<U> operator<(const U& lhs, in_tag rhs) { return {lhs}; }
template <typename U, typename T, std::size_t N>
bool operator>(in_op_temporary<U> lhs, const std::array<T, N> rhs)
{
return includes(rhs, lhs.value);
}
int main()
{
const std::array<std::string, 3> answers {
"dirtballs", "Dirt Balls", "dirt balls"
};
if ("Dirt Balls" <in> answers)
std::cout << "success!" << std::endl;
if (not ("DirtBalls" <in> answers))
std::cout << "success!" << std::endl;
}
Live On Coliru
But for this particular problem, I'd suggest finding a more general way of accounting for errors in the string.

c++ If all condition are met

Is there any way to check if all conditions are met?
e.g:
if(num[i] > (*all*)alt[c])
{
}
Instead of doing it this way
if(num[i] > alt[1] && num[i] > alt[2] && num[i] > alt[3])
{
}
Like is there a shorter way?
You could use a suitable auxiliary function which effectively just calls one of the algorithms, e.g.:
if (is_bigger(num[i], alts)) {
// ...
}
where the function is_bigger() just uses std::all_of() with a suitable condition:
template <typename T, typename Sequence>
bool is_bigger(T const& test, Sequence const& alts) {
return std::all_of(alts.begin(), alts.end(),
[&](T const& other){ return test > other; });
}
all_of() is simple an algorithm which applies a predicate to all elements in the sequence delimited by the begin and end iterator (alts.begin() and alts.end()). The other thing in this function is simple a lambda expression creating a corresponding predicate.
Well, you can take the maximum of all alts, and then compare num[i] to it.
Get the maximum element with:
auto max = std::max_element(alt.begin(), alt.end());
For now no, at least without creating additional code (instead of evaluating at compile-time). But if you use 'inline' variables (currently only an early draft - idea of mine), you could write:
auto FuncCheckingMulCond(auto &inline varSrc, auto &inline varTarget, inline size_t nTimes)
{
for(inline size_t i(0); i < nTimes; ++i)
if(!(varSrc > varTarget[i]))
return false;
return true;
}
And so your example will look like this:
if(FuncCheckingMulCond(num[i], alt, 5))
{
}
Inline variables should be such which value is known at compile-time and as 'FuncCheckingMulCond' contain 'inline' parameters it should be evaluated at compile-time too. '&inline' is an inline reference which means that it instead of storing some pointer, all it's instances are replaced with the variable it had bound to. So in theory - the above code should do exactly the thing you wanted, but unfortunately this isn't part of ISO C++ yet.

Comparing a char to chars in a list in C++

Is there a way to compare a char to each element in a list of chars?
char ch;
if(ch == 'a' || ch == 'b' || ch == 'c')
Is there some way to just do
if(ch is one of {a, b, c})
Why would you write lambdas or use a throwaway string object when you can just:
if (strchr("abc", ch))
Use : std::any_of
With C++11 :
std::string str="abc";
if(std::any_of(str.cbegin(), str.cend(),
[ch](const char& x){return x==ch; } ))
{
}
Or use a functor:
struct comp
{
comp(char x) :ch(x){}
bool operator()(const char& x) const
{
return x == ch;
}
char ch;
};
And then,
if(std::any_of(str.cbegin(), str.cend(),comp(ch) ))
{
}
Edit : std::any_of might not be efficient enough, just for sake of C++'s <algorithm> one can try this out too .
You could use std::find. Assuming chars is your character array and you need to find ch.
if(std::find(std::begin(chars), std::end(chars), ch) != std::end(chars))
One way to do it is searching a string, like this:
string abc("abc");
if (abc.find(ch) != string::npos) {
...
}
(This answer really only applies if you don't want to use C++ std lib constructs.)
In your specific case, you should be able to do:
if(ch >= 'a' && ch <= 'c')
I also have employed fall-through switch for this case:
switch(ch)
{
case 'a':
case 'b':
case 'c':
case 'e':
...
break;
}
Some people don't like fall-through switch/case statements, but I think its less error prone than a massive piece of boolean logic and will perform better than using a data structure for this purpose. The compiler is really good with dealing with switch statements.
If you can use variadic template arguments, which were introduced in C++11, then you can do something like this:
template <typename Key, typename Value>
inline bool in(const Key& key, const Value& value) {
return key == value;
}
template <typename Key, typename Value0, typename ...ValueN>
inline bool in(const Key& key, const Value0& value, ValueN &&...args) {
return (key == value ? true : in(key, std::forward<ValueN>(args)...));
}
I use it for strings like this:
if (in(some_string, "base", "os", "io", "coroutine", "debug")) ...
But other types that support comparison (char is one of them) should also work.
Hope it helps. Good Luck!
Just as another option, create a set with the characters, and check if it's contained there;
std::set<char> mySet = {'a','b','c'}; // C++11 initializer list
if(mySet.find('d') != mySet.end()) {
...
}
I'm sort of surprised that nobody suggested find_first_of.
char c('e');
// we can check if c is undesirable
const std::string unwanted("abc");
bool undesirable = (unwanted.find_first_of(c) != std::string::npos);
// OR we can check if c is desirable
const std::string wanted("def");
bool desirable = (wanted.find_first_of(c) != std::string::npos); //..or check if it's desirable.
I use this (maybe I shouldn't? folks?) for ignoring unwanted characters from a string iterator...
/** in and out are string iterators.
* skip over any undesirable characters by matching
* against desirable and looking for npos.
**/
const std::string ok("!+-./0123456789:^ABFIORmn");
while (ok.find_first_of(*in) == string::npos && in < out) {
in++;
}
A nice benefit of this is that by putting more frequent characters at the front of the string, there's a little bit of saving in time.

D language: Are function signatures with constraints considered equal if they refer to the type directly or the parameter names?

Given the below function signatures (and their constraints), would they be considered the same? Both pass my unittests, so I am led to believe they may be, but I'd like to know if they are truly identical or if they are different (but behave the same):
Here, the signature constraint refers the parameter names (I realize the runtime information is not available, my assumption is that the compiler uses these to refer to the types of haystack and needle):
T[] find(T, E)(T[] haystack, E needle)
if(is(typeof(haystack[0] != needle) == bool))
{
// ...
}
Now, if I update to refer to the types T and E, it still works. I like this form better because it's explicit that my signature constraint is looking the types (and not runtime information)... and well it's more concise:
T[] find(T, E)(T[] haystack, E needle)
if(is(typeof(T != E) == bool))
{
// ...
}
Are my assumptions correct or am I missing something?
personally I'd use if(is(typeof(T.init != E.init) == bool)) to ensure it's about the vars of the type
(and then when you want T to be a range (and losing the array notation it'd be if(isInputRange(T) && is(typeof(T.init.front != E.init) == bool)))
edit: best way to test things like this is by expanding the test case:
if we take a different function:
int binarySearch(T,E)(T[] haystack, E needle)
if(is(typeof(haystack[0] < needle) == bool)) {
//...
return -1;
}
this compiles and works as you'd expect (barring implementation details...)
but
int binarySearch(T,E)(T[] haystack, E needle)
if(is(typeof(T < E) == bool)) {
//...
return -1;
}
doesn't (calling binarySearch([1,2,3],0); on it doesn't compile)
however like my original answer:
int binarySearch(T,E)(T[] haystack, E needle)
if(is(typeof(T.init > E.init) == bool)) {
//...
return -1;
}
this does work like expected
My first tought is that the function signature is not related to static constraints. When used your function is generated, and so is its signature, I think.
Constraints are just to disambiguate and/or generate compile time errors, my assumption is that you can't talk about signature of a template function, but maybe, as signature template :)
In your example, I believe you want to check convertibility from one type to another, say E to T, (is this int in the array of double), which is written with is(E : T) or using convenient template isImplicitlyConvertible in std.traits.
In your first example, you check that comparison of values haystack[0] and needle is possible, but there is no chance that you can find 3.14 in an array of int, however you can compare an int to a float, so this static if seems to be too permissive.

std::string comparison (check whether string begins with another string)

I need to check whether an std:string begins with "xyz". How do I do it without searching through the whole string or creating temporary strings with substr().
I would use compare method:
std::string s("xyzblahblah");
std::string t("xyz")
if (s.compare(0, t.length(), t) == 0)
{
// ok
}
An approach that might be more in keeping with the spirit of the Standard Library would be to define your own begins_with algorithm.
#include <algorithm>
using namespace std;
template<class TContainer>
bool begins_with(const TContainer& input, const TContainer& match)
{
return input.size() >= match.size()
&& equal(match.begin(), match.end(), input.begin());
}
This provides a simpler interface to client code and is compatible with most Standard Library containers.
Look to the Boost's String Algo library, that has a number of useful functions, such as starts_with, istart_with (case insensitive), etc. If you want to use only part of boost libraries in your project, then you can use bcp utility to copy only needed files
It seems that std::string::starts_with is inside C++20, meanwhile std::string::find can be used
std::string s1("xyzblahblah");
std::string s2("xyz")
if (s1.find(s2) == 0)
{
// ok, s1 starts with s2
}
I feel I'm not fully understanding your question. It looks as though it should be trivial:
s[0]=='x' && s[1]=='y' && s[2]=='z'
This only looks at (at most) the first three characters. The generalisation for a string which is unknown at compile time would require you to replace the above with a loop:
// look for t at the start of s
for (int i=0; i<s.length(); i++)
{
if (s[i]!=t[i])
return false;
}