I am looking for code wchich parses prefix expressions using recursion. Primarily in C++, but it can bee in other language, i will translate. Thanks.
It's really easy to do yourself (you just need a stack for the operators (and sometimes/optionally its first term)).
But if you really don't want to do much work, here's a link:
prefix notation string to int conversion
If you need to use recursion, you basically use local variables in the function as individual elements in your stack.
Eg. pseudo-C++ code follows:
int naughtyglobalendindex = 0;
int parse(string str) {
if (/* str starts off with an integer */) return the integer;
char operator;
operator = ?? // you will need to get the first op here. Maybe sscanf(str,"%c",&operator) or similar
// get first argument
int first = parse(/* str with 1st operator removed */);
// get 2nd integer argument
int second = parse(/* str - get substring from naughtyglobalendindex to end*/)
// return first operator second <- this is pseudocode
// in effect you want a switch clause
switch (operator) {
case '+': return first + second;
case '-': return first - second; // and so on
}
}
You can convert the pseudocode to actual C++, and if you want, fix the global naughtyglobalendindex variable if you want.
Related
int i = ("aac" > "aab");
cout << i;
The above code does not give me the output as 1 (as it should be). But when I assign "aac" and "aab" to two separate string variables and use the variables instead of using strings directly (code attached below), I get the desired output.
Could anyone help me please?
string s1 = "aac";
string s2 = "aab";
int i = (s1 > s2);
cout << i;
Literal constants like "aac" aren't std::string objects; rather, they are just data in (read-only) memory that evaluate, in most 'access' cases, to the address of their first element (i.e. a char* pointer); so, a comparison between them will be a comparison between those addresses — something you are unlikely to be able to control or predict.
To get an inline comparison, in your case, you can use inline std::string constructors (sometimes knows as "wrappers"), like this:
int i=(string("aac")>string("aab"));
Or, using the more 'modern' "curly-brace" initializer syntax:
int i = (string{ "aac" } > string{ "aab" });
For more brevity, you can make use of the fact that std::string has versions of the > (and similar) operators that take a string literal as one of the arguments; thus, you need only 'wrap' one of the literals, and could reduce the above code to something like:
int i = (string{ "aac" } > "aab");
If you use C-style char * / char [] strings, you need to use strcmp like:
int i = strcmp("aac", "aab");
Otherwise, you are just comparing addresses of the first elements of both of strings.
Its question is" Give the second parameter of make_plural (§ 6.3.2, p. 224) a default argument of 's'. Test your program by printing singular and plural versions of the words success and failure"
here is the make_plural.
string make_plural(size_t ctr, const string& word, const string& ending )
{
return (ctr > 1) ? word + ending : word;
}
Does it mean that change the 'ending', but ending is the third parameter, isn't it?
This question worries me a lot!
Regards!
That must be a typo.
Looking at the code:
string make_plural(size_t ctr, const string& word, const string& ending )
{
return (ctr > 1) ? word + ending : word;
}
the most reasonable thing would be to have "s" as default for ending, as this is how you make the plural by default (not always, but with "bee" -> "bees" e.g. it works).
A much stronger argument is that in C++ it is not possible (unless you find a magic workaround (*)) to have a default argument for the n-th parameter if the (n+1)-th has no default argument:
foo(int first = 0,int second) // not possible !!
With this example it is maybe not so clear why this isnt allowed, but consider having multiple default values. Lets say you would write:
foo(int first = 0,int second,int third = 0); // actually still not allowed
Then there would be no way to know if
foo(1,2);
is supposed to call
foo(0,1,2);
or
foo(1,2,0);
To resolve this ambiguity some rule had to be invented and for C++ the rule is that default arguments have to be provided from right to left.
(*) If you can change the function and are willing to write some extra code, the workaround is rather trivial. You just have to encapsulate all parameters in a struct that provides creation of parameters with whatever combination of defaults you like.
I'm working on creating a program that will take a fraction and reduce it to it's lowest terms. I'm using a tokenizer to parse through the string (In my case I'm reading in a string) and separate the numerator from the denominator.
I'm getting the following error, and am looking for an explanation to why it's happening. I've looked up people with similar problems, but I'm still a beginner looking for a basic explanation and suggestion for an alternative way to solve it.
RationalNum() // Default
:numerator(0), denominator(1){}
RationalNum(int num) // Whole Number
:numerator(num), denominator(1){}
RationalNum(int num, int denom) // Fractional Number
:numerator(num), denominator(denom){}
RationalNum(string s)
{
int num = 0;
char str[] = s;
}
I know the problem lies in the setting the char array to s.
Thanks for taking the time to look at this.
You are trying to initialise an array of char to a std::string, which is an object. The literal meaning of the error is that the compiler is expecting an initialisation that looks something like this :
char str[] = {'1','2','3','4'};
However, since you are planning on string manipulation anyway, you would have a much easier time just keeping the string object rather than trying to assign it to a char array.
Instead of building your parser from scratch, you can use string stream and getline. with '/' as your delimiter. You can initialise an std::stringstream with a string by passing it as an argument when constructing it. You can also use another stringstream to convert a string into a number by using the >> operator.
This question already has answers here:
C/C++: switch for non-integers
(17 answers)
Closed 9 years ago.
How can I compare an array of char in c++ using switch-case?
Here is a part of my code:
char[256] buff;
switch(buff){
case "Name": printf("%s",buff);
break;
case "Number": printf("Number "%s",buff);
break;
defaul : break
}
I receive the error :" error: switch quantity not an integer".How can I resolve it?
If you really need a switch statement, you will need to convert your buff variable to an integer. To do so, you could use a hash function or a std::map.
The easy approach would be to make a std::map<std::string,int> containing the keys you want to use in the switch associated with unique int values. You would get something like:
std::map<string,int> switchmap;
...
switch(switchmap.find(std::string(buff))->second){
...
}
The std::map approach is very readable and shouldn't cause much confusion.
You just can't use an array as the expression in a switch construct.
In C++ case statements require a constant integer value and cannot be used with values calculated at runtime. However if you are using C++11 you can use a constexpr function to generate case values simulate using strings with a case statement.
This uses a hash function that takes a pointer to a string and generates a value at compile time instead of runtime. If more than one string generates the same value (a hash collision) you get the familiar error message about multiple case statements using the same value.
constexpr unsigned int djb2Hash(const char* str, int index = 0)
{
return !str[index] ? 0x1505 : (djb2Hash(str, index + 1) * 0x21) ^ str[index];
}
The djb2Hash function can then be used directly in both the switch and case statements. There is one caveat however, the hash function can result in a collision at runtime. The probability of this happening is driven primarily by the quality of the hash function. The solution presented here does not attempt to address this problem (but may in the future).
void DoSomething(const char *str)
{
switch(djb2Hash(str))
{
case djb2Hash("Hello"): SayHello(); break;
case djb2Hash("World"): SayWorld(); break;
}
}
This works very well but might be considered ugly. You can simplify this further by declaring a user defined literal that handles invoking the hash function.
// Create a literal type for short-hand case strings
constexpr unsigned int operator"" _C ( const char str[], size_t size)
{
return djb2Hash(str);
}
void DoSomething(const char *str)
{
switch(djb2Hash(str))
{
case "Hello"_C: SayHello(); break;
case "World"_C: SayWorld(); break;
}
}
This provides a more intuitive usage of strings in a switch statements but may also be considered slightly confusing because of the user defined literal.
[Edit: Added note about runtime hash collisions. Much Kudos to R. Martinho Fernandes for bringing it to my attention!]
You cannot use a non-integral type in a switch statement. Your problem would require something like:
char buff[256];
if(!strcmp(buf, "Name") printf("%s",buff);
if(!strcmp(buf, "Number") printf("%s",buff);
To get the results you are looking for - basically a bunch of if statements to replace the switch.
You are trying to do something we all dearly wish we could, but not in C/C++ :) The case in a switch statement must be integral values. One easy alternative is to have an enumeration that matches the set of strings you want to act on.
In C++ you can use a switch-case only with integers (char, int, ...) but not with c-strings (char *)
In your case you have to use a if-then-else construct
if (strcmp(buff, "Name") == 0) {
...
} else if (...) {
...
}
As the error says, switch only works for integers. The simplest resolution is to use a chain of if...else if... tests.
However, using a char array rather than a string is awkward, since you need quirky C-style functions to compare them. I suggest you use std::string instead.
std::string buff;
if (buff == "Name") {
// deal with name
} else if (buff == "Number") {
// deal with number
} else {
// none of the above
}
More complex approaches, perhaps mapping strings to numbers for use in a switch or to functors to call, are possible and may be more efficient if you have a huge number of cases; but you should get the simple version working before worrying about such optimisations.
Unlike many other languages that allow string and other object comparisons to be used in a switch-case, c++ requires that the underlying value be an integer. If you want use more complex object types, you will have to use an if else-if construct.
You can't use a switch directly for this situation.
Typically, you'd want to use a std::map (or std::unordered_map) to store the action to associate with each input. You might (for example) use a std::map<std::string, std::function>, and then store the addresses of functions/function objects in the map, so your final construct would be something like:
std::map<std::string, std::function> funcs;
funcs["Name"] = [](std::string const &n) {std::cout << n;};
funcs["Number"] = [](std::string const &n) {std::cout << "Number: " << n;};
// ...
auto f = funcs[buff];
f(buff);
// or combine lookup and call: funcs[buff](buff);
Two notes: first, you probably really want to use map::find for the second part, so you can detect when/if the string you're looking for isn't present in the map.
Second, as it stands, your code doesn't seem to make much sense -- you're both switching on buff and printing out buff's value, so (for example) if you buff contains Number, your output will be "Number Number". I'd guess you intend to use buff and some other variable that holds the value you care about.
You can partially do a "string" compare.
The below does not specifically satisfy your query (as C won't ride that pony), nor is it elegant code, but a variation on it may get you through your need. I do not recommend you do this if you a learning C/C++, but this construct has worked well in limited programming environment.
(I use it in PIC programming where strlen(buff)==1 or 2 and sizeof(int)==2.)
Let's assume sizeof(int) == 4 and strlen(buff) >= 3.
char buff[256];
// buff assignment code is TBD.
// Form a switch 4-byte key from the string "buff".
// assuming a big endian CPU.
int key = (buff[0] << 3*8) | (buff[1] << 2*8) | (buff[2] << 1*8) | (buff[3] << 0*8);
// if on a little endian machine use:
// int key = (buff[0] << 0*8) | (buff[1] << 1*8) | (buff[2] << 2*8) | (buff[3] << 3*8);
switch (key) {
// Notice the single quote vs. double quote use of constructing case constants.
case 'Name': printf("%s",buff); break;
case 'Numb': printf("Number \"%s\"",buff); break;
default : ;
}
I am trying to create and expression from two or more numbers and character operator. The exact scenario is that i have two number for eg.
float a = 10.1, b = 10.2;
and a character operator
char ch = '+';
Now i have to create an expression that would look like
float c = 10.1 '+' 10.2;
i.e. i want to apply the operator mentioned in char variable "ch" between the two float numbers i have. So in this case the charater is '+' so i want to create the expression where both the float values will be added, if '-' then substraction etc. All the values will actually be supplied by the user so want to create an expression and than perform the operation.
Now one solution I thought of is to have switch case for different operators and that would do the trick. Another one is below:
float a = 10.1, b = 20.3;
char ch = '+';
string result = "";
ostringstream os;
os << a;
result += os.str();
os.str("");
os << b;
result += ch + os.str();
Now I wrote the above snippet so that I can create the expression based on user input and than return that expression so that it can be evaluated it in another procedure.
I am not sure if that's possible. I mean the switch case solution seems to be fine where i evaluate the expression here itself and return the output value, but just wanted to know if there is a way to return the expression to another function and then evaluate it there?
In tcl scripting language we have a command "expr" which does the same job and so was wondering if we have any such ability to do the same in c++. Any help would be appreciated.
I think the key to your question is in considering the expression as an object. You're using C++, which some consider an object-oriented programming language, right? :) Consider writing a class Expression that follows the Composite Pattern. An Expression might be just a simple value:
Expression(10.1)
It could also represent the addition of two subordinate Expressions:
Expression(Expression(10.1) + Expression(20.3))
Or to give you a further hint:
Expression('+', Expression(10.1), Expression(20.3))
Make Expression hold the operators and operands of the expression without actually evaluating it. Then you are free to construct it in one place in your program, then pass that to another place to actually evalute it.
C++ has a wealth of expression parsing libraries. While I haven’t used any of them myself I have heard good things about muParser.
Assuming that this is another assignment/homework and you don't pursue fully featured expression parser, here is the solution as simple as it could be:
#include <iostream>
#include <sstream>
using std::stringstream;
using std::cout;
using std::endl;
float compute(float a, float b, char op) {
switch(op) {
case '+':
return a + b;
case '-':
return a - b;
// You may add more operations in the similar way.
default:
cout << "Operation is not supported." << endl;
}
return 0;
}
int main() {
// These guys are here to simulate user input.
float input_a = 10.1;
float input_b = 20.3;
char input_op = '+';
stringstream ss;
ss << input_a << input_op << input_b;
// If you really make it interactive, then the program actually starts here.
float a;
float b;
char op;
// You simply read operands and operator from some input stream,
// which in case of interactive program could be `std::cin`.
ss >> a;
ss >> op;
ss >> b;
// Print the result of computation.
cout << compute(a, b, op) << endl;
}
If you want to handle more complex situations, like evaluation of nested expressions, possibly including parentheses functionality, then I'd suggest that you read first 4 chapters of the classical Dragon Book. It really took me around 1-2 weeks to be able to write LR-parser for ANSI C, which is somewhat much more complicated than your problem.
Your task is very simple and can be described with a toy context-free grammar which doesn't even require LL-parser to handle. Anyway to understand, why and how, I encorage you to read this book.