tags:

views:

111

answers:

4

this seems like it should be pretty simple, im probably leaving something simple out.

this is the code im trying to run. it is 3 files, 2*cpp and 1*header.

this wont run on code blocks, im trying to see what im 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;
}
A: 

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 ..."

Max
But i need to do that otherwise main.cpp has no array initialisation??
ace
What does it mean? I need to do it. It is not permitted by c++, so C++ doesn't want you to need it.Don't use global variables.Think about some interface like that: void GenerateArray(int size, vector<int>* array); void DisplayArray(const vector<int> void ReverseOrder(vector<int>* array);
Max
So, you function can return generated arrays, not writing to the global ones.
Max
when i say i need to, i mean i dont understand another way of doing it.if i just define them inside of main, the same problem comes up
ace
@ace: No, it's a different problem, because the error messages are different.
sbi
Declare inside main() int array1[arraySize]; int array2[arraySize];in your lab6.h declare these 3 functions:void GenerateArray(int size, int* array);void DisplayArray(int size, const int* array);void ReverseOrder(int size, int* array);in main() you run these funtions like that:GenerateArray(10, array1);GenerateArray(10, array2);ReverseOrder(10, array1);ReverseOrder(10, array2);DisplayArray(10, array1);DisplayArray(10, array2);int lab6.cpp file realize these funtions with prototypes as I wrote.It is better your function write to array, that you give by params.
Max
@Max: These functions are already using the parameters given. It just so happens that ace gave those parameters the same name as the global variables.
sbi
Pls, somebody, when I write comment how to make sentence come in new line?
Max
@Max: Comments are not meant for this kind of lengthy explanation. They are comments. You can however edit your answer and put it in there in pretty formatting.
Space_C0wb0y
@sbi: Oh, sorry. yes, you are right.
Max
@Space_C0wb0y: Ok!
Max
A: 

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

  • you use global variables instead of local ones (once you fixed that, they are also not defined in two translation units anymore),
  • the code would blow up if you changed arraySize (because you haven't used it everywhere),
  • you use int to specify the size of the arrays instead of std::size_t and
  • you use C arrays instead of C++' containers (which might be required, as this is homework).

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).

sbi
thanx, so where should i be defining my arrays?
ace
@ace: As locally as possible, so within `main()`.
sbi
@sbi, cc is the C compiler, not the C++ compiler.
Michael Aaron Safyan
@Michael: Can you tell I'm not a command line user? `:)` Please feel free to correct my answer.
sbi
A: 

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).

Michael Aaron Safyan
@Micheal: Since the loops are iterating over array indexes, too, I would rather suggest using `std::size_t` for the loop indexes as well.
sbi
A: 

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;
}
aCuria