LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-19-2008, 04:58 PM   #1
JMJ_coder
Member
 
Registered: Apr 2006
Distribution: Fedora
Posts: 478

Rep: Reputation: 30
Undefined Reference error


Hello,

When compiling my program, I received the following error message:

Code:
/tmp/ccbx5rJi.o: In function `evaluateExpression(theOperator, linkedStack<int>&, char*, int&)':
eval.cc:(.text+0x1cd): undefined reference to `outputExpression(int, char*, int)'
/tmp/ccbx5rJi.o: In function `computeOperator(theOperator, linkedStack<int>&, linkedStack<theOperator>&, char*, int&)':
eval.cc:(.text+0x3a4): undefined reference to `evaluateExpression(theOperator, linkedStack<int>&, char*, int)'
/tmp/ccbx5rJi.o: In function `main':
eval.cc:(.text+0x554): undefined reference to `computeOperator(theOperator, linkedStack<int>&, linkedStack<theOperator>&, char*, int)'
collect2: ld returned 1 exit status
All three functions mentioned are contained within the main file. They all have a function prototype listed at the top of the file. I am not sure where to even look to begin to debug this.
 
Old 03-19-2008, 05:24 PM   #2
matthewg42
Senior Member
 
Registered: Oct 2003
Location: UK
Distribution: Kubuntu 12.10 (using awesome wm though)
Posts: 3,530

Rep: Reputation: 65
We need more information:
  1. What commands did you use which generated this output?
  2. Please post your code.
 
Old 03-19-2008, 05:28 PM   #3
JMJ_coder
Member
 
Registered: Apr 2006
Distribution: Fedora
Posts: 478

Original Poster
Rep: Reputation: 30
Hello,

I hadn't issued any commands - I was merely compiling the program.

The following is the code:

Code:
/*
 *
 * This program will take a mathematical expression and evaluate
 * it according to the proper orders of precedence.
 *
 */

#include <iostream>
#include "linkedStack.h"


/* This struct will define the data type of the operator, which 
   consists of the operator sign itself and of a precedence level 
   to determine if this data will be put onto the operator stack 
   or if it will be immediately evaluated */

struct theOperator {
    int precedenceLevel;
    char operatorSign;
};


/* function prototypes */

int getOperand(char);
theOperator getOperator(char, int);
void computeOperator(theOperator, linkedStack<int>&, 
                     linkedStack<theOperator>&, char*, int);
void evaluateExpression(theOperator, linkedStack<int>&, 
                        char*, int);
void outputExpression(int, char*, int);


int main()
{
    char nextTokenIn;
    char expressionArray[80];
    int arrayIndex = 0;
    int currentOperand;
    int parenLevel = 0;
    theOperator currentOperator;
    linkedStack<int> operandStack;
    linkedStack<theOperator> operatorStack;

    std::cout << "Please begin to input the expressions:\n";

    while ((nextTokenIn = std::cin.get()) != '.') {
        expressionArray[arrayIndex++] = nextTokenIn;
        if (nextTokenIn == '(')
           parenLevel++;
        else if (nextTokenIn == ')')
           parenLevel--;
        /* todo: create error message for parenthesis levels */
        else if (isdigit(nextTokenIn)) {
            currentOperand = getOperand(nextTokenIn);
            operandStack.push(currentOperand);
        }
        else if (isalpha(nextTokenIn)) {
            currentOperator = getOperator(nextTokenIn, parenLevel);
            computeOperator(currentOperator, operandStack, 
                            operatorStack, expressionArray, 
                            arrayIndex);
        }
        else
            std::cin.ignore();
    }

    return 0;
}


/*
 * The getOperand function will take a number from the input stream 
 * and will assign it to an int variable. It takes the stream 
 * character by character and builds up a complete interger.
 *
 * Inputs: char tokenIn - the character from the input stream
 *
 * Returns: int num1 - the constructed integer
 */

int getOperand(char tokenIn)
{
    int num1 = (tokenIn - '0');
    
    while (!isspace(tokenIn = std::cin.get())) {
        num1 = (num1 * 10) + (tokenIn - '0');
    }

    return num1;
}


