function returning something strange - c++

I have a function to get a grade point value from a grade object and return it as a double as implemented below:
double Grade::getNumGrade()
{
double value;
if (strGrade == "A")
{
return 4.0;
}
else if (strGrade == "A-")
{
return 3.7;
}
else if (strGrade == "B+")
{
return 3.3;
}
else if (strGrade == "B")
{
return 3.0;
}
else if (strGrade == "B-")
{
return 2.7;
}
else if (strGrade == "C+")
{
return 2.3;
}
else if (strGrade == "C")
{
return 2.0;
}
else if (strGrade == "C-")
{
return 1.7;
}
else if (strGrade == "D+")
{
return 1.3;
}
else if (strGrade == "D")
{
return 1.0;
}
else if (strGrade == "D-")
{
return 0.7;
}
else if (strGrade == "F")
{
return 0.0;
}
}
With strGrade being the string representation of the grade. However with the code here:
Grade jon = Grade("A+");
cout << jon.getNumGrade();
outputs :
-1.#IND
The constructor just makes sure the first letter is uppercase and then saves the string provided as strGrade. Not sure why this is happening or how to fix it?

As NathanOliver pointed out,
You never handle A+ in your if statements.
See
double value;
if (strGrade == "A")
{
return 4.0;
}
else if (strGrade == "A-")
{
return 3.7;
}
No conditional for when strGrade == A+.
But since this was answered in a comment, I'll attempt to justify writing this as an answer by giving you some advice.
Your final conditional,
else if (strGrade == "F")
{
return 0.0;
}
shouldn't be an else if. There's plenty of good ways to deal with error handling (like an unexpected input) but a very easy yet efficient practice is to end your conditionals with an else. For example,
//if all other conditionals thus far have returned false
else
{
... error handling here ...
}
In the event that you fall into this else, log an error and/or gracefully exit the program; at the least, return a value and handle it appropriately.
Also consider applying your if else in a logical ordered based on the likelihood of a certain conditional being evaluated to true. More specifically, if you know that a majority of students are going to get a B+, make that the first expression that gets evaluated in your if else series. If a B- is the next most common grade, make that the second expression that gets evaluated; and so on. Additionally, if you know that a grade is least likely to be passed through, make that the last conditional you check.

