passing object to function, columns class


 
Thread Tools Search this Thread
Top Forums Programming passing object to function, columns class
# 1  
Old 04-12-2011
passing object to function, columns class

I am working on a small columns class, since I use allot of tabular data. I am trying to set up code to allow me to efficiently read in tabular data, manipulate it, and write to output files. I more or less know what I need to do, but there are many options to sort through.

I have the beginnings of a columns class, without access functions and such. This also includes a vector of class that will hold one object for each col.
Code:
class column_data {

public:

   // initialize class members
   column_data()
      : scaleMin(0.0),
        scaleMax(0.0),
        content(""),
        type(""),
        scale_type("") ,
        header("")  { }

   float scaleMin, scaleMax;
   std::string content, type, scale_type, header;
   std::vector<std::string> inputDataString;
   std::vector<char> inputDataChar;
   std::vector<int> inputDataInt;
   std::vector<float> inputDataFloat;

};

// create vector of column_data objects
std::vector<column_data> columns;

There is some meta data here (like the content field), that will probably end up in a different class. I have vectors for the different data types that could be in the data. Only one of these would get populated, depending on the value of "type".

I am reading all of the data and storing each row in a vector of string,
Code:
   // create an input stream and open the input file
   ifstream splitsInput;
   splitsInput.open( splitsInFile.c_str() );

   // read in each line
   while(getline(splitsInput,newSplitsLine)) {
      // remove '\r' EOL chars
      newSplitsLine.erase (remove(newSplitsLine.begin(),newSplitsLine.end(),'\r') , newSplitsLine.end());
      // store row data in vector of string
      storeSplitsRows.push_back(newSplitsLine);
   }

Then I can create an object for each col by parsing the first row,
Code:
   colsRowStream << storeSplitsRows[0];
   int i = 0;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      // create new column data object
      column_data newCol;
      // add to vector
      columns.push_back(newCol);
      i++;
   }
   // clear the buffer
   colsRowStream.clear();

Now I have an object for each col and can begin processing the other rows.

I would like to make processing a function where I would add a row to the string stream, select a target variable in the class for the parsed data to go, and pass the stringstream and the target to a loading function.
Code:
// accepts a string stream and parses the data in to columns
int row_toCols(stringstream colsRowStream){
   int i = 0;
   std::string rowCell

   // parse row into cells by tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      columns[i].content = rowCell;
      i++;
   }
   // clear the buffer
   colsRowStream.clear();
}

// load first row into string stream
colsRowStream << storeSplitsRows[0];
row_toCols( stringstream colsRowStream);

The code above results in the data in the first row being parsed by tab and deposited in the content string var of each object. What I need to do is to be able to pass the target in the call so I can re-use this function to populate the rest of the data structure. I guess I would set the function to look for a pointer to an object, and then pass the object using the & operator, but there are always allot of ways of doing this kind of thing, so I'm not sure. I also need the code to handle different data types other than string. I could have different loading functions for different data types if that is necessary.

If I am going about this whole thing in the wrong way, now would be a good time to say so. Smilie The loading function will probably be a class method at some point.

LMHmedchem
# 2  
Old 04-12-2011
Keeping them as vectors but not using 2/3 of the vector positions is very wasteful. Why have all those different types anyway, instead of one class that contains a string and has operators to return float, int, char? It'd let you keep everything in one vector.

Why do you store each and every row in a vector when you don't need them later? Why not process the row then discard it?

Quote:
I would like to make processing a function where I would add a row to the string stream, select a target variable in the class for the parsed data to go, and pass the stringstream and the target to a loading function.
I don't understand this at all, but I think I sort of get your pseudocode -- you want to load data from a string.

Well, you already have a function that loads strings, though it opens files and reads lines to get the strings. You could make a more general-purpose string loading member function that's used by your file loader and external things alike.