/*
 * The getOperator function will take a character from the input
 * stream and will assign it to a theOperator variable. It will 
 * also compute the precedence level for the variable and assign
 * that value to the theOperator variable.
 *
 * Inputs: char tokenIn - the character from the input stream
 *         int parenLevel - the variable to calculate the level 
 *                          of parenthesis in the expression
 *
 * Returns: theOperator currentOperator - the variable that holds
 *                      the operator and the precedence level
 */

theOperator getOperator(char tokenIn, int parenLevel)
{
    theOperator currentOperator;

    currentOperator.operatorSign = tokenIn;

    switch (currentOperator.operatorSign) {
        case ';':
            currentOperator.precedenceLevel = 0;
            break;
        case '+':
        case '-':
            currentOperator.precedenceLevel = 1;
            break;
        case '*':
        case '/':
            currentOperator.precedenceLevel = 2;
            break;
        /* default:
           error message */
    }

    currentOperator.precedenceLevel += (parenLevel * 10);

    return currentOperator;
}


/*
 * The computeOperator function will take the currentOperator and
 * analyze it to see what to do. If its precedence level is greater
 * than that on the top of the operator stack, it is pushed onto the 
 * operator stack. If and while its precedence level is greater than
 * or equal to the top of the stack, it is evaluated with a call to
 * evaluateExpression(); If the entire expression is completed, a 
 * call to outputExpression is made.
 *
 * Inputs: theOperator currentOperator - the variable that holds
 *                      the operator and the precedence level
 *         linkedStack<int>& operandStack - the operand stack; 
 *                      passed by reference to work directly on it
 *         linkedStack<theOperator>& operatorStack - the operator 
 *                      stack; passed by reference to work directly 
 *                      on it
 *         char* expressionArray - holds the entire expression 
 *                      which will be used to print out in the 
 *                      outputExpression() function
 *         int& arrayIndex - holds the index position for inserting
 *                      new tokens into expressionArray, will be 
 *                      reset to zero in outputExpression() function
 *
 * Returns: none by return, operandStack and operatorStack
 *                      by reference - result is
 */

void computeOperator(theOperator currentOperator,
                     linkedStack<int>& operandStack,
                     linkedStack<theOperator>& operatorStack,
                     char* expressionArray, int& arrayIndex)
{
    theOperator topOfStack;
    
    topOfStack = operatorStack.top();

    if (currentOperator.precedenceLevel > topOfStack.precedenceLevel)
        operatorStack.push(currentOperator);
    else if (currentOperator.precedenceLevel 
                            <= topOfStack.precedenceLevel) {
        operatorStack.push(currentOperator);
        topOfStack = currentOperator;
        while (currentOperator.precedenceLevel 
                              <= topOfStack.precedenceLevel) {
            operatorStack.pop();
            evaluateExpression(currentOperator, operandStack,
                               expressionArray, arrayIndex);
            topOfStack = operatorStack.top();
        }
    }

    /* todo: create error message if not enough operands */
}


/*
 * The evalusteExpression function will take the top two operands
 * from the operand stack and evaluate them with the operator that
 * is currently being processed.
 * 
 * Inputs: theOperator currentOperator - the variable that holds
 *                      the operator and the precedence level
 *         linkedStack<int>& operandStack - the operand stack; 
 *                      passed by reference to work directly on it
 *         char* expressionArray - holds the entire expression 
 *                      which will be used to print out in the 
 *                      outputExpression() function
 *         int& arrayIndex - holds the index position for inserting
 *                      new tokens into expressionArray, will be 
 *                      reset to zero in outputExpression() function
 *
 * Returns: none by return, operandStack by reference - result is
 *                      pushed back onto the operand stack
 */