Not sure why this is happening or how to fix it?
That's happening because your function doesn't return a value for the "A+" case and exposes undefined behavior.
As mentioned in comments you should have seen a compiler warning about that stating
Not all of your code paths return a value.
You can fix that providing always a (reasonable) return value before your last brace in the function, or throwing an exception for unexpected cases of strGrade.
BTW the much easier solution would be to use a std::map<std::string,double> to hold the associative values:
double Grade::getNumGrade() {
static std::map<std::string,double> numGrades = {
{ "A", 4.0 } ,
{ "A-", 3.7 } ,
{ "B+", 3.3 } ,
// ...
};
auto found = numGrades.find(strGrade);
if(found != numGrades.end()) {
return found->second;
}
return 0.0;
}
It also looks that this should be a free or static function rather than a class member function:
double getNumGrade(const std::string& strGrade) {

Related

What is causing zsh:segmentation fault in this case?

this is my first every time posting a question on stackoverflow so I apologize beforehand If my question seems messy. I have a class named token, and a derived class from it called function, integer, and operator. Token has a public variable of type int called _type. I assigned different _type values for each derived classes. The type for integer is 1, 2 for operator, and 3 for function. The purpose of this is so that I can implement different operations depending on the type encountered. I made an rpn function and in it I have something like this.
double RPN::rpn(){
Stack<Token*> rpn_stack;
while(input_q.empty() == false){
if(input_q.front()->_type == 1){
rpn_stack.push(input_q.pop());
}
if(input_q.front()->_type == 2){
double x = rpn_stack.pop()->value();
double y = rpn_stack.pop()->value();
//cout << x << y;
char i = input_q.pop()->op();
if(i == '*'){
double result;
result = x * y;
rpn_stack.push(new Integer(result));
}
}
if(input_q.front()->_type == 3){
input_q.pop();
rpn_stack.push(new Integer(_val));
}
}
return rpn_stack.top()->value();
}
after testing it a couple of times, I found out that the zsh:segmentation fault problem is caused by the input_q.pop() in
if(input_q.front()->_type == 3){
input_q.pop();
rpn_stack.push(new Integer(_val));
}
However, the code works if I change the order of the if statements like this
double RPN::rpn(){
Stack<Token*> rpn_stack;
while(input_q.empty() == false){
if(input_q.front()->_type == 3){
input_q.pop();
rpn_stack.push(new Integer(_val));
}
if(input_q.front()->_type == 1){
rpn_stack.push(input_q.pop());
}
if(input_q.front()->_type == 2){
double x = rpn_stack.pop()->value();
double y = rpn_stack.pop()->value();
//cout << x << y;
char i = input_q.pop()->op();
if(i == '*'){
double result;
result = x * y;
rpn_stack.push(new Integer(result));
}
}
}
return rpn_stack.top()->value();
}
which leads me to question whether the problem was input_q.pop() in the first place. It also works if I were to assign input_q.front()->_type to a static variable inside the while loop like this
double RPN::rpn(){
Stack<Token*> rpn_stack;
while(input_q.empty() == false){
int type = input_q.front()->_type;
if(type == 1){
rpn_stack.push(input_q.pop());
}
if(type == 2){
double x = rpn_stack.pop()->value();
double y = rpn_stack.pop()->value();
//cout << x << y;
char i = input_q.pop()->op();
if(i == '*'){
double result;
result = x * y;
rpn_stack.push(new Integer(result));
}
}
if(type == 3){
input_q.pop();
rpn_stack.push(new Integer(_val));
}
}
return rpn_stack.top()->value();
}
At this point I am very confused as to what is causing zsh:segmentation fault when using the first version. Im wondering if the problem lies in accessing input_q.front()->_type? I could just use the second and third version but I really want to know what is causing zsh:segmentation fault on the first version. If it helps, here is the simple program I wrote to test it. I am also using stack and queue if it helps.
Queue<Token *> postfix;
postfix.push(new Integer(3));
postfix.push(new Integer(5));
postfix.push(new Operator("*"));
RPN rpn(postfix);
cout << "3 5 *: " << rpn() << endl;
cout << "-------------" << endl;
Queue<Token *> postfix2;
postfix2.push(new Integer(3));
postfix2.push(new Function("X"));
postfix2.push(new Operator("*"));
rpn.set_input(postfix2);
cout << "3 x *: (x=3): " << rpn(3) << endl;
the rpn function is called using the () operator in the RPN class. the RPN class has a private variable called _val that is assigned a value to by the () operator. Hope the information Ive provided is enough. Thank you for your time, would appreciate the input!
With reference to your first code snippet, when you say this:
if(input_q.front()->_type == 1){
rpn_stack.push(input_q.pop());
}
if(input_q.front()->_type == 2){
...
You don't check if there's anything left on the input queue the second time you call input_q.front.
A simple fix is to insert a continue statement, like this:
if(input_q.front()->_type == 1){
rpn_stack.push(input_q.pop());
continue;
}
...
You will then loop back to the while statement which checks whether the queue is empty before proceeding.
There are other places in the code where you need to make a similar change, but you get the idea.

Can somebody tell me how this code working with no curly braces between two if?

If I am enclosing the code after first if upto second return in curly braces it is not giving me desired output.
static int comparator(Player a, Player b) {
if(a.score == b.score)
if(a.name == b.name)
return 0;
else
return (a.name > b.name)? -1:1;
return (a.score < b.score)? -1:1;
}
Your code has if() and else statements. Each will execute one line of code that comes after them. This means that it will only execute a single statement and end after the first ; that it finds.
for() loops, while() loops, if-else blocks can be used without curly braces if the statement you want to execute consists of only one line of code following them.
Your code works as -
static int comparator(Player a, Player b) {
// if statement without braces- means just one statement executes
if(a.score == b.score)
// Remember if-else will be considered as a single code block so both will run
if(a.name == b.name)
return 0;
else
return (a.name > b.name)? -1:1;
// This statement will run only when the above if condition is not satisfied
return (a.score < b.score)? -1:1;
}
This can be considered to be same as -
static int comparator(Player a, Player b) {
if(a.score == b.score) {
if(a.name == b.name) {
return 0;
} else {
return (a.name > b.name) ? -1 : 1;
}
}
return (a.score < b.score) ? -1 : 1;
}
NOTE : It is generally better if you use the braces as it will be good for readability as well as maintainability of the code. There can actually be two way of parsing it - Dangling else(though most compiler will associate the else with closest if).
In this coding style, there's no way to differentiate between below two code -
if(condition1)
if(condition2)
foo1();
else
foo2();
and,
if(condition1)
if(condition2)
foo1();
else
foo2();
Since, in C/C++, it doesn't consider the indentation in code, so it might create ambiguity while reading the code. So its always better to use curly braces instead of doing it like above. Drop them only when you have a single line and it won't create any confusion reading the code later on...
Hope this helps !
Without curly braces, only the next statement is executed. With proper indentation it becomes easier to see what's going on:
static int comparator(Player a, Player b) {
if(a.score == b.score)
if(a.name == b.name)
return 0;
else
return (a.name > b.name) ? -1 : 1;
return (a.score < b.score) ? -1 : 1;
}
This is actually the same as:
static int comparator(Player a, Player b) {
if(a.score == b.score) {
if(a.name == b.name) {
return 0;
} else {
return (a.name > b.name) ? -1 : 1;
}
}
return (a.score < b.score) ? -1 : 1;
}
You have maybe used the braceless else variant without noticing it when writing something like:
if(condition) {
//
} else if(another_condition) {
//
} else {
//
}
Which is actually the same as
if(condition) {
//
} else {
if(another_condition) {
//
} else {
//
}
}
Without curly braces, the if guard only applies to the immediate next statement.
It's just how the language works. :/

Error: control may reach end of non-void function in C++

I cannot figure out why this error is happening: error: "control may reach end of non-void function" even when "else" statement is present at the end.
Here is the code:
bnode* binsert(bnode *h,int k){
bnode *temp=new bnode;
if(h==NULL)
{
temp->num=k;
temp->L=NULL;
temp->R=NULL;
h=temp;
return h;
}
else if(h->L==NULL && k<h->num)
{
temp->num=k;
temp->L=NULL;
temp->R=NULL;
h->L=temp;
return h;
}
else if(h->R==NULL && k>h->num)
{
temp->num=k;
temp->L=NULL;
temp->R=NULL;
h->R=temp;
return h;
}
else if(h->L!=NULL && k<h->num)
{
h->L=binsert(h->L,k);
}
else
{
h->R=binsert(h->R,k);
}
}
You need to return the results of recursive calls, it's not done automatically.
You can also simplify your code a bit by adding a constructor:
bnode::bnode(int v)
: num(v),
L(nullptr),
R(nullptr)
{
}
and since you're already handling the case of a null parameter, you don't need special cases for null children:
bnode* binsert(bnode *h,int k)
{
if(h == nullptr)
{
h = new bnode(k);
}
else if(k < h->num)
{
h->L = binsert(h->L, k);
}
else if(k > h->num)
{
h->R = binsert(h->R, k);
}
return h;
}
because this last 2 conditions:
else if(h->L!=NULL && k<h->num)
{
h->L=binsert(h->L,k);
}
else
{
h->R=binsert(h->R,k);
}
may occur and no return is given...
you need to be sure the function returns a value no matter what the condition evaluates....
else if(h->L!=NULL && k<h->num)
{
h->L=binsert(h->L,k);
}
else
{
h->R=binsert(h->R,k);
}
In the else if and else cases for your code, if you reach here, you do not return a value, and the behavior is undefined if you try to use this value.
You probably want to add a return h; in the two branches.

infix to postfix program

I have written the following infix to postfix program but it's not working.
My program takes input but doesn't show any result. Can anyone help find the problem in my program.
And also it would be a great help if you tell if my Algorithm for converting infix to postfix is correct or not.
using namespace std;
class Stack
{
private:
int top;
char s[mx];
public:
Stack()
{
top=-1;
}
void push(char c)
{
if(!stackFull())
s[++top]=c;
}
void pop()
{
if(!stackEmpty())
top--;
else cout<<"Stack is empty"<<endl;
}
char topShow()
{
if(!stackEmpty())
return s[top];
}
bool stackEmpty()
{
if(top==-1)
return 1;
else return 0;
}
bool stackFull()
{
if(top == (mx-1))
return 1;
else return 0;
}
};
class Expression
{
private:
char entry2;
int precedence;
char infix[mx];
char postfix[mx];
public:
int prec(char symbol)
{
switch(symbol)
{
case '(':return 0; break;
case '-':return 1; break;
case '+':return 2; break;
case '*':return 3; break;
case '/':return 4; break;
}
}
void Read()
{
cout<<"Enter the infix expression: ";cin>>infix;
for(int i=0;infix[i]!='\0';i++)
{
convertToPostfix(infix[i]);
}
}
void ShowResult()
{
cout<<"Postfix expression"<<endl;
for(int j=0;postfix[j]!='\0';j++)
{
cout<<postfix[j];
}
}
void convertToPostfix(char c)
{
int p=0;
Stack myStack;
precedence=prec(c);
entry2=myStack.topShow();
if(isdigit(c))
{
postfix[++p]=c;
}
if(precedence>prec(entry2))
{
myStack.push(c);
}
if(precedence<prec(entry2))
{
switch(c)
{
case '(': myStack.push(c); break;
case ')': while(myStack.topShow()!= '(')
{
postfix[++p]=myStack.topShow();
myStack.pop();
};myStack.pop();break;
case '+':
case '-':
case '*':
case '/': while(prec(myStack.topShow())>=precedence)
{
postfix[++p]=myStack.topShow();
myStack.pop();
};break;
}
}
}
};
int main()
{
Expression myExp;
myExp.Read();
myExp.ShowResult();
return 0;
}
Here are some issues I found:
Boolean Functions Return true or false
Match return types with return values. The numbers 1 and 0 are not Boolean values.
Precedence table
Add and subtract have same precedence.
Multiply and divide have same precedence.
Multiply and divide have higher precedence than add and subtract.
Stack disappears
Since the stack is declared as a local variable in the function, it will be created fresh when entering the function and destroyed before exiting the function.
Solution: move it to the class as a class member or declare it as static.
Multiple statements per line are not more efficient
Blank lines and newlines do not affect performance, and add negligible time to the build.
However, they make your program more readable which helps when inspecting or debugging. Use them.
And similarly with space before and after operators.
Build the habit now rather than correcting when you get a job.
Call function once and store the value
You call prec(entry2) twice, which is a waste of time. Call it once and save the value in a variable. Similarly with stack.TopShow().
Use std::vector not an array
The std::vector will grow as necessary and reduce the chance of buffer overflow.
With an array, you must check that your indices are always within range. Also, array capacities don't change; you have to declare a new instance and copy the data over.
The variable mx is not declared
The compiler should catch this one. You use mx as the capacity for an array and comparing for full. However, it is never declared, defined nor initialized. Prefer std::vector and you won't have to deal with these issues.
Input is not validated
You input a letter, but don't validate it.
Try these characters: space, #, #, A, B, etc.
Missing default for switch
Crank up your compiler warnings to maximum.
Your switch statements need defaults.
What precedence do numeric characters ('0'..'9') have?
(You check the precedence of numeric characters.)
Check all paths through your functions and program.
Using a debugger (see below) or pen and paper, check your program flow through you functions. Include boundary values and values not within the bounds.
Case statements: break or return
You don't need a break after a return statement. Think about it. Can the program continue executing at the line after a return statement?
Use a debugger or print statements
You can print variables at different points in your program. This is an ancient technique when debuggers are not available.
Learn to use a debugger. Most IDEs come with them. You can single step each statement and print out variable values. Very, very, useful.
class infixToPostfix{
public static void postfix(String str){
Stack<Character> stk = new Stack<Character>();
for(Character c : str.toCharArray()){
// If operands appears just print it
if(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z'){
System.out.print(c);
}else{
// Open paranthesis push is
if(c == '('){
stk.push(c);
//Close paranthesis pop until close paranthesis
}else if( c == ')'){
while(stk.peek() != '(')
System.out.print(stk.pop());
stk.pop();
// check the precedence of operator with the top of stack
}else if(c == '+' || c == '-'){
if(!stk.isEmpty()){
char top = stk.peek();
if(top == '*' || top == '/' || top == '+' || top == '-'){
System.out.print(stk.pop());
}
}
stk.push(c);
}else{
if(!stk.isEmpty()){
char top = stk.peek();
if(top == '/' || top == '*'){
System.out.print(stk.pop());
}
}
stk.push(c);
}
}
}
//Print all the remaining operands
while(!stk.isEmpty()) System.out.print(stk.pop());
System.out.println();
}
public static void main(String args[]){
String str = "A+B-(c+d*Z+t)/e";
postfix(str);
}
}
using stack and map u can solve the problem
1) create a map having operator as key and some integer to set priority. operator with same precedence will have same value something like:
map<char,int>oprMap;
oprMap['^'] = 3;
oprMap['*'] = 2;
oprMap['/'] = 2;
oprMap['+'] = 1;
oprMap['-'] = 1;
2) iterate through given expression call these checks
1) if current element
i) is operand add it to result
ii) not operand do following check
a. while not (stack is empty and element is open bracket and found operator with higher precedence.
add top of the stack to the result and pop()
b. push current element to stack
iii) if open brackets push to stack
iv) if closed brackets pop until get closed bracket and add it to result
3) while stack is not empty pop() and add top element to the result.
{
stack<char>S;
for (int i = 0; i < n; i++) {
if(isOperand(exps[i])) {
res = res + exps[i];
} else if(isOperator(exps[i])){
while(!(S.empty() && isOpenParanthesis(S.top()) && isHeigherPrecedence(S.top(),exps[i])){
res = res+S.top();
S.pop();
}
S.push(exps[i]);
} else if(isOpenParanthesis(exps[i])) {
S.push(exps[i]);
} else if(isClosingParanthesis(exps[i])) {
while(!S.empty() && !isOpenParanthesis(S.top())) {
res = res+S.top();
S.pop();
}
S.pop();
}
}
while(!S.empty()) {
res = res + S.top();
S.pop();
}
}
}
#include<bits/stdc++.h>
using namespace std;
// This isHigher function checks the priority of character a over b.
bool isHigher(char a,char b)
{
if(a=='+' || a=='-')
return false;
else if((a=='*' && b=='*') || (a=='*' && b=='/') || (a=='/' && b=='*') ||
(a=='/' && b == '/')|| (a=='^' && b=='^')||(a=='*' && b=='^') || (a=='/' &&
b=='^'))
return false;
return true;
}
int main(){
string s;
cin>>s;
s = s + ")";
//Vector postfix contains the postfix expression.
vector<char>postfix;
stack<char>mid;
mid.push('(');
for(int i=0;i<s.length();i++)
{
if(s[i] == '(')
mid.push(s[i]);
else if(s[i] == '+' || s[i] == '^' || s[i] == '-' || s[i] == '*'||
s[i] == '/')
{
if(mid.top() == '(')
mid.push(s[i]);
else {
if(isHigher(s[i],mid.top()))
mid.push(s[i]);
else
{
while(mid.top()!='(')
{
if(!isHigher(s[i],mid.top()))
{
postfix.push_back(mid.top());
mid.pop();
}
else
break;
}
mid.push(s[i]);
}
}
}
else if(s[i] == ')')
{
while(mid.top() != '(')
{
postfix.push_back(mid.top());
mid.pop();
}
mid.pop();
}
else
postfix.push_back(s[i]);
}
for(int i=0;i<postfix.size();i++)
cout<<postfix[i];
return 0;
}