If you really wanted to process stringstreams, you could do that with your existing file-loading code, since stringstreams act just like file streams. You just need to make everything more general: A function that loads from a stream, which your file-opening member could use too, instead of just one member which loads from a filename and nothing else.
# 3  
Old 04-12-2011
Quote:
Originally Posted by Corona688
Keeping them as vectors but not using 2/3 of the vector positions is very wasteful. Why have all those different types anyway, instead of one class that contains a string and has operators to return float, int, char? It'd let you keep everything in one vector.
I have changed this into 2 classes. In some files I have, the first several rows are like extended header rows that give information about the data type and exactly what is stored in the column. I am now creating a metadata object for each col to hold the info from these first rows, and then a second object to hold the actual data. I put the different vector types into the class because the columns could contain any of those data types. For each column, only one vector will have data added to it. I presumed that the declaration of the vectors doesn't cost any significant resource since they have no size at that point.

Quote:
Originally Posted by Corona688
Why do you store each and every row in a vector when you don't need them later? Why not process the row then discard it?
This is probably temporary, in that I tend to start with a method that I know will work. In some cases, I need to look at allot of the data before I decide what to do with it, so I may not be able to process it one row at a time.

Quote:
Originally Posted by Corona688
I don't understand this at all, but I think I sort of get your pseudocode -- you want to load data from a string.
I need to load tabular data from a text file. Reading the data into a string for each row, and then parsing the row by the delimiter is the only way I know how to do that at the moment.

Here is an updated version of the code.
Header file,
Code:
// class columns in columns .h

class col_metadata {
public:
   // initialize class members
   col_metadata()
      : scaleMin(0.0),
        scaleMax(0.0),
        content(""),
        type(""),
        scale_type("") { }

   float scaleMin, scaleMax;
   std::string content, type, scale_type, header;
};

class column_data {
public:
   // initialize class members
   column_data()
      : header("") { }

   std::string header;
   std::vector<std::string> inputDataString;
   std::vector<char> inputDataChar;
   std::vector<int> inputDataInt;
   std::vector<float> inputDataFloat;
};

std::vector<col_metadata> metadata;  // create vector of col_metadata objects
std::vector<column_data> columns;  // create vector of column_data objects

Main function,
Code:
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>

#include "columns.h"

using namespace std;

// creates a data object and meta data object for each column
int createColObjs( stringstream &colsRowStream ){
   std::string rowCell;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      // create new column data object
      col_metadata newColMeta;  metadata.push_back(newColMeta);
      // create new column data object
      column_data newCol;  columns.push_back(newCol);
   }
   // clear the buffer
   colsRowStream.clear();
}


int main(int argc, char **argv) {

// declarations for args
   // file names
   int cmdArguments;
   std::string colsInFile, splitsInFile, outputFile;

//---------------------------------------------------------------------
//  Parse command line arguments
while ((cmdArguments = getopt (argc, argv, "c:i:o:d:h")) != -1)
   switch (cmdArguments)
   {
      case 'c':
         colsInFile = optarg;
      break;
      case 'i':
         splitsInFile = optarg;
      break;
      case 'o':
         outputFile = optarg;
      break;
      case 'd':
         //set delimiter;
      break;
      case 'h':
         std::cout << std::endl; // print help blurb
         exit(0);
      break;
   }

//---------------------------------------------------------------------
// check args

   if(splitsInFile.length() == 0) {
      std::cout << "  -> no input file was specified" << std::endl;
      return(-1);
   }
//---------------------------------------------------------------------
// declarations
   int i; // loop iterator
   std::string newSplitsLine, rowCell;
   std::vector<std::string> storeSplitsRows;    // storage structure for input rows
   stringstream colsRowStream;

//---------------------------------------------------------------------

   // create an input stream and open the parameter file
   ifstream splitsInput;
   splitsInput.open( splitsInFile.c_str() );

   // read innput file and store,
   while(getline(splitsInput,newSplitsLine)) {
      // remove '\r' EOL chars
      newSplitsLine.erase (remove(newSplitsLine.begin(),newSplitsLine.end(),'\r') , newSplitsLine.end());
      // store row data in vector of string
      storeSplitsRows.push_back(newSplitsLine);
   }

   //use first row to create objects for each col
   colsRowStream << storeSplitsRows[0];
   createColObjs ( colsRowStream );


   // load information from metadata row 0 to metadata[i].content
   colsRowStream << storeSplitsRows[0];
   i = 0;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      metadata[i].content = rowCell;
      i++;
   }
   // clear the buffer
   colsRowStream.clear();

   // load information from metadata row 1 to metadata[i].type
   colsRowStream << storeSplitsRows[1];
   i = 0;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      // add header row content to content field
      metadata[i].type = rowCell;
      i++;
   }
   // clear the buffer
   colsRowStream.clear();

   // load information from metadata row 1 to metadata[i].scale_type
   colsRowStream << storeSplitsRows[2];
   i = 0;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      // add header row content to content field
      metadata[i].scale_type = rowCell;
      i++;
   }
   // clear the buffer
   colsRowStream.clear();

   std::cout << std::endl;
   for (i=0; i<metadata.size(); i++) {
      std::cout << "metadata[" << i << "].content     " << metadata[i].content << std::endl;
      std::cout << "metadata[" << i << "].type        " << metadata[i].type << std::endl;
      std::cout << "metadata[" << i << "].scale_type  " << metadata [i].scale_type << std::endl;
      std::cout << std::endl;
   }

} // main EOF brace

