views:

137

answers:

4

Hi I have a text file containing two arrays and one value(all integers) like this

3 90 22 5 60 33 24

Where the first number stands for how many integers to read in. I can read in all this in one function. Do I need several functions to be able to use the different matrices and the first variable?

    ifstream in(SOMEFILE.dat);
    if (!in) {
    cerr << "Cannot open file.\n";
    return -1;}
    in >> VAR;
    A=new int[VAR]; 
    B=new int[VAR];
    for(int i=0 ;i<VAR;i++){
      in >>A[i];
    }
 for(int i=0 ;i<VAR;i++){
      in >>B[i];
    }

       in.close();

Above is the code I have so far and this would work in the main function. Do I have to write three functions to read this info in so I can use it in my program or is there any way I could for example send in three pointers to a function?

I would like A to be 90 22 5
B to be 60 33 24
And VAR to be 3

Thanks

+3  A: 

Whenever you want to group together data items, use a class or a structure. For example, to pass three integers as x, y and z coordinates,:

struct Coord {
   int x, y, z;
};

and then pass the structure to the function:

void f( Coord & c ) {
}

The same goes for arrays, but in your case you would make the structure contain pointers.

Your question actually opens up huge areas of C++ programming that it seems you are not aware of. Some things you should read up on before you go any further:

  • the concept of structures, as outlined above
  • constructors and destructors for structures
  • when and when not to use dynamic memory allocation
  • use of C++ standard library containers like std::vector

This may seem a lot, but once you have a clear grip on these, you will find C++ programming much, much easier and safer.

anon
Thanks alot! I actually know a bit of the above. However the course I took in c++ always used classes in examples with linked lists and I just didn't think of it in this example where I dont need the different Arrays together later in the code. I understand the concepts, but I lack the experience to use them wisely...
mrbuxley
@mrbuxley Gah! The linked list! Curse of all trainee programmers! For my opinions on the damn things see http://punchlet.wordpress.com/2009/12/27/letter-the-fourth/
anon
(=What Im actually doin is rewriting a working code to make it as effecient as possible. A bit off topic here. But shoul I go with Vectors or dynamical arrays if we're talking array sizes of 256*256?
mrbuxley
@mrbuxley As you say a bit OT - you might be better off asking another question. If it were me, I'd definitely investigate using a matrix library rather than writing it myself.
anon
+2  A: 

The easiest way is to define a type, say a struct, that represents the data from one line:

struct MyMatrix
{
  int size;
  int *a;
  int *b;
};

Then write a function that reads one such instance from a line of text:

struct MyMatrix load_matrix(std::ifstream& stream)
{
  MyMatrix m;

  stream >> m.size;

  m.a = new int[m.size];
  for(int i=0 ;i < m.size; i++)
      stream >> m.a[i];

  m.b = new int[m.size];
  for(int i=0 ;i < m.size; i++)
      stream >> m.b[i];

  return m;
}

This code lacks error-checking, but you can add that. Remember that memory allocation can fail.

unwind
A: 

Or just use params by reference.

int theFunction(int*& arrayA, int*& arrayB){
    int size;
    // ...
    arrayA = new int[size];
    arrayB = new int[size];
    // ...
    return size;
}
VDVLeon
+1  A: 

When you want to return multiple elements you can either use additional output parameters in your functions (passed by reference) or return a tuple. I tend to prefer the later option as it results in more readable code.

Instead of manually managing the memory of your arrays with new and delete[], you can use a std::vector to achieve an equivalent behavior. Each vector stores its own size so that you don't need to return an additional variable for that.

To summarize, in this case you can just return a tuple of two vectors. In the standard library, two-element tuples are represented with the std::pair class. Therefore, your function will return a pair of vectors: std::pair<std::vector<int>, std::vector<int> >. Since that is a lot to type, you better use a typedef.

This is one possible implementation of your function. Note that you can avoid manually written loops thanks to the standard istream_iterator class:

typedef std::pair<std::vector<int>, std::vector<int> > Data;
Data read(std::ifstream & ifs)
{
    int n;
    ifs >> n;
    typedef std::istream_iterator<int> in_it;

    std::vector<int> a(n);
    std::copy(in_it(ifs), in_it(), a.begin());

    std::vector<int> b(n);
    std::copy(in_it(ifs), in_it(), b.begin());

    return Data(a, b);
}

And this is how you would use your function. Notice how you are not returning the size implicitly but you can retrieve it easily through std::vector::size().

int main() {

  std::ifstream ifs("SOMEFILE.txt");
  Data data = read(ifs);

  unsigned int n = data.first.size();
  std::vector<int> & a = data.first;
  std::vector<int> & b = data.second;

  return 0;
}

EDIT: Neil's suggestion of using a dedicated struct scales better and leads to more readable code, so you should certainly consider that as well. In this case your struct would be:

struct Data {
    std::vector<int> a, b;
};

And your main function would be identical except that you have to replace first and second with a and b.

Manuel