Build Errors

Write your question here.
When I build a solution to the program, I get the following error messages:

Error 1 error LNK2019: unresolved external symbol "double __cdecl expr(char *)" (?expr@@YANPAD@Z) referenced in function _main C:\Users\Documents\Visual Studio 2013\Projects\Ex6_10\Ex6_10\Ex6_10.obj Ex6_10

Error 2 error LNK1120: 1 unresolved externals C:\Users\Documents\Visual Studio 2013\Projects\Ex6_10\Debug\Ex6_10.exe Ex6_10

What is wrong and how do I fix this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  // EX6_10.cpp
// A program to implement a calculator

#include <iostream>                              // For stream input/output
#include <cstdlib>                               // For the exit() function
#include <cctype>                                // For the isdigit() function
using std::cin;
using std::cout;
using std::cerr;
using std::endl;

void eatspaces(char* str);                       // Function to eliminate blanks
double expr(char* str);                          // Function evaluating an expression
double term(const char* str, size_t& index);     // Function analyzing a term
double number(const char* str, size_t& index);   // Function to recognize a number

const size_t MAX{ 80 };                          // Maximum expression length, including '\0'
int main()
{
  char buffer[MAX] {};                           // Input area for expression to be evaluated

  cout << endl
    << "Welcome to your friendly calculator."
    << endl
    << "Enter an expression, or an empty line to quit."
    << endl;

  for (;;)
  {
    cin.getline(buffer, sizeof buffer);          // Read an input line
    eatspaces(buffer);                           // Remove blanks from input

    if (!buffer[0])                              // Empty line ends calculator
      return 0;
    try
    {
      cout << "\t= " << expr(buffer)             // Output value of expression
        << endl << endl;
    }
    catch (const char* pEx)
    {
      cerr << pEx << endl;
      cerr << "Ending program." << endl;
      return 1;
    }
  }
}


// Function to eliminate spaces from a string
void eatspaces(char* str)
{
  size_t i{};                                    // 'Copy to' index to string
  size_t j{};                                    // 'Copy from' index to string

  while ((*(str + i) = *(str + j++)) != '\0')    // Loop while character
    // copied is not \0
  if (*(str + i) != ' ')                         // Increment i as long as
    i++;                                         // character is not a space

  return;
}

// Function to evaluate an arithmetic expression
double expr(char* str)
{
  double value{};                                // Store result here
  size_t index{};                                   // Keeps track of current character position

  value = term(str, index);                      // Get first term

  for (;;)                                       // Indefinite loop, all exits inside
  {
    switch (*(str + index++))                    // Choose action based on current character
    {
    case '\0':                                   // We're at the end of the string
      return value;                              // so return what we have got

    case '+':                                    // + found so add in the
      value += term(str, index);                 // next term
      break;

    case '-':                                    // - found so subtract
      value -= term(str, index);                 // the next term
      break;

    default:                                     // If we reach here the string is junk
      char message[38] {"Expression evaluation error. Found: "};
      strncat_s(message, str + index - 1, 1);    // Append the character
      throw message;
      break;
    }
  }
}

// Function to get the value of a term
double term(const char* str, size_t& index)
{
  double value{};                                // Somewhere to accumulate the result

  value = number(str, index);                    // Get the first number in the term

  // Loop as long as we have a good operator
  while (true)
  {

    if (*(str + index) == '*')                   // If it's multiply,
      value *= number(str, ++index);             // multiply by next number

    else if (*(str + index) == '/')              // If it's divide,
      value /= number(str, ++index);             // divide by next number
    else
      break;
  }
  return value;                                  // We've finished, so return what 
  // we've got
}

// Function to recognize a number in a string
double number(const char* str, size_t& index)
{
  double value{};                               // Store the resulting value

  // There must be at least one digit...
  if (!isdigit(*(str + index)))
  { // There's no digits so input is junk...
    char message[31] {"Invalid character in number: "};
    strncat_s(message, str + index, 1);          // Append the character
    throw message;
  }

  while (isdigit(*(str + index)))                 // Loop accumulating leading digits
    value = 10 * value + (*(str + index++) - '0');

  // Not a digit when we get to here
  if (*(str + index) != '.')                     // so check for decimal point
    return value;                                // and if not, return value

  double factor{ 1.0 };                          // Factor for decimal places
  while (isdigit(*(str + (++index))))            // Loop as long as we have digits
  {
    factor *= 0.1;                               // Decrease factor by factor of 10
    value = value + (*(str + index) - '0')*factor;   // Add decimal place
  }

  return value;                                  // On loop exit we are done
}
It builds fine for me mate.

(that error message is alluding to your 'expr' function, but I can't see why).

you dont seem to be returning from that function from all possible paths. dunno if that has anything to do with it?
Last edited on
Linker errors always look scary. This type of error usually suggests that the arguments list in the function prototype are not the same as the arguments list in the function definition.

For example, if I were to change line 13 from double expr(char* str); to double expr(const char* str); then I get a similar error message. However, as mutexe said, the code you've posted seems to compile OK.
Thank you all for the reply. I am using Microsoft Visual Studio Express 2013 for desktops. I reloaded Visual Studio Express and ran the program again. Same result. Could it be that I need another version of Visual Studio Express.
If I run the code from the compiler linked on the forum, it doesn't recognize the strncat_s function. It looks like this requires the Windows <string.h> header to be included. http://msdn.microsoft.com/en-us/library/w6w3kbaf.aspx
Well, that can be got rid of by inserting #include <cstring> & changing the strncat_s to strncat (though user beware! There is no bounds-checking with vanilla strncat). For the version of VS I have, cstring & string.h are included via iostream, but I don't have VS2013, so I don't know for certain if that is still the case. It's worth a try, but I don't think that the error message is consistent with that missing header include.

The compiler error is basically saying :"You told me double expr(char* str); exists on line 13, but by the time I came to use it on line 37, I didn't have a definition"
If you want to replicate the error, #include <cstring> , change strncat_s to strncat, and comment out the definition of the expr function (lines 65-94). Then you'll get basically the same compiler error as the OP is reporting.

I can't see anything syntactically wrong with this code. Stylistically, there are some oddities such as mixing c-style strings with c++11 initializer lists (char buffer[MAX] {};). I'm sure this program could probably be done more easily & succinctly with std::strings & associated functions.

Maybe there's some other issue that I'm just not seeing, but I can't imagine what could be wrong with the OP's set-up to give that kind of error for the code that has been posted.
Last edited on
Topic archived. No new replies allowed.