void evaluateExpression(theOperator currentOperator, 
                        linkedStack<int>& operandStack,
                        char* expressionArray, int& arrayIndex)
{
    int righthandOperand, lefthandOperand, result;

    if (currentOperator.operatorSign == ';') {
        result = operandStack.top();
        operandStack.pop();
        outputExpression(result, expressionArray, arrayIndex);
    }
    else {
        righthandOperand = operandStack.top();
        operandStack.pop();
        lefthandOperand = operandStack.top();
        operandStack.pop();
    }

    /* todo: create error message if not enough operands */
    
    switch (currentOperator.operatorSign) {
        case '+':
            result = lefthandOperand + righthandOperand;
            operandStack.push(result);
            break;
        case '-':
            result = lefthandOperand - righthandOperand;
            operandStack.push(result);
            break;
        case '*':
            result = lefthandOperand * righthandOperand;
            operandStack.push(result);
            break;
        case '/':
            result = lefthandOperand / righthandOperand;
            operandStack.push(result);
            break;
    }
}


/*
 * The outputExpression function will print out the whole
 * expression that has been evaluated and also the result. This 
 * function will also clear out any values that need to be reset
 * to evaluate the next expression.
 *
 * Inputs: int result - the result of the expression
 *         char*& expressionArray - holds the entire expression 
 *                      which will be used to print out the 
 *                      expression entered
 *         int& arrayIndex - holds the index position for inserting
 *                      new tokens into expressionArray, will be 
 *                      reset to zero
 * Returns: none by return, char& expressionArray[] and
 *                      int& arrayIndex by reference and are flushed
 *                      clean of all data.
 */

void outputExpression(int result, char* expressionArray, 
                      int& arrayIndex)
{
    std::cout << std::endl << expressionArray 
              << " = " << result << std::endl;

    for (arrayIndex = 0; arrayIndex < 80; arrayIndex++) {
        *(expressionArray + arrayIndex) = '\0';
    }
    arrayIndex = 0;
}
 
Old 03-19-2008, 06:53 PM   #4
matthewg42
Senior Member
 
Registered: Oct 2003
Location: UK
Distribution: Kubuntu 12.10 (using awesome wm though)
Posts: 3,530

Rep: Reputation: 65
Quote:
Originally Posted by JMJ_coder View Post

I hadn't issued any commands - I was merely compiling the program.
Did gcc invoke itself? I'm asking how you ran the compiler - what options and arguments you used... in other words what command you entered to run the compiler.

I only examined evaluateExpression. The function prototype does not match the definition - in the prototype the fourth argument is an int, in the definition it is a reference to an int. You should make these match, and that when you call the function, that the types match also.
 
Old 03-19-2008, 07:06 PM   #5
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
That's exactly what it is. The compiler sees it as an overloaded function so you don't get any message during compilation.
ta0kira
 
Old 03-19-2008, 07:10 PM   #6
JMJ_coder
Member
 
Registered: Apr 2006
Distribution: Fedora
Posts: 478

Original Poster
Rep: Reputation: 30
Hello,

Quote:
Originally Posted by matthewg42 View Post
Did gcc invoke itself? I'm asking how you ran the compiler - what options and arguments you used... in other words what command you entered to run the compiler.
No options. Just:

% g++ eval.cc


Quote:
Originally Posted by matthewg42 View Post
I only examined evaluateExpression. The function prototype does not match the definition - in the prototype the fourth argument is an int, in the definition it is a reference to an int. You should make these match, and that when you call the function, that the types match also.


I can't believe I was so stupid. It was because I didn't match the prototypes with the function headers. The headers were correct, I forgot to tell the prototypes that the last int was a reference.

I guess that error message scared me half to death and froze my meager mind. I had never seen anything like it (shows how inexperienced I am) and didn't know where to look.

Thank you so much.
 
Old 03-20-2008, 01:27 AM   #7
matthewg42
Senior Member
 
Registered: Oct 2003
Location: UK
Distribution: Kubuntu 12.10 (using awesome wm though)
Posts: 3,530

Rep: Reputation: 65
You're welcome - a fresh pair of eyes is often useful, and I'm happy to provide them.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Undefined reference error jacques83 Programming 20 04-11-2013 07:23 AM
undefined reference to error in C++ knobby67 Programming 3 01-19-2008 10:34 PM
undefined reference error ilnli Programming 2 08-02-2007 08:34 PM
undefined reference error bahadur Programming 5 07-25-2006 09:18 PM
undefined reference error Quest101 Programming 3 01-01-2005 12:27 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:33 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration