Reputation: 189
this seems like it should be pretty simple, I'm probably leaving something simple out.
this is the code I'm trying to run. it is 3 files, 2*cpp and 1*header.
this wont run on code blocks, I'm trying to see what I'm missing!
these are the errors given:
obj\Debug\main.o||In function `main':|
|9|undefined reference to `generateArray(int*, int)'|
|11|undefined reference to `reverseOrder(int*, int*, int)'|
|13|undefined reference to `displayArray(int*, int*, int)'|
// lab6.h
#ifndef LAB6_H_INCLUDED
#define LAB6_H_INCLUDED
int const arraySize = 10;
int array1[arraySize];
int array2[arraySize];
void generateArray(int[], int );
void displayArray(int[], int[], int );
void reverseOrder(int [],int [], int);
#endif // LAB6_H_INCLUDED
// lab6.cpp
#include "lab6.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
using std::cout; using std::endl;
using std::rand; using std::srand;
using std::time;
using std::setw;
void generateArray(int array1[], int arraySize)
{
srand(time(0));
for (int i=0; i<10; i++)
{
array1[i]=(rand()%10);
}
}
void displayArray(int array1[], int array2[], int arraySize)
{
cout<<endl<<"Array 1"<<endl;
for (int i=0; i<arraySize; i++)
{
cout<<array1[i]<<", ";
}
cout<<endl<<"Array 2"<<endl;
for (int i=0; i<arraySize; i++)
{
cout<<array2[i]<<", ";
}
}
void reverseOrder(int array1[],int array2[], int arraySize)
{
for (int i=0, j=arraySize-1; i<arraySize;j--, i++)
{
array2[j] = array1[i];
}
}
// and finally main.cpp
#include "lab6.h"
int main()
{
generateArray(array1, arraySize);
reverseOrder(array1, array2, arraySize);
displayArray(array1, array2, arraySize);
return 0;
}
Upvotes: 0
Views: 189
Reputation: 7205
Don't use "using" directives when writing native C++ code as it pollutes the global namespace.
How do you tell the difference between constants with your naming convention? How about ARRAYSIZE instead of arraySize for constants and enums
Why are your arrays in the header file? your functions are for the "user" to use in main(). With this implementation the user cannot change ARRAYSIZE can he. In fact, is there even a need for ARRAYSIZE when the functions are designed to work with arrays of arbitrary size?
Pass arrays by pointer, passing by value is slower and more expensive
lab6.cpp
#include "lab6.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
//#include <iomanip>
void generateArray(int* array1, int arraySize)
{
// make implicit type conversions explicit
std::srand((unsigned)std::time(0));
// why the magic number here?
for (int i=0; i<10; i++)
{
array1[i]=(std::rand()%10);
}
}
void displayArray(int* array1, int* array2, int arraySize)
{
std::cout << std::endl << "Array 1" << std::endl;
for (int i=0; i<arraySize; i++)
{
std::cout<<array1[i]<<", ";
}
std::cout << std::endl << "Array 2" << std::endl;
for (int i=0; i<arraySize; i++)
{
std::cout<<array2[i]<<", ";
}
}
void reverseOrder(int* array1, int* array2, int arraySize)
{
// This is hard to read, and why do you need another integer anyway
// for (int i=0, j=arraySize-1; i<arraySize;j--, i++)
// {
// array2[j] = array1[i];
// }
for(int i=0;i<arraySize;i++)
{
array2[arraySize - i - 1] = array1[i];
}
}
lab6.h
#ifndef LAB6_H_INCLUDED
#define LAB6_H_INCLUDED
void generateArray(int* array1, int arraySize);
void displayArray(int* array1, int* array2, int arraySize);
void reverseOrder(int* array1, int* array2, int arraySize);
#endif // LAB6_H_INCLUDED
main.cpp
#include "lab6.h"
int main()
{
int const arraySize = 10;
int array1[arraySize];
int array2[arraySize];
generateArray(array1, arraySize);
reverseOrder(array1, array2, arraySize);
displayArray(array1, array2, arraySize);
return 0;
}
Upvotes: 0
Reputation: 224079
Concluding from the linker's error messages, it seems that you haven't given the linker both object files, and it cannot find what you defined in lab6.cpp
. I don't know CodeBlocks, so I don't know how you would have to setup your project so that the linker gets passed all the object files.
Most compilers, however, would invoke the linker with all the object files they generate, so manually invoking the compiler
cc lab6.cpp main.cpp
(substituting your compiler for "cc") might do.
Anyway, once you managed that, you will still have linker errors, because your arrays are defined in the header, which makes them end up in two translation units. The linker will complain about duplicate symbols then.
Other than that, I'd criticize that
arraySize
(because you haven't used it everywhere), int
to specify the size of the arrays instead of std::size_t
and Oh, and I would remove all the using declarations and prefix identifiers with std::
, where needed. In your case it would even save typing. Also, it makes the code clearer (some would argue against this) and it is less error prone (hard to argue against that).
Upvotes: 1
Reputation: 95509
Firstly, take the following snippet of code out of your header file:
int const arraySize = 10; int array1[arraySize]; int array2[arraySize];
Move the code above inside your main function. If you put these in the header file, you are making them into global variables, which is a really bad idea. Moreover, since these are definitions, not declarations, they will be created multiple times (once for each compilation unit -- i.e., .cpp source file -- that includes the header), which will result in a multiple definition error if you were to link "lab6.o" and "main.o" together.
Secondly, it appears that you have compiled "main.cpp" to "main.o" but then you have forgotten to compile "lab6.cpp" to "lab6.o" and to link "lab6.o" with "main.o", together. I don't know how to do this with Code::Blocks, although I suspect it involves checking "lab6.cpp" so that it is included in the build. If you are willing to use the commandline to build and you have the g++ compiler, then you can use:
g++ main.cpp -c -o main.o g++ lab6.cpp -c -o lab6.o g++ main.o lab6.o -o lab6
With the above, you can then invoke ./lab6
to run your program. You may want to use a build system such as CMake or Make (I recommend CMake) to build your program instead of relying on Code::Blocks.
Also, assuming you are permitted to do so, it is highly advisable that you use std::vector instead of primitive arrays. Of course, your assignment might be requiring you to use regular arrays, in which case that wouldn't be possible. Also, it is generally better to use std::size_t instead of int as an indexing type, although int will work, and if you use std::size_t (which is unsigned) it might cause problems with some of your loops, so contrary to the suggestion of one of the other answerers, I'd advise you just stick with int at this point (though, in the future, you should probably use std::size_t as your array size/index type).
Upvotes: 0
Reputation: 4932
No, you haven't. You have two cpp files, that contain
int array1[arraySize];
int array2[arraySize];
lib6.cpp and main.cpp compile normally but duranig linking of course there is an error: "multiple definition of array1 ..."
Upvotes: 0