views:

572

answers:

4

I want to create a struct from data harvested by line from a file. Each line necessitates a new struct, and the lines are accessed in a while loop. In C# I did this by creating anonymous structs and adding them to a list of structs. C++ would seem not to allow anonymous structs. I tried naming them with an incrementing variable, but this did not work, as the variable name was taken literally - regardless, I would prefer not to be forced to use this method as I hate the idea of irrelevant names. I suppose I could name the struct by a unique property, but, obviously, I would rather use a property as. . . a property. Besides, what if they are not all necessarily unique?

Can someone suggest something or explain something that I am missing?

Thanks!

in c# (psuedo:

public static List<Referral> Referrals = new List<Referral>();

//in loop:
var NewReferral = new Referral(referringURL.Trim(), referringWords.Trim().ToLower() , 1);
if ( NewReferral.URL == referringURL.Trim() )  {Referrals.Add(NewReferral);

in c++:

 list<CollectedData> AllData;

 ifstream myFile("test_data.txt");
 if (myFile.fail()) {cout << "Error opening file"; return 0;}
 else
 {
  cout << "File opened... \n";
  while( getline(myFile, line) ) {
   struct CollectedData;
                        //add property values
                        //add struct to struct list
  }
 }

(please do go into detail about when they automatically delete, it probably won't be helpful, but i'd like to know. thanks!)

A: 

A struct in C++ is a data structure, whose entire "structure" (layout, members, types of members) is defined at compile time.

Do you perhaps want something like a hashtable (or other associative/map-like data structure) instead, where you have one of those structures per line of the file, in, say, an array?

Adam Batkin
+1  A: 

Your question is a little unclear on what you're asking. I infer you mean that each struct has the same fields for every line, like columns in an SQL database. That means that you do not have a different struct definition for each line in the file.

So, assuming that all your structs have the same fields, the job is easy; simply define a copy constructor for your struct, and then you can add them to a std::vector or a std::list or your own implementation of array / list / deque / whatever.

struct mystruct
{ 
  int a,b,c;
  // has default (shallow-copy) constructor, coz that's fine for integral types...
}

void readfromfile( YourFileClass *pFile, /* etc.. */ )
{
   mystruct temp;
   std::list<mystruct> result;
   // read each line into the temp struct one at a time, add to a list
   while ( pFile->ReadNextFileLineIntoStruct( &temp ) )
   {
      result.push_back( temp );
   }
   // result has a linked list of data...
}

You can also new up an instance of your struct each time through the loop, and add pointers to those structs to the list ( as Smashery suggests ), but be aware that those objects will not be freed when the list is deleted -- you will need to loop through the entire list and call delete on each entry when you're done with it, or you will irretrievably leak memory.

(You can also make a class that inherits from std::list and properly frees each entry in its destructor, but this enters dangerous territory if you don't know just what you're doing.)

Crashworks
+5  A: 

Your C++ looks to be on the right track, aside from two things. One, you have to define the form of a CollectedData struct somewhere, and two you have to give a name to your struct variable:

For example, if you define the CollectedData struct like so

struct CollectedData {
  int field1;
  std::string field2;
  bool field3;
  // etc
};

Then in your inner loop you can do this

while( getline(myFile, line) ) {
                CollectedData lineData;
                 //add property values
                 lineData.field1 = /*whatever*/;
                 lineData.field2 = /*whatever*/;
                 lineData.field3 = /*whatever*/;
                 //add struct to struct list
                 AllData.push_back(lineData);
        }

Each time through the loop a new CollectedData object is created, and its fields are filled in, then a copy of it is pushed into the AllData list, and then finally the object is automatically destroyed (remember a copy still exists in the list).

Detail About When Objects Are Destroyed

C++ has three sorts of storage: static, automatic, and dynamic.

Static-storage objects exist for the whole lifetime of the program. Any object created outside of a class or function is static (i.e. globals are static). Same goes for anything declared inside of a class or function with the 'static' keyword.

Dynamic-storage objects are objects created with keyword 'new' (or with malloc(), but that is a C-ism that should generally be avoided in C++ unless really necessary). Dynamic-storage objects are objects whose lifetime is managed manually by the programmer. A dynamically-stored object will continue to exist until you destroy it with keyword "delete". Note that the only way you can access a dynamically-stored object is through a pointer or a reference. If you're not using a pointer or reference, it isn't dynamic (but a pointer/reference can also refer to a non-dynamic object).

Automatic-storage objects are your regular variables: members variables of structs and classes, and local variables (including parameters) in methods and functions.

Automatic-storage objects defined inside functions are created when the line of code that defines them is run. They are automatically destroyed when they "go out of scope", that is, when the block that they are declared inside of terminates. In general, a "block" is a set of braces: {}. So, anything created inside of a function is destroyed when the function returns, and likewise anything created inside of a while-loop's body is automatically destroyed when the loop reaches its end (regardless of whether it terminates or iterates again).

Automatic-storage objects defined as members of classes or structs are created when the object that contains them as members is created, and destroyed when the object that contains them as members is destroyed.

(I used the term "object" repeatedly above, but the same rules apply to fundamental types like int, char, bool, etc)

Tyler McHenry
+1 for clarity. The difference between dynamic and stack allocation is also described here: http://stackoverflow.com/questions/599308/proper-stack-and-heap-usage-in-c
Crashworks
A: 

There's no such a thing as an anonymous type in C++. You must define the line struct explicitly, and then you must define the data structure that represents the collection of lines.

Eduardo León