I've got a problem with converting types in C++. I've got an expression: string wholeExpression = "44*2"; and I want to separate numbers from operators.
If it is a operator, I use this part of code:
string subExpression;
char skladnik;
subExpression = wholeExpression.substr(poczatek, lenght);
skladnik = subExpression[0];
if it is a number:
subExpression = wholeExpression.substr(poczatek, lenght);
skladnik = atoi(subExpression.c_str());
#EDIT
switch (skladnik)
{
case '+':
case '-':
{
while (topOfStack > 0 && stack[topOfStack - 1] != '(')
{
outPut += stack[topOfStack - 1] + przecinek;
stack.resize(topOfStack - 1);
topOfStack--;
}
stack += skladnik;
topOfStack++;
break;
}
case '/':
case '*':
{
while (topOfStack > 0 && (stack[topOfStack - 1] == '*' || stack[topOfStack - 1] == '/'))
{
outPut += stack[topOfStack - 1] + przecinek;
stack.resize(topOfStack - 1);
topOfStack--;
}
stack += skladnik;
topOfStack++;
break;
}
case '(':
{
stack += skladnik;
topOfStack++;
break;
}
case ')':
{
while (stack[topOfStack - 1] != '(')
{
outPut += stack[topOfStack - 1] + przecinek;
stack.resize(topOfStack - 1);
topOfStack--;
}
if (stack[topOfStack - 1] == '(')
{
stack.resize(topOfStack - 1);
topOfStack--;
}
break;
}
default:
{
outPut += to_string(skladnik) + przecinek;
break;
}
}
}
But suddenly I've got problem with a numbers from 40 to 43 and 45 and 47 -> which are operators (in ASCII code). They are probably interpret by the switch not as numbers but as oparators. Another numbers work perfectly. How can i solve this problem?
You've answered your own question. The char for the number 40 doesn't exist. It's two char variables: 4 and 0. Because you are putting an int into a char with atoi, it is going to use the ASCII code. Without knowing the value of lenght, it's hard to say that this is indeed your problem, but here are two possible solutions:
Don't use atoi upfront. Instead interpret each number char into an actual integer after your switch statement (4 and 0 would be
atoi('4') * 10 + atoi('0'))
use an int orlong or double variable to hold your numbers.
You are using your variable skladnik in two different ways. In one code path it refers to a decoded integer, in the second code path it refers to a character. Once you've conflated the meaning like this, there's no way to tell once you're at the switch which meaning it has.
You should use two different variables, one for decoded numbers and one for operator characters. Then there will be no confusion.
Related
This is the homework spec
// Returns a string where the same characters next each other in
// string n are separated by "22"
//
// Pseudocode Example:
// doubleDouble("goodbye") => "go22odbye"
// doubleDouble("yyuu") => "y22yu22u"
// doubleDouble("aaaa") => "a22a22a22a"
//
string doubleDouble(string n)
{
return ""; // This is not always correct.
}
This is part of a homework set that deals with recursion. I know how to use recursion with an int function but I'm not entirely sure how to approach this problem when a string is passed through. Is it as simple as n.length == n.length() +1 ? and then simply insert "22" ? Alongside this, how would one traverse the string? Thanks!
I would say that the base case be if n turns out to be just a blank space, or if it has a size 0, then simply return the string back, no changes made.
This seems OK to me (untested code)
string doubleDouble(string n)
{
if (n.size() < 2)
return n;
else if (n[0] == n[1])
return n[0] + ("22" + doubleDouble(n.substr(1)));
else
return n[0] + doubleDouble(n.substr(1));
}
As you can see you recurse on substrings of the original string.
Undoubtedly there are more efficient ways to do this (that minimise the string copying) but I'll leave that for you.
PS you need to enable C++11 to get all the required versions of + for strings.
string doubleDouble(string n)
{
if(n.length() == 2){
if(n[0]==n[1])
return n.insert(1,"22");
else
return n;
}
else if(n.length() == 1)
return n;
else
if(n.length() % 2 == 1 || n[n.length()/2]!=n[n.length()/2+1])
return doubleDouble(n.substr(0,n.length() / 2)) + doubleDouble(n.substr((n.length() / 2),n.length()));
else if(n[n.length()/2]==n[n.length()/2+1])
return doubleDouble(n.substr(0,n.length() / 2)) +"22"+ doubleDouble(n.substr((n.length() / 2),n.length()));
}
My solution uses 'Divide-and-conquer' paradigm to separate the string in 2 halfs again and again until it finds 1 or 2 characters only. The solution above is simpler. I tried an academic style.
I recently learnt that using getchar_unlocked() is a faster way of reading input.
I searched on the internet and found the code snippet below:
But I am unable to understand it.
void fast_scanf(int &number)
{
register int ch = getchar_unlocked();
number= 0;
while (ch > 47 && ch < 58) {
number = number * 10 + ch - 48;
ch = getchar_unlocked();
}
}
int main(void)
{
int test_cases;fast_scanf(test_cases);
while (test_cases--)
{
int n;
fast_scanf(n);
int array[n];
for (int i = 0; i < n; i++)
fast_scanf(array[i]);
}
return 0;
}
So, this code takes input for an integer array of size n for a given number of test_cases . I didn't understand anything in the function fast_scanf, like why this line:
while (ch > 47 && ch < 58)
{ number = number * 10 + ch - 48;
why the register is used while declaring ch?
why the getchar_unlocked() is used twice in the function? and so on..
It would be great help if someone elaborates this for me. Thanks in advance!
Okay, since what you are asking needs to be explained clearly, I am writing it here... so I don't jumble it all up inside the comments...
The function: (Edited it a bit to make it look like more C++-standard)
void fast_scanf(int &number)
{
auto ch = getchar_unlocked();
number= 0;
while (ch >= '0' && ch <= '9')
{
number = number * 10 + ch - '0';
ch = getchar_unlocked();
}
}
Here, take up consideration by looking at the ASCII Table first, since you won't understand how the results are coming up if you don't...
1) Here, you have a character ch takes up the input character from the user using getchar_unlocked() (The auto keyword does that automatically for you and is only usable in C++, not C)...
2) You assign the variable number to zero so that the variable can be re-used, note that the variable is a reference so it changes inside your program as well...
3) while (ch >= '0' && ch <= '9')... As pointed out, checks whether the characters is within the numerical ASCII limit, similar to saying that the character has to be greater than or equal to 48 but less than or equal to 57...
4) Here, things are a little bit tricky, Variable number is multiplied with the product of itself and 10 and the real integer value of the character you stored)...
5) In the next line, ch is reassigned so that you don't have to stay in the loop forever, since ch will remain that number forever if the user doesn't type anything... remember a loop goes back to where it was declared after reaching the end, checks if the condition is true, continues if it is true else breaks)...
For example: 456764
Here, ch will first take 4 then the others follow so we go with 4 first...
1) Number will be assigned to zero. While loop checks if the given character is a number or not, if it is continues the loop else breaks it...
2) Multiplication of 0 with 10 will be zero... and adding it with difference 52 (that is '4') with 48 (that is '0') gives you 4 (the real numerical value, not the char '4')...
So the variable number now is 4...
And the same continues with the others as well... See...
number = number * 10 + '5' - '0'
number = 4 * 10 + 53 - 48
number = 40 + 5
number = 45... etc, etc. for other numbers...
No matter what number is generated here I always get the first option (penguins). I can't seem to see any problem with my code, anyone else see what's wrong?
{
srand(time(0));
prand = (rand() % 20);
if (prand == 1,5,9,10,14,15,19,20){
entity = "penguins";
srand(time(0));
pquantity = (rand() % 8) + 2;
}
else if (prand == 2,6,11,16,18){
entity = "troll";
pquantity = 1;
}
else if (prand == 3,7,12,17){
entity = "goblin";
pquantity = 1;
}
else if (prand == 4,8,13){
entity = "wizard";
pquantity = 1;
}
}
The code fragment prand == 1,5,9,10,14,15,19,20 is a sequence of expressions (the , is usually know as the comma operator), where the result of the first (or last — depending on language) expression only is used as a condition for the if statement. The remaining expressions are evaluated and their value is forgotten (please note this may lead to serious side effects in more complex situations.)
It's not very clear what language you are using, but in, say, C# you could use a switch statement to achieve what you want:
switch (prand)
{
// first set of options
case 1:
case 5:
…
case 20:
// your code here
break;
// second set of options
case 2:
case 6:
…
case 18:
// your code here
break;
default:
// all other options not listed above
break;
}
Most languages have such a statement. See this wikipedia article for a general description.
You're misusing the comma operator. The expression in the first
if is:
if ( (prand == 1), (5), (9), (10), (14), (15), (19), (20) )
with each of the commas a comma operator. The definition of
a comma operator is to evaluate the first expression (for
possible side effects), then evaluate the second; the value of
the expression is the value of the second expression. So your
if becomes the exact equivalent of:
if ( 20 )
And 20 is implicitly converted to a bool, resulting in
true.
Your compiler should have warned you about this. Something to
the effect of a useless expression.
if (prand == 1,5,9,10,14,15,19,20)
Although this is valid C++ and will compile, it does not do what you expect. You need to compare the variable to each value in turn:
if (prand == 1 || prand == 5 || prand == 9 || prand == 10 || prand == 14 || prand == 15 || prand == 19 || prand == 20)
This is because == is a binary operator which takes two values of compatible types.
In this situation, a switch...case statement is preferred as #Ondrej has explained.
I can think of at least two alternative ways to simulating a dice roll (which it appears you are trying to do:
Use consecutive values for each option:
if (prand >= 1 && prand <= 8) {
// ...
} else if (prand >= 9 && prand <= 13) {
// ...
} else if (prand >= 14 && prand <= 17) {
// ...
} else if (prand >= 18 && prand <= 20) {
// ...
} else {
// Print an error message
}
Store the different possibilities in a std::list<std::set<int>>. Then you can iterate over the sets in the list and use the std::set.contains() method to check if the current set contains the value. This has the advantage of scalability. For example, it makes it easier to code the choices for 1d100 or other dice rolls with a large number of possible values.
If it is "C" then You are testing the result of a comma operator. So the result of prand == 1,5,9,10,14,15,19,20, is the last element (BTW the first element is prand == 1). It is 20 which is always true.
I would suggest to build an array and check its elements...
enum Being_t {BEING_PENGUIN, BEING_TROLL, BEING_GOBLIN, BEING_WIZARD};
enum Being_t arr[20] = {BEING_PENGUIN, BEING_TROLL, BEING_GOBLIN, BEING_WIZARD,
BEING_PENGUIN, BEING_TROLL, BEING_GOBLIN, BEING_WIZARD, ...};
Then You can use a switch
srand(time(0));
prand = (rand() % 20);
switch (arr[prand]) {
case BEING_PENGUIN:
...
break;
...
}
You should use or's or switch statements. For example, with if
if (prand == 1 || prand == 5 || prand == 9 || prand == 10 || prand == 14|| prand == 15|| prand == 19|| prand == 20)
{
// your code here
}
and with switch
switch (prand)
{
case 1:
{
// your code here
break;
}
case 5:
{
// your code here
break;
}
case 9:
{
// your code here
break;
}
case 10:
{
// your code here
break;
}
case 14:
{
// your code here
break;
}
case 15:
{
// your code here
break;
}
case 19:
{
// your code here
break;
}
case 20:
{
// your code here
break;
}
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I've just taken a test for a graduate C++ developer with the question below. It didn't go too well as I couldn't decide on a clear way of completing the task. Time limit didn't help either. I'm interested in how experienced developers would have tackled the follow problem - in pseudo or sample code:
Evaluate
Write a function in C or C++ that evaluates the result of a simple expression.
The function should ignore whitespace, but stop at the first non valid character.
Valid tokens are listed in the table below:
0-9 - Only integers are allowed in expressions
() - Nested expressions should be evaluated first.
+, -, *, / - Basic operators are addition, subtraction, multiplication and division.
The expression should be parsed from left to right. It is not necessary to consider operator precedence in your solution (e.g. 1 + 3 * 4 = 16). If there is an error in the expression, the function should return false.
Suggested prototype for function:
Example:
bool evaluate(const char *expression, int &result)
{
...
}
**Input**
1+3
(1 + (12 * 2)
**Result**
4
N/A
**Return code**
true
false (missing bracket)
In addition, this is the 2nd C++ that I've failed to complete successfully. Have had 1 year intership experiece and 1 year academic experiece using C++, but I'm not prepared for some of these tests. Are there any recommended resources where I can attept to solve problems such as this one in order to gain more 'testing' experience?
The problem here is mostly parsing, which would be covered in a compiler course probably in second or third year. Once you can parse expressions to build up a recursive data structure representing the input (called a syntax tree) it's pretty trivial to evaluate such expressions. A recursive decent parser can also evaluate the expression as it goes without actually building a syntax tree.
For a full treatment you'd want a book on compilers, such as the dragon book. Also IIRC the book Programming: Principals and Practice using C++ covers an example like this.
You could also wait for chapter ten of The Art of Computer Programming to be published, which will cover parsing. It's scheduled to be out around 2020.
Here is my shortest attempt. It took about 40 minutes to type up, you can play with it on ideone (link).
The code is very straightforward, assuming that you have at least a cursory familiarity with the basic recursive descent parsing technique.
#include <iostream>
#include <cctype>
using namespace std;
bool eval_expr(const char **pe, int &lhs, bool inside = false);
// gets the next char after skipping optional whitespace
char skip_ws(const char **pe) {
while (**pe == ' ') ++(*pe);
return **pe;
}
// evaluates a parenthesized expression or a number
bool eval_prim(const char **pe, int &res) {
char c = skip_ws(pe);
if (c == '(') {
++(*pe);
if (!eval_expr(pe, res, true)) return false;
++(*pe);
return true;
}
if (isdigit(c)) {
res = 0;
while (isdigit(c)) {
res = 10*res + c - '0';
c = *(++(*pe));
}
return true;
}
return false;
}
// evaluates a chain of + - * / operations
bool eval_expr(const char **pe, int &lhs, bool inside) {
if (!eval_prim(pe, lhs)) return false;
char op;
while ((op = skip_ws(pe)) && (op == '+' || op == '-' || op == '*' || op == '/')) {
++(*pe);
int rhs;
if (!eval_prim(pe, rhs)) return false;
switch (op) {
case '+': lhs += rhs; break;
case '-': lhs -= rhs; break;
case '*': lhs *= rhs; break;
case '/': lhs /= rhs; break;
}
}
return inside ? op == ')' : !op;
}
// wrapper API to hide an extra level of indirection
bool evaluate(const char *e, int &result) {
return eval_expr(&e, result);
}
Begin with a simple grammar:
expr: n-expr {o-expr} | p-expr {o-expr}
n-expr: [0-9]n-expr
p-expr: ( expr )
o-expr: op expr
op: + | - | * | /
This is probably the largest hurdle for the question. You want to be able to write a simple top down recursive descent parser, so your grammar needs to be written in a way to allow that to happen.
Then, the implementation from there is fairly straightforward:
bool expr (const char *&s, int &result, int eos = 0) {
while (isspace(*s)) ++s;
if (*s == eos) return false;
if (isdigit(*s)) {
if (!n_expr(s, result)) return false;
} else if (*s == '(') {
if (!p_expr(s, result)) return false;
} else return false;
while (isspace(*s)) ++s;
if (*s == eos) return true;
return o_expr(s, result, eos);
}
bool n_expr (const char *&s, int &result) {
int n = 0;
while (isdigit(*s)) n = 10 * n + (*s++ - '0');
result = n;
return true;
}
bool p_expr (const char *&s, int &result) {
if (expr(++s, result, ')')) {
++s;
return true;
}
return false;
}
bool o_expr (const char *&s, int &result, int eos) {
int oresult = 0;
const char *op = strchr("+-*/", *s);
if (op == 0) return false;
if (!expr(++s, oresult, eos)) return false;
switch (*op) {
case '+': result += oresult; break;
case '-': result -= oresult; break;
case '*': result *= oresult; break;
case '/': result /= oresult; break;
default: return false;
}
return true;
}
This is a simple scan push apply (the twist is the braces).
Look for a number:
If you see a number push onto stack
if you see a '(' push it onto stack and goto 1
Otherwise an error.
Look for an op:
If you see an op push it onto stack
Otherwise an error
Look for a number:
If you see a number push onto stack
If you see a '(' push onto stack and goto 1
Otherwise an error
pop last three items from the stack (should be number op number)
do the operation and push the result onto the stack.
Now the complex bit:
Peek to see if the next character is a ')' if it is goto "PopCode" below.
If no more input goto 7.
Otherewise goto 2
If only one item on the stack you have your result.
Otherwise an error.
PopCode
Pop last two values from the stack. Should be '( Number'
If it is not then an error
Throw away the '('
If the top of the stack is an op push value goto 4 (above)
Otherwise push the value onto the stack goto 5 (above)
When finished there should be one number on the stack.
Example:
1+3
Rule 1: push 1 stack = '1'
Rule 2: push + stack = '1 +'
Rule 3: push 3 stack = '1 + 3'
Rule 4: pop and do: stack = '4'
Rule 5: Nothing stack = '4'
Rule 6: goto 7 stack = '4'
Rule 7: stack = '4'
(1 + (12 * 2)
Rule 1: push ( goto 1 stack = '('
Rule 1: push 1 stack = '( 1'
Rule 2: push + stack = '( 1 +'
Rule 3: push ( goto 1 stack = '( 1 + ('
Rule 1: push 12 stack = '( 1 + ( 12'
Rule 2: push * stack = '( 1 + ( 12 *'
Rule 3: push 2 stack = '( 1 + ( 12 * 2'
Rule 4: Pop and do: stack = '( 1 + ( 24'
Rule 5: Do 'PopCode' stack = '( 1 + ( 24'
Pop 1: Pop 2 stack = '( 1 +'
Pop 2: Holding 24 stack = '( 1 +'
Pop 3: push 24 goto 4 stack = '( 1 + 24'
Rule 4: Pop and do stack = '( 25'
Rule 5: Nothing stack = '( 25'
Rule 6: goto 7 stacj = '( 25'
Rule 7: More than 1 item error
Re-Doing with correct formula
(1 + (12 * 2))
Rule 1: push ( goto 1 stack = '('
Rule 1: push 1 stack = '( 1'
Rule 2: push + stack = '( 1 +'
Rule 3: push ( goto 1 stack = '( 1 + ('
Rule 1: push 12 stack = '( 1 + ( 12'
Rule 2: push * stack = '( 1 + ( 12 *'
Rule 3: push 2 stack = '( 1 + ( 12 * 2'
Rule 4: Pop and do: stack = '( 1 + ( 24'
Rule 5: Do 'PopCode' stack = '( 1 + ( 24'
Pop 1: Pop 2 stack = '( 1 +'
Pop 2: Holding 24 stack = '( 1 +'
Pop 3: push 24 goto 4 stack = '( 1 + 24'
Rule 4: Pop and do stack = '( 25'
Rule 5: Do 'PopCode' stack = '( 25'
Pop 1: Pop 2 stack = ''
Pop 2: holding 25 stack = ''
Pop 3: Nothing. stack = ''
Pop 4: push 25 goto 5 stack = '25'
Rule 5: Nothing stack = '25'
Rule 6: goto 7 stack = '25'
Rule 7: Result = 25
The easiest way to solve a (not necessarily) simple mathematical expression is to use the Shunting Yard algorithm to convert it to Reverse Polish Notation, which is almost trivial to parse using a stack. Of course it might not be feasible to do so for an assignment or an interview (perhaps unless a SY algorithm reference is available).
I am trying to understand the switch statement better. I don't need the code but kinda a walkthrough on how it would be done.
If someone enters a 7 digit phone number EG. 555-3333 but enters it as "jkl-deff" as it would correspodnd to the letters on the dial pad, how would I change the output back to numbers?
Would this work:
switch (Digit[num1])
case 'j,k,l':
num1 = 5;
break;
case 'd,e,f':
num1 = 3;
break;
To do that with a switch statement, you'd have to walk through the char array, switching on each character. Group all the chars that have the same number together.
Something like
switch (phoneChar[i])
case 'a':
case 'b':
case 'c':
newChar[i] = '2';
break;
That said, I'm not sure that switch case is the best way to do that. I don't know what would be the best off the top of my head, but something feels wrong about this :)
Edit
The i would be the index of the current character under consideration. You'll have a 7 (or 8 or 10 or 12 character string depending on formatting) for a phone number. You'd have to take each character at a time.. so phone[0] = 'j' in the above example.
I would not use a switch!
// A,B,C => 2; D,E,F => 3 etc.
static int convert[] = {2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
for(int loop =0 ;loop < Digit.size(); ++loop)
{
num = convert[Digit[loop] - 'a'];
// Thus the character 'a' gets mapped to position 0
// the character 'b' gets mapped to position 1 etc.
// num is then the character mapped into the covert[] array above.
}
You could probably do it like this:
if (islower(c)) { num=(c-'a')/3; num = 2 + (num==8) ? 7 : num; }
to convert a character to a phone pad digit. The num==8 part at the end handles the exra digit on the 9 key.
Altogether it would look like this:
char c = getNextCharacterSomehow();
int num = -1;
if (isdigit(c)) num = c-'0';
else if (islower(c)) { num=(c-'a')/3; num = 2 + (num==8) ? 7 : num; }
else if (isupper(c)) { num=(c-'A')/3; num = 2 + (num==8) ? 7 : num; }
Also, a note about the switch statement: The item that comes between the "case" and the ":" has to have the same type as the thing specified by the "switch()" portion. And that type must be a scalar, which excludes things like strings.