This compiles and runs, giving the expected output. I have attached the src. This part just loads the data from the first few rows into the respective col objects. Later code would load the actual data, rows 7-11 in the attached data file, into a vector of the appropriate type. There is an issue that I am loading from the input file and storing as a string, and then parsing the string, possibly to int or real. I know you can convert from string to real, etc, but that seams like a silly solution. The issue is that the rows of data contain all kinds of types, so I'm not sure what else to do.

The above code is written out in blocks, where it is obvious that there should be a function to load data,
Code:
// accepts a string stream and parses the data in to columns
int metadata_row_toCol( stringstream &colsRowStream ){
   int i = 0;
   std::string rowCell;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      metadata[i].content = rowCell;
      i++;
   }
   // clear the buffer
   colsRowStream.clear();
}

colsRowStream << storeSplitsRows[0];
metadata_row_toCol( colsRowStream ); // loads the first row to metadata[i].content

This function works but I need to be able to pass the object.var that is being populated in the second function, since it can't be hardcoded to metadata[i].content like above.

I hope that makes it a bit more clear as to what I'm trying to do, although I'm sure it makes it no more certain I'm going about it the right way.

LMHmedchem

Last edited by LMHmedchem; 04-12-2011 at 06:58 PM..
# 4  
Old 04-12-2011
Quote:
Originally Posted by LMHmedchem
I need to load tabular data from a text file. Reading the data into a string for each row, and then parsing the row by the delimiter is the only way I know how to do that at the moment.
Sure, but why pass it as a stringstream? Why not just pass it as a string?

Or if you really want to pass it a stringstream, why not make one function to handle file streams and stringstreams? The whole point of a stream is you don't have to care what kind it is...
Quote:
I know you can convert from string to real, etc, but that seams like a silly solution.
Oh, I see. You want a stringstream so that you can stream>>vartype with it.

It's a choice between
Code:
if(vartype==1) stream>>vartype1;
else if(vartype==2) stream>>vartype2;
...

and
Code:
if(vartype==1) sscanf(string, "%f", &vartype1);
else if(vartype==2) sscanf(string, "%d", &vartype2);

Be honest with yourself: There's no way around sheer brute force either way, they're equally ugly. >> looks prettier but is harder to check for errors and more difficult to process formatted input with.

You can indeed pass a string stream pointer that way, by the way, but you have to use its members with -> instead of .



Another concept that may help you is the union, with which you can build one class to hold many types.

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class multitype
{
public:
        multitype(const char *i):e(strdup(i)),type(T_CSTRING)   { }
        multitype(float i):c(i),type(T_FLOAT)   { }
        multitype(char i):b(i),type(T_CHAR)             { }
        multitype(int i):a(i),type(T_INT)               { }

        inline operator int() const     { return(a); }
        inline operator float() const   { return(c); }
        inline operator char() const    { return(b); }
        inline operator const char *() const    { return(e); }

        ~multitype()
        {       if(type==T_CSTRING) free(e);            }

protected:
        enum { T_INT, T_CHAR, T_FLOAT, T_DOUBLE, T_CSTRING } type;

        // All members of a union occupy the SAME memory.
        // You can't use more than one at once.
        union
        {
                int a;
                char b;
                float c;
                char *e;
                // You cannot put classes in a union though, since it won't know
                // which constructor to use!
        };
};

int main(int argc, char *argv[])
{
        multitype str("asdf"), f(3.14159f), i(32);

        printf("string %s float %f int %d\n", (const char *)str,
                (float)f, (int)i);
        return(0);
}


