Issues with functions

Hi there! For a class project, we are supposed to write a code that basically works as a magic 8 ball. I think I got most of the things, but I can't really test it out since I keep getting an error saying this:

/tmp/ccJtJJrE.o: In function `main':
:(.text.startup+0xcf): undefined reference to `eightBall(std::string)'
collect2: error: ld returned 1 exit status

I think it's something about the function prototype for "eightBall" but I don't really know what to do. I can't just go the easy way and get rid of all the functions because that is a requirement, also I can't get rid of the string(s) or arrays.
Any help is appreciated and welcomed, so are any critics on areas of the code I can close up. Thanks!

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
// Example program
#include <iostream>
#include <string>
#include <cstdlib> 
#include <ctime> 
using namespace std;
//Function Prototypes
int randNumber(int); //Get random number
void eightBall(string);//connect
//Universal Variable
const int ARRAY_SIZE = 8;
string ballResponse[ARRAY_SIZE];

int randNum;
int main()
{
    
  string question, name, printString;
  cout << "Please enter your name to start!:" << endl;
  getline(cin,name);
  cout << "\n\nWelcome to the Magic 8-ball game, " << name << "!\n\n";
  cout << "Please enter your yes or no question." << endl;
  getline(cin,question);
    cout << "\n\n\n\n\n\n\n";
    cout << question << endl;
    eightBall(ballResponse[ARRAY_SIZE]);
 
}//End of Main

int randNumber(int randNum){
    
srand(time(0)); //STEP 4 of 5 for random numbers
randNum = rand() % 9; //STEP 5 of 5 for random numbers
return randNum;

}// End of randNumber

void eightBall(string ballResponse[ARRAY_SIZE]){
    //Responses
        ballResponse[0] = " As I see it, yes.";
        ballResponse[1] = "Don't count on it.";
        ballResponse[2] = "You may rely on it.";
        ballResponse[3] = "Outlook good.";
        ballResponse[4] = "My sources say no.";
        ballResponse[5] = "It is decidedly so.";   
        ballResponse[6] = "My reply is no."; 
        ballResponse[7] = "Outlook not so good."; 
    //Get response
    cout << randNum%ARRAY_SIZE;    



}
Last edited on
Hello BGA6444,

What is the difference between:

1
2
3
//Function Prototypes

void eightBall(string);//connect 

and
1
2
3
// Function definition.

void eightBall(string ballResponse[ARRAY_SIZE])


They both need to match.

And the function call is just the name of the variable or variables.

Hope that helps,

Andy

P.S. if you define a global variable you do not need to pass it to a function.
Last edited on
Hi Andy!

I tried various variations of that but I just got different errors.

When I put void eightBall(string ballResponse[ARRAY_SIZE]);//connect
I get this error:
9:36: error: 'ARRAY_SIZE' was not declared in this scope
In function 'int main()':
26:38: error: cannot pass objects of non-trivially-copyable type 'std::string {aka class std::basic_string<char>}' through '...'

When I put void eightBall(string ballResponse);
I get
/tmp/cc8qTJ8g.o: In function `main':
:(.text.startup+0xcf): undefined reference to `eightBall(std::string)'
collect2: error: ld returned 1 exit status

When I put void eightBall(string ballResponse[]);//connect
I get
In function 'int main()':
26:39: error: cannot convert 'std::string {aka std::basic_string<char>}' to 'std::string* {aka std::basic_string<char>*}' for argument '1' to 'void eightBall(std::string*)'

When I put void eightBall(string [ARRAY_SIZE]);//connect
I get
9:24: error: 'ARRAY_SIZE' was not declared in this scope
In function 'int main()':
26:39: error: too many arguments to function 'void eightBall()'
9:6: note: declared here

Then when I put void eightBall(string []);//connect
I get
In function 'int main()':
26:39: error: cannot convert 'std::string {aka std::basic_string<char>}' to 'std::string* {aka std::basic_string<char>*}' for argument '1' to 'void eightBall(std::string*)'

So I don't know since it isn't working.
@BGA6444,
The statements in int main() are compiled on the basis of what they know about at the time (i.e. functions declared or defined before them). Line 26 (which is wrong anyway) tries to call a function defined by the prototype on line 9 ... which does not match the actual function whose definition starts on line 38: the prototype has a scalar argument; the defined function has an array argument.

Change line 9 to match the actual function:
void eightBall(string[]); //Note the array argument signified by the []

