1

I'm trying to read data from a text file called fields.txt which holds the members of the struct Fields.

{1, 0, 7.4, 39.5, 5.33784}, 
{3, 1, 4.6, 27.9, 6.06522}, 
{5, 2, 2.2, 12.5, 5.68182}, 
{8, 0, 14.5, 86, 5.93103}, 
{11, 1, 8, 43.8, 5.475}, 
{16, 2, 5.9, 37.7, 6.38983}, 
{22, 0, 12.7, 72, 5.66929}, 
{24, 1, 10.5, 63.2, 6.01905} 

I want my program to read the data into my array of struct called Fields fielddata[8] = {}; so that I am able to use the data to create a display.

#include<iostream>
#include<fstream> 

using namespace std;
std::ifstream infile("fields.txt");

int initialise(int field, int crop, float size, float yof, float yph);

struct Fields {


int Field;
int Crop;
float Size;
float Yof;
float Yph;

int initialise(int field, int crop, float size, float yof, float yph)
{
    Field = field;
    Crop = crop;
    Size = size;
    Yof = yof;
    Yph = yph;

};

};



int main() {


Fields fielddata[8];

ifstream file("fields.txt");
if(file.is_open())
{


    int a, b, i = 0;
    float c, d, e;
    while (infile >> a >> b >> c >> d >> e)
    {
        fielddata[i].Field = a;
        fielddata[i].Crop = b;
        fielddata[i].Size = c;
        fielddata[i].Yof = d;
        fielddata[i].Yph = e;

        ++i;
    }


}




int highyph = 0;



cout << "Field\t" << "Crop\t" << "Size\t" << "YOF\t" << "YPH\t" << endl;

for (int i = 0; i < 8; i++) {


    cout << fielddata[i].Field << "\t" << fielddata[i%3].Crop << "\t" << fielddata[i].Size << "\t" << fielddata[i].Yof << "\t" << fielddata[i].Yph << "\t" << endl;
}


for (int i = 0; i < 8; i++)
{
    if (fielddata[i].Yph > highyph)
        highyph = fielddata[i].Field;
}

cout << "The Field with the Highest Yield is " << highyph << endl;




system("Pause");
    return 0;
}
Daniel H
  • 29
  • 6
  • I believe this would be of help? http://stackoverflow.com/questions/7868936/read-file-line-by-line – Keno Feb 07 '16 at 23:53
  • right now it reads the data into the console but i am unsure how to read the data into the array of struct so that it can be used by my loop – Daniel H Feb 07 '16 at 23:53

1 Answers1

0

Edit: To specifically deal with the type of input shown in OP's post (comma delimiters with curly braces outside), this is what is done. Idea taken from this thread

//Get each line and put it into a string
String line;
while (getline(infile, line)) {
     istringstream iss{regex_replace(line, regex{R"(\{|\}|,)"}, " ")};
     vector<float> v{istream_iterator<float>{iss}, istream_iterator<float>{}};

     //Assigns each member of the struct to a member of the vector at the relevant position
     fielddata[i].Field = static_cast<int>(v.at(0));
     fielddata[i].Crop = static_cast<int>(v.at(1));
     fielddata[i].Size = v.at(2);
     fielddata[i].Yof = v.at(3);
     fielddata[i].Yph = v.at(4);
     ++i;
}

Basically what's happening here is:

  1. The program reads a line from the file and puts it into the String line (until there are no more lines to be read [EOF]).
  2. An inputstringstream replaces all occurences of commas and curly braces with spaces, for easy acquisition.
  3. We then use a vector to get all the numbers left over in iss.
  4. Each member of the struct fielddata is then given the value in each relevant position in the vector. We convert the first two to integers since the vector is of type float.

From this thread

First, make an ifstream:

#include <fstream>
std::ifstream infile("thefile.txt");

Assume that every line consists of two numbers and read token by token:

   int a, b;
   while (infile >> a >> b)
   {
        // process pair (a,b)
   }

You'll simply need to create 5 variables which match the data types you're looking for to put into each struct. E.g. 2 ints, 3 floats. Then you simply follow the format outlined above and assign each variable to each member of the struct.

Also, it would be advisable to initialize all your variables at the start of main and not in the middle.

And one more bit of help to nudge you along.

    int a, b, i = 0;
    float c, d, e;
    while (infile >> a >> b >> c >> d >> e)
    {
        fieldData[i].Field = a;
        //Assign other struct members as you wish
        ++i; //Or use an inner for loop to do the incrementation
    }

If you need further guidance with this let me know, but I'd like to see what you manage to do with it.

Community
  • 1
  • 1
Keno
  • 2,018
  • 1
  • 16
  • 26
  • updated my post am i getting anywhere @Keno Clayton ? – Daniel H Feb 08 '16 at 01:52
  • @DanielH It looks like you're on the right track, but I noticed fielddata[i%3].Crop Is that intended? Aside from that it looks like that should work, have you tested it yet? – Keno Feb 08 '16 at 02:10
  • :@KanoClayton yes there are only 3 element values (0,1,2) in the crop array where as in the other arrays there are 8. So that is why i have done that. I tested it but got a bunch of strange values in the display such as -8503d304 – Daniel H Feb 08 '16 at 02:16
  • @DanielH sounds like a variable wasn't initialized. Looking closer at your code, I noticed that you're declaring fielddata twice, which is incorrect. Here is my suggestion. Declare all your variables at the start of every function from here on out. It helps you to keep track of all your variables. Then simply call that variable wherever you need to use it. – Keno Feb 08 '16 at 02:26
  • OKay i've altered that. Someone else has said that "your code does not take into account the characters '{', ',' and '}' in your input file." any idea? – Daniel H Feb 08 '16 at 02:48
  • @DanielH Oh that's right. My suggestion only works if there are only numbers on each line otherwise it won't give you the values you need. In that case I'll edit my post with the method you should use in order to deal with the extra characters. – Keno Feb 08 '16 at 02:53