Last edited by Corona688; 04-12-2011 at 07:18 PM..
# 5  
Old 04-12-2011
I have made some progress, I will deal with the issue of using string or stringstream in a little bit. Can a string be parsed by a delimiter using the same method I was using for stringstream, or do I have to do something different?

I have the function creating the objects,
Code:
// creates a data object and meta data object for each column
int createColObjs( stringstream &colsRowStream ){
   std::string rowCell;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      // create new column data object
      col_metadata newColMeta;  metadata.push_back(newColMeta);
      // create new column data object
      column_data newCol;  columns.push_back(newCol);
   }
   // clear the buffer
   colsRowStream.clear();
}

This is called with,
colsRowStream << storeSplitsRows[0];
createColObjs ( colsRowStream );

which dumps the first row into the stream and passes it to the create object function. I get a col metadata object and a col data object for each col in the input file. The objects are stored in vectors, metadata and columns respectively.

I am a bit stuck on the loading function, which parses the stream and loads it to the appropriate var in the col object.
Code:
// accepts a stringstream and parses the data in to columns
int metadata_row_toCol( stringstream &colsRowStream, 
                        std::vector<col_metadata>& metadata ){
   int i = 0;
   std::string rowCell;
   // parse row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      metadata[i].content = rowCell;
      i++;
   }
   // clear the buffer
   colsRowStream.clear();
}

This above works, but is hard coded to put the data into metadata[i].content. I can't seem to see how I indicate that the first rows goes into content, but the next row goes into a different member. It seems like I should be passing a pointer to metadata[i].content, and not to the metadata vector of objects.If I did that, I could pass a pointer to metadata[i].type for the next row, etc. All the function would need to know is that it is expecting a pointer to a class variable. At any rate, I need to be able to tell the loading function where to put the data that is parsed out of the stream, but I can't seem to work out the syntax.

LMHmedchem

Last edited by LMHmedchem; 04-12-2011 at 08:13 PM..
# 6  
Old 04-13-2011
Quote:
Originally Posted by LMHmedchem
I have made some progress, I will deal with the issue of using string or stringstream in a little bit. Can a string be parsed by a delimiter using the same method I was using for stringstream, or do I have to do something different?
You have to do something different, perhaps something like this:
Code:
# from http://stackoverflow.com/questions/289347/using-strtok-with-a-string-argument-instead-of-char
void split(const string& str, const string& delim, vector<string>& parts) {
  size_t start, end = 0;
  while (end < str.size()) {
    start = end;
    while (start < str.size() && (delim.find(str[start]) != string::npos)) {
      start++;  // skip initial whitespace
    }
    end = start;
    while (end < str.size() && (delim.find(str[end]) == string::npos)) {
      end++; // skip to end of word
    }
    if (end-start != 0) {  // just ignore zero-length strings.
      parts.push_back(string(str, start, end-start));
    }
  }
}

I admit this looks clunky compared to stringstream... In C I'd just use strtok or strtok_r, which has side-effects that one must stay aware of but makes a lot of problems stupidly simple.

Quote:
I am a bit stuck on the loading function, which parses the stream and loads it to the appropriate var in the col object.
On first look I'm left wondering, you DID resize the vector to accommodate all the elements it might need, yes? They don't grow automatically.
Quote:
Code:
// accepts a stringstream and parses the data in to columns
int metadata_row_toCol( stringstream &colsRowStream, 
                        std::vector<col_metadata>& metadata ){
   int i = 0;
   std::string rowCell;
   // parse row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      metadata[i].content = rowCell;
      i++;
   }
   // clear the buffer
   colsRowStream.clear();
}

This above works, but is hard coded to put the data into metadata[i].content. I can't seem to see how I indicate that the first rows goes into content, but the next row goes into a different member. It seems like I should be passing a pointer to metadata[i].content, and not to the metadata vector of objects.
The difficulty arises because you're processing it a line at a time even though the data doesn't make sense as individual lines. Make a function that takes a file stream(or better yet, a general purpose istream), it will be able to read and process additional lines at need by whatever method you please.
# 7  
Old 04-13-2011
Well I have something that works. What I ended up doing is loading all of the data to the objects as string. I plan to do the conversion from string to whatever as a second step. That will simplify the loading functions, since they will only have to deal with one type. I think I can do conversion as a class method that will read the string vector in the object and do the conversion to either the int vector or the float vector. In some cases it stays as string.