C++ returning boolean as 95

Problem with returning booleans in c++..
bool find( const TrieNode &node, const string word )
{
if (word.length() == 0)
{
if (node.isWord)
{
cout << "TRUE" << endl;
return true;
}
else
{
cout << "FALSE" << endl;
return false;
}
}
char firstletter = word.at(0);
int index = firstletter - 'a';
if (node.letters[index] == NULL)
{
return false;
}
else
{
find (*node.letters[index],word.substr(1,(word.length() - 1)));
}
}
in my main I have
cout << find(*mynode,"word") << endl;
would yield to :
FALSE
95
clearly, a cout of FALSE means that the function returns false.. However, when I print out the result of the function, I get 95 which evaluates to true.. Any reason why it could be doing this?
thanks
Your missing a final return statement, so your getting whatever is in the low byte of EAX, which is random garbage. your probably want return true; at the very end of your function.
Your should pump the warning level of your compiler as it should be telling you this (something along the lines of "not all control paths return a value").
The problem is with your final if statement:
if (node.letters[index] == NULL) {
return false;
}
else {
//if execution gets here, the return value of the function is undefined
find (*node.letters[index],word.substr(1,(word.length() - 1)));
}
...perhaps try:
if (node.letters[index] == NULL) {
return false;
}
else {
return find (*node.letters[index],word.substr(1,(word.length() - 1)));
}