Federico
Federico

Reputation: 1090

opening and reading a file whose name is given at runtime

My problem is how to use correctly the function infile.open().

I have a class that, among the others, has the following public properties:

class myclass {
public:
int rows
int columns
const char* array_file
}

All values are given at run-time.

When I call the function that uses a member of the class I have (pt is a pointer to a member of the class)

#include <vector>
#include <fstream>
#include <iostream>
typedef std::vector< std::vector<int> > Matrixint;

void function(myclass* pt) { 
    Matrixint array_name(pt->rows, std::vector<int>(pt->columns));

    std::ifstream infile;

    infile.open("%s", pt->array_file); // my problem: is this correct?
    for (int a = 0; a < pt->rows; a++) {
         for (int b = 0; b < pt->columns; b++) {
               infile >> array_name[a][b] ;
         }
    }
    infile.close();

}

Is this way of opening/reading the file correct?

The data in the file will be formatted as in this question (please note: only the array will be present in the file, no other data)

Upvotes: 1

Views: 1856

Answers (2)

sbi
sbi

Reputation: 224069

Assuming that my psychic abilities for fixing your question's code were right, I'd write it like this:

struct mine {
    int rows
    int columns
    std::string array_file
}

void function(const mine& m) { 
    Matrixint array_name(pt->rows, std::vector<int>(pt->columns));

    std::ifstream infile(m.array_file.c_str());

    for (int a = 0; a < ls->rows && infile.good(); ++a) {
         for (int b = 0; b < ls->columns && infile.good(); ++b) {
               infile >> array_name[a][b] ;
         }
    }

    if(!infile) 
        throw "Uh oh!"; // assume real error handling here
}

Why have I changed all these things?

  • A class with all public data isn't a class, but an aggregation of data. I'd use a struct for that, to not to confuse those who later need to maintain my code. (That might include me a few years down the road, which is a strong incentive to be very helpful.)
  • Unless you know exactly what you're doing (which doesn't seem to be the case), you should be using std::string rather than C-style strings.
  • Why pass the function parameter by pointer, when you can use a const reference?
  • std::ifstream has a constructor with which you can open a file immediately. I rarely ever use (or see used) its open() member function.
  • You need to test whether the file was opened and whether the input operations succeeded. (In this case, I merged the test whether it could be opened with the input operation succeed test, since the for loop is a pre-testing loop.) After the operations, I check whether an error occurred. Alternatively you could break out of the loop with an exception when reading fails.
  • Usually there is no need to close a stream, since its destructor already does this. If you make your variables as local as possible (which is good programming praxis), the file will be closed right away nevertheless.

Upvotes: 2

sergio
sergio

Reputation: 69027

infile.open gets as its first parameter the filename:

void open ( const char * filename, ios_base::openmode mode = ios_base::in );

(source)

I don't know what your filename is but maybe something like this (just a guess based on variable types) could do:

infile.open(pt->array_file); 

of course you have to ensure that the filename you pass in is correct at the time of calling that function.

Upvotes: 3

Related Questions