Here is the code,
Header file,
Code:
class col_metadata {
public:
   // initialize class members
   col_metadata()
      : scaleMin(0.0), scaleMax(0.0),
        content(""), type(""), scale_type(""),
        strScaleMin(""), strScaleMax(""),
        header("") { }

   float scaleMin, scaleMax;
   std::string content, type, scale_type,
               strScaleMin, strScaleMax,
               header;
};

class column_data {
public:
   // initialize class members
   column_data()
      : header("") { }

   std::string header;
   std::vector<std::string> inDtaStr;
   std::vector<char> inputDataChar;
   std::vector<int> inputDataInt;
   std::vector<float> inputDataFloat;
};

main file,
Code:
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include "columns.h"

using namespace std;

// global declarations
   // declare vector of col_metadata objects
   std::vector<col_metadata> metadata;
   // declare vector of column_data objects
   std::vector<column_data> columns;

// functions
// creates a data object and meta data object for each column
int createColObjs( stringstream &colsRowStream ){
   std::string rowCell;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      // create new column data object
      col_metadata newColMeta;  metadata.push_back(newColMeta);
      // create new column data object
      column_data newCol;  columns.push_back(newCol);
   }
   // clear the buffer
   colsRowStream.clear();
}

// accepts a stringstream and parses the data in to columns
int metadata_row_toCol( stringstream &colsRowStream, 
                        std::vector<col_metadata>& metadata,
                        std::string col_metadata::* var ){
   int i = 0;
   std::string rowCell;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      metadata[i].*var = rowCell;
      i++;
   }
   // clear the buffer
   colsRowStream.clear();
}

// accepts a stringstream and parses the data in to columns
int header_row_toCol( stringstream &colsRowStream, 
                    std::vector<column_data>& columns,
                    std::string column_data::* var ){
   int i = 0;
   std::string rowCell;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      columns[i].*var = rowCell;
      i++;
   }
   // clear the buffer
   colsRowStream.clear();
}

// accepts a stringstream and parses the data in to columns
int data_row_toCol( stringstream &colsRowStream, 
                    std::vector<column_data>& columns ){
   int i = 0;
   std::string rowCell;
   // parse header row into cells, tab delimiter
   while(getline(colsRowStream,rowCell,'\t')) {
      columns[i].inDtaStr.push_back(rowCell);
      i++;
   }
   // clear the buffer
   colsRowStream.clear();
}