Change the call on line 26 (it doesn't need a declared array size there):
eightBall(ballResponse);


That will probably get your code to compile, at least. They are also what @Handy Andy has already told you ... and you simply ignored him.


However, there are a lot of further problems with it.
- Don't declare ballResponse[] as a global variable if you also want it as an argument to function eightBall().
- Call srand() ONCE, probably at the beginning of main(), not on every call to your random-number supplier ... otherwise you are very likely to get the same number coming back at you repeatedly.
Last edited on
Hello BGA6444,

Between what I said earlier and what lastchance has said it is a good start.

The first error you have talked about has to do with the prototype not matching the function definition.

What I find to work the best is to write the prototype and then use it for the function definition or vice versa. It depends on what I am thinking about at the time. Although the prototype only needs to know what type of variable(s) are needed by the function I like to I like to write the prototype with the variable name. My VS IDE will use the information from the prototype to give a hint of what is needed when writing the function call.

When you write something like int FunctionName(int num);. "num" may be defined in "main", but in the function definition "num" becomes a local variable to the function. That is why you can use the same name in two or more different places.

Your next error, out of order:

9:24: error: 'ARRAY_SIZE' was not declared in this scope
In function 'int main()':
26:39: error: too many arguments to function 'void eightBall()'
9:6: note: declared here


Looking at your code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Example program
#include <iostream>
#include <string>
#include <cstdlib> 
#include <ctime>

using namespace std;

//Function Prototypes
int randNumber(int); //Get random number
void eightBall(string);//connect
//void eightBall(string ballResponse[ARRAY_SIZE]);//connect

//Universal Variable
const int ARRAY_SIZE = 8;
string ballResponse[ARRAY_SIZE];

I added some blank lines to make it easier to read and understand.

Notice the two parts in bold. You are trying to use "ARRAY_SIZE" before it is defined.

The compiler basically works on one line at a time, so on line 12 "ARRAY_SIZE" has not been defined yet.

What yo want to do is something like 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
// Example program
#include <iostream>
#include <string>
#include <cstdlib> 
#include <ctime> 

//using namespace std;  // <--- Best not to use.

using std::cin; // <--- Better choice if you must use something.
using std::cout;
using std::endl;
using std::string;

const int ARRAY_SIZE = 8; // <--- From C++11 on constexpr size_t ARRAY_SIZE{ 8 };.

//Function Prototypes
int randNumber(int); //Get random number
void eightBall(const string ballResponse[ARRAY_SIZE]);//connect

//Universal Variable // <--- Global variables are best avoided. These should be in "main".
int randNum;
const string ballResponse[ARRAY_SIZE]
{
	" As I see it, yes.",
	"Don't count on it.",
	"You may rely on it.",
	"Outlook good.",
	"My sources say no.",
	"It is decidedly so.",
	"My reply is no.",
	"Outlook not so good."
};

By putting "ARRAY_SIZE" at line 14 the compiler will know about the variable before it is first used on line 18. This will correct one error.

Lines 22 - 32 will define the variable and initialize it to the values given. This could be done in one line, this way it is easier to understand.

In the end both of these variables, lines 21 and 22, should be put in main and passed to the functions as your prototypes suggest.

The other thing I found is when I defined line 22 as a "const" I had to change the prototype and function definition for the function call and every thing else to work properly.

In "main" as lastchance pointed out "srand()" only needs done once. I have found this to be one of the best ways to write this line: srand(static_cast<size_t>(time(nullptr)));. Looking at http://www.cplusplus.com/reference/cstdlib/srand/?kw=srand you will notice the what is sent to "srand" is an "unsigned int". The problem is that "time" does not return an "unsigned int", do it needs to be type cast.

Looking at http://www.cplusplus.com/reference/ctime/time/?kw=time you can see what "time" returns and how it is used. Somewhere I remember reading that the value sent to "time" should be "nullptr" although (0) zero and NULL will work "nullptr" is the better choice.

In your function call all you need is the variable name(s) and nothing else. In your case "[ARRAY_SIZE]" is not needed.

At the end of "main" return 0;is not necessary or required, but I think it is good form and it makes a really good break point when debugging the program.

That should be enough to get the code to compile, but as lastchance pointed out once the code compiles and runs there are more problems with your code.

First you should get the code to compile then when you can run it the other problems will show up.

Here is a tip: When you write a prompt this tends to look better:
cout << "Please enter your name to start!: ";. By ending the quoted string with ": " and leaving out the "endl" this puts the "cin" on the same line as the prompt. My personal choice I tend to like this way better. Also most times I will start the quoted string with "\n ". For me this is one line off the top of the screen and one space in. It makes it easier to read for me.

Work on getting the code to compile for now and we can fix the other problems later,

Hope that helps,

Andy
Topic archived. No new replies allowed.