int main(int argc, char **argv) {

// declarations for args
   // file names
   int cmdArguments;
   std::string colsInFile, splitsInFile, outputFile;

//  Parse command line arguments
while ((cmdArguments = getopt (argc, argv, "c:i:o:d:h")) != -1)
   switch (cmdArguments)
   {
      case 'c':
         colsInFile = optarg;
      break;
      case 'i':
         splitsInFile = optarg;
      break;
      case 'o':
         outputFile = optarg;
      break;
      case 'd':
         //set delimiter;
      break;
      case 'h':
         std::cout << std::endl; // print help blurb
         exit(0);
      break;
   }

// check args
   if(splitsInFile.length() == 0) {
      std::cout << "  -> no input file was specified" << std::endl;
      return(-1);
   }

// declarations
   int i; // loop iterator
   std::string newSplitsLine, rowCell, loadvar;
   std::vector<std::string> storeSplitsRows;    // storage structure for input rows
   stringstream colsRowStream;

// read input file
   // create an input stream and open the splitsInFile file
   ifstream splitsInput;
   splitsInput.open( splitsInFile.c_str() );

   // read innput file and store
   while(getline(splitsInput,newSplitsLine)) {
      // remove '\r' EOL chars
      newSplitsLine.erase (remove(newSplitsLine.begin(),newSplitsLine.end(),'\r') , newSplitsLine.end());
      // store row data in vector of string
      storeSplitsRows.push_back(newSplitsLine);
   }

// create objects to store data and meta data
   //use first row to create objects for each col
   colsRowStream << storeSplitsRows[0];
   createColObjs ( colsRowStream );

// load metadata into metadata objects
   // declare pointer to class data member, this is used to tell the loading
   // function where the data goes in the object
   std::string col_metadata::*var;

   // load information from metadata row 0 to metadata[i].content
   colsRowStream << storeSplitsRows[0];
   //set pointer to metadata.content
   var = &col_metadata::content;
   // call func to load row 0 data to content
   metadata_row_toCol( colsRowStream, metadata, var );

   // load information from metadata row 1
   colsRowStream << storeSplitsRows[1];
   var = &col_metadata::type; // load type row
   metadata_row_toCol( colsRowStream, metadata, var );

   // load information from metadata row 2
   colsRowStream << storeSplitsRows[2];
   var = &col_metadata::scale_type; // load scale_type row
   metadata_row_toCol( colsRowStream, metadata, var );

   // load information from metadata row 3
   colsRowStream << storeSplitsRows[3];
   var = &col_metadata::strScaleMin; // load strScaleMin row
   metadata_row_toCol( colsRowStream, metadata, var );

   // load information from metadata row 4
   colsRowStream << storeSplitsRows[4];
   var = &col_metadata::strScaleMax; // load strScaleMax row
   metadata_row_toCol( colsRowStream, metadata, var );

   // load information from metadata row 5
   colsRowStream << storeSplitsRows[5];
   var = &col_metadata::header;  // load header row
   metadata_row_toCol( colsRowStream, metadata, var );

   // print loaded data for checking
   std::cout << std::endl;
   for (i=0; i<metadata.size(); i++) {
      std::cout << "metadata[" << i << "].content      " << metadata[i].content << std::endl;
      std::cout << "metadata[" << i << "].type         " << metadata[i].type << std::endl;
      std::cout << "metadata[" << i << "].scale_type   " << metadata[i].scale_type << std::endl;
      std::cout << "metadata[" << i << "].strScaleMin  " << metadata[i].strScaleMin << std::endl;
      std::cout << "metadata[" << i << "].strScaleMax  " << metadata[i].strScaleMax << std::endl;
      std::cout << "metadata[" << i << "].header       " << metadata[i].header << std::endl;
      std::cout << std::endl;
   }

// load data to data objects
   // load header row
   int metadata_rows, j;
   std::string column_data::*varCol;
   std::vector<std::string> column_data::*stringVar;

   // number of rows of metadata before header
   metadata_rows = 5;

   // load header row data
   colsRowStream << storeSplitsRows[metadata_rows];
   varCol = &column_data::header;  // load header row
   header_row_toCol( colsRowStream, columns, varCol );

   for(i=metadata_rows+1; i<storeSplitsRows.size(); i++ ) {
      // load first row to stringstream
      colsRowStream << storeSplitsRows[i];
      data_row_toCol( colsRowStream, columns );
   }

   // print loaded data for checking
   std::cout << std::endl;
   for (i=0; i<columns.size(); i++) {
      std::cout << "columns[" << i << "].header       " << columns[i].header << std::endl;
      for (j=0; j<columns[0].inDtaStr.size(); j++) {
         std::cout << "columns[" << i << "].inDtaStr[" << j << "]  " << columns[i].inDtaStr[j] << std::endl;
      }
      std::cout << std::endl;
   }

}

What I did to load the metadata was to declare a pointer to class data member,
Code:
    std::string col_metadata::*var;

Then in the function definition, I pass a reference to the vector of objects, and also the pointer to data member,
Code:
 int metadata_row_toCol( stringstream &colsRowStream, 
                         std::vector<col_metadata>& metadata,
                         std::string col_metadata::*  var );

As far as I can tell, the function just knows there will be a pointer, but doesn't care which data member it points to, or which object. In the loading fucntion, it's just,
Code:
      metadata[i].*var = rowCell;

Then I select a row to process,
Code:
    colsRowStream << storeSplitsRows[0];

point *var to what I want (the content string here, which is in row 0)
Code:
   var = &col_metadata::content;

and call the loading function with the row, the vector of objects, and the pointer.
Code:
metadata_row_toCol( colsRowStream, metadata, var );

This lets me load each row to a different data member by changing the pointer. As far as I can tell, the only limitation is that the pointer is declared as a string, so I couldn't point to an int data member, etc. I could declare different kinds of pointer if I needed to.

For the data rows, I am loading everything as string, so the destination in the objects is always the same. I am using push_back to dynamically size the vectors.

I think that logically these functions should be class methods, but I'm not sure how to go about adding them. I seem to remember issues when referencing thing from inside a class. I also need to add methods for doing the translation from string to int and string to float.

Do you see anything grievously wrong with how I'm going about this? I am hoping to develop some nice reusable code that I can implement in other apps that use similar data. I think I can dispense with storing the entire file on input, since I am storing as string anyway, or I can just clear the storage vector when I am done with it? Is there some point at which I need to become concerned with resource allocation? I have tried the above on an input file of 250 cols and ~16,000 rows. The app uses about 135MB of RAM and takes 1min 8 seconds to complete. This includes writing the data back to an output file in an inefficient method.

LMHmedchem
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Programming

C++ : Base class member function not accessible from derived class

Hello All, I am a learner in C++. I was testing my inheritance knowledge with following piece of code. #include <iostream> using namespace std; class base { public : void display() { cout << "In base display()" << endl; } void display(int k) {... (2 Replies)
Discussion started by: anand.shah
2 Replies

2. Programming

How to initialize an object with another object of different class?

How to initialize an object of class say "A", with an object of type say "B". The following code give the error message "error: conversion from âAâ to non-scalar type âBâ requested" #include <iostream> using namespace std; class B; class A{ public: A() { cout <<"\nA()" << endl; } ... (1 Reply)
Discussion started by: techmonk
1 Replies

3. Programming

Created a wrapper for a function in a class.

I have a class called Parsing with the following function. I want to create a wrapper for it, so that I call it using GetReal rather than GetFloat. Bit confused on how to do this. class Parsing { private: int Length; // int Ptr; ... (3 Replies)
Discussion started by: kristinu
3 Replies

4. UNIX and Linux Applications

opends- help with custom object class

we have 2.2.0 of opends running on RedHat 2.6.21 and we're trying to setup a structure that will suit our needs. One of the things we'd like to do is create our own custom object classes based off some of the existing ones you get out of the box. The opends documentation covers this here (sorry, it... (1 Reply)
Discussion started by: snafu
1 Replies

5. Programming

question about function object

I have a code as following: #include <iostream> #include <algorithm> #include <list> using namespace std; //the class Nth is a predicates class Nth{ private: int nth; int count; public: Nth(int n):nth(n),count(0){} bool operator()(int){ ... (2 Replies)
Discussion started by: homeboy
2 Replies

6. Shell Programming and Scripting

How to Call external function in .C or .So (Shared Object)

Hi, Anybody know any way to Call with Shell Script an external function wrote in .C or .So (Shared Object) on AIX enviroment and returning parameters of .C or .SO to Shell Script? Tks!! (6 Replies)
Discussion started by: rdgsantos
6 Replies

7. Programming

Handling a signal with a class member function

Hello, i am using the sigaction function to handle the SIGCHLD signal.Is it possible to use a class member function as the handler function (the sa_handler member of the sigaction structure)? The function's signature is: void (*sa_handler)(int);so i don't think i can use a static member function... (2 Replies)
Discussion started by: Zipi
2 Replies

8. Shell Programming and Scripting

Passing global variable to a function which is called by another function

Hi , I have three funcions f1, f2 and f3 . f1 calls f2 and f2 calls f3 . I have a global variable "period" which i want to pass to f3 . Can i pass the variable directly in the definition of f3 ? Pls help . sars (4 Replies)
Discussion started by: sars
4 Replies

9. Programming

How to make a function friend to both base and derived class

Hi, I have a base class and derived a class from the base class, i want to print & read the data for the object created for the derived class,so i have overloaded both the << and >> operators and also have done the foward declaration. Below is the code snippet, #include <iostream> class... (3 Replies)
Discussion started by: ennstate
3 Replies

10. Programming

Listing function exports from object file

Is it possible to view all the functions exported by a given object file? "dump -tv" comes the closest, but what exactly am I looking for to determine whether the symbol exists in the object file? Essentially, I have a library that requires a call to "xdr_sizeof" and the compile is failing... (5 Replies)
Discussion started by: DreamWarrior
5 Replies
Login or Register to Ask a Question