Ok I have to make a 3-D array within a class and read from a file with input like this

90312 Thing_1 12.34 100 25 // Shelf 9, row 3, bin 12
20705 Thing_2 54.78 24 25
10101 Another_Thing 123.45 183 4

There array is based off 9 shelves, 7 rows in a shelve, 12 items
another confusing thing is the first number in the file item determines the position in the array as shown above

I have no clue how to do this as we just started using classes and I have used the search function

Recommended Answers

All 48 Replies

Ok I have to make a 3-D array within a class and read from a file with input like this

90312 Thing_1 12.34 100 25 // Shelf 9, row 3, bin 12
20705 Thing_2 54.78 24 25
10101 Another_Thing 123.45 183 4

There array is based off 9 shelves, 7 rows in a shelve, 12 items
another confusing thing is the first number in the file item determines the position in the array as shown above

I have no clue how to do this as we just started using classes and I have used the search function

What exactly are you having problems with?

  1. Overall organization?
  2. Setting up the class data members?
  3. Reading a line from a file?
  4. Setting up a 3-D array?
  5. Parsing "90312" into 9,3,12?
  6. Putting the data into a struct element?
  7. Etc.

You haven't provided a spec or a class skeleton or a driver program, so we have no idea what you're doing. You posted a few lines from the input file, but you need to expand more on what the goal is and where you're stuck.

I am trying to figure out how to read a input into a 3-D array, ive created a basic class with function we are suppose to have but I am trying to figure out where to begin

#ifndef _INVENTORYH_
#define _INVENTORYH_

#include <iostream>
#include <string>
using namespace std; 

class Inventory
{
  public:
          //Accessors
          GetDescription();
          GetUnitPrice();
          GetQOH();
          GetMRQ();
          
          //Default Constructor
          Inventory();
                     
          //Mutators
          Initialize(string, float, integer, integer);
          AddQOH(integer);
          SubtractQOH(integer):
                    
  private:
            
          string pDscript; //part description
          float uPrice; //unit price 
          int QOH; 
          int MQG;
};
#endif

Some project information

LGPC needs to keep track of
their generic inventory. They have a warehouse where parts are kept. The warehouse has 9 shelves lined
up from the front to the back. In each shelf there are 7 rows and each row has 12 bins. The part number for
an LGPC part is a five-digit number comprised of the shelf number, the row number, and the bin number.
For each part LGPC keeps track of its description, unit price, quantity on hand (QOH), and minimum
reorder quantity (MRQ).

There will be only one record in the file for each part. The records in the file can be in any order. Not all
the bins in the warehouse have to contain a part. All fields in the files will be separated by a space. The data
in the file will be in the correct format.
PROCESSING: 1) Read the inventory data into a three dimensional array. The elements of this array will
be a class. The class will be a part.
The Part class will contain the following private data members: part description, unit price, QOH, and
MRQ. It will include the following operations:
Accessors: GetDescription( )
(look at stuff) GetUnitPrice( )
GetQOH( )
GetMRQ( )
NOTE: All accessor member functions must be declared as const.
Mutators: Initialize(string, float, integer, integer

Pretty much 1 4 5 and putting it into a 3-D array using 5

Well the spec says you need to name the class Part, not Inventory, so change it. Since you know the size of the array, there's no need to have the array be dynamic.

Part inventory[9][7][12];

Read a line from the file into these local non-class variables:

int location;
string pDscript;
float uPrice;
int QOH; 
int MQG;

Set up three more local non-class variables as indexes:

int shelf, row, bin;

Have a function that parses location into shelf, row and bin, and call it:

void ParseLocation (int location, int& shelf, int& row, int& bin);

Now initialize the Part:

inventory[shelf][row][bin].Initialize (pDscript, uPrice, QOH, MQG);

This should set you in the right direction.

Thanks, Ill check this out and report back with a code. I assume it would be fine to make a .cpp using this local non-class variables?

Thanks, Ill check this out and report back with a code. I assume it would be fine to make a .cpp using this local non-class variables?

Not sure what you mean. Yes, it'll go in a separate .cpp file and it won't be called "Part.cpp" Stick this code in main () or wherever. Any .cpp file that isn't "Part.cpp". I wrote "local non-class" variables to distinguish them from your class variables of the same names and to point out that this code isn't part of your class, though it uses your class. This may not make sense if you've never used classes before.

I seem to have a problem formulate a proccess of how to even begin parsing the location and what proccess Initialize should have which I assumes read the file into a 3-D Array? He also noted the read from file function must be a seperate function in the program it seems to me like this dick like making things complicated. I've made a implementation.cpp of my class but its just return the private variables as stated in the project

I seem to have a problem formulate a proccess of how to even begin parsing the location and what proccess Initialize should have which I assumes read the file into a 3-D Array? He also noted the read from file function must be a seperate function in the program it seems to me like this dick like making things complicated. I've made a implementation.cpp of my class but its just return the private variables as stated in the project

You need to step back and look at your whole approach to the project. First, expect to have to spend A LOT of time on this. You have several things you have never done before. Approaches differ, but expect to have to put aside the main project several times in order to learn new things, then come back to it. If you don't have much experience with classes, but the project aside and take a tutorial on them, write a few smaller programs with some, but not all of this project's requirements in them till you get used to classes.

Drop the project and take a detour and learn about the string class and how to parse a string into separate strings. Learn how to convert a string to a number and vice-versa. Drop the project and write the ParseLocation function that I posted, including a small main function that calls it and prints out the results.

Drop the project and learn about multi-dimension arrays and how to declare them, access them, and change them.

Drop the project, set up several data files in the form that your input files will take, and practice reading them in and displaying them.

If you aren't familiar with public versus private variables and getter/accessor and setter/mutator functions, drop the project and study up on them, then come back to the project.

If you're approaching this all at once, you're almost guaranteed to be overwhelmed. As I mentioned in a previous thread, you need to write some Display functions right away because you'll need them at every stage to check your work on the smaller stages. You had the problem before of thinking that the error was in one part of the program when it was actually in a previous part because you hadn't rigorously tested the previous part before moving on. You're going to have to write several functions probably that aren't listed in order to test things, and you'll probably delete a lot of these functions. Similarly, if you're not using a debugger, you'll need to put a bunch of cout statements at various points in the code (delete them later), displaying what different variables are at different parts of the code.

commented: well said +2

He also noted the read from file function must be a seperate function in the program it seems to me like this dick like making things complicated.

There's no reason to trash talk your professor on this forum. He may well be a jerk, but even so, no one here knows him and no one wants to hear it. It's pretty standard to require you to use a separate function to read in the data and there are good reasons for it.

Ok, Ill work on the parse function
Im not familiar with a breaking down 010203
into separate integers such as 010203 I am familiar with using the atoi function to convert a string into a integer

I have a semi poor way to parse this

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main()
{
    ifstream fin;
    string numb;
    
    
    fin.open("num.data");
    
    while(!fin.eof())
    {            
      fin>>numb; //reads 090201
    }
    
    fin.close();
   
   //Since there will  always be "6" values in the integer;

  shelf = numb[0] + numb[1]; //Somehow to learn convert this using atoi 

row = numb[2] + numb[3];

bin = numb[4] + numb[5];
    

    return 0;
}

not the most efficent way but I suppose it would work, your take on this? Reason I include the number before the nonzero value in the integer is he said the rows shelves and bins are subject to change

I have a semi poor way to parse this

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main()
{
    ifstream fin;
    string numb;
    
    
    fin.open("num.data");
    
    while(!fin.eof())
    {            
      fin>>numb; //reads 090201
    }
    
    fin.close();
   
   //Since there will  always be "6" values in the integer;

  shelf = numb[0] + numb[1]; //Somehow to learn convert this using atoi 

row = numb[2] + numb[3];

bin = numb[4] + numb[5];
    

    return 0;
}

not the most efficent way but I suppose it would work, your take on this? Reason I include the number before the nonzero value in the integer is he said the rows shelves and bins are subject to change

Try it out and see if it works. I see no output statements, so how will you know whether it works? There's no call to atoi. Look up what atoi requires on www.cplusplus.com and make sure you are passing it the correct parameter(s). Look at the string and cstring libraries and see if they have anything that may help (they will).

No output means you are just guessing. Don't guess. Experiment and see what works.

Thanks for the breakdown, Vern. I usually tend to over complicated things when coding, I took your advice and went and look at the c_string and string l properly implemented a function to parse the locations properly I was surprised to find a better method than i had

#include <iostream>
#include <string>
#include <fstream>
using namespace std; 

int main()
{
    ifstream fin;
    string temp; 
    string numb;
    int shelf, row, bin;
    
    fin.open("num.data");
    
    while(!fin.eof())
    {
      fin>>numb; 
    }
    
    fin.close();
    
    cout<<numb <<"number as integer"<<endl;//numb integer in file as string
    cout<<endl; 
    
    temp = numb.substr(0,1) + numb.substr(1,1);//strip the first twp chars in the string with substr
    
    shelf = atoi(temp.c_str()); //convert to stripped chars from string to int
    
    cout<<shelf<<endl; //string chars converted to int
    
    temp = numb.substr(2,1) + numb.substr(3,1);
    
    row = atoi(temp.c_str());
    
    cout<<row<<endl; //row strings converted to int
    
    temp = numb.substr(4,1) + numb.substr(5,1);
    
    bin = atoi(temp.c_str());
    
    cout<<bin<<endl; //bin string chars converted to int
    
    return 0;
}

Good. Experimentation is the key. Try it with a variety of text files like:

000000
110807
090602
08000[B]5[/B]

Make sure it always works.

Food for thought. substr can isolate more than one character at a time, if you like. Also, since input like this can be read in as an integer, you can do that and then use the / and % operators to isolate the numbers within the larger number that you want, avoiding all string manipulation.

This doesn't mean the way you did it is incorrect. There's just more than one way to do it. But run a file with multiple numbers in it through your program and see if it parses all of them correctly. If you find that something doesn't work, placing debugging statements in the code (delete them later!) can be very valuable.

Thanks vern!
I had previously tried it with the number 190203 before 090203 and it worked fine I appreciated the help I am just wondering what function I should work on next perhaps initialize a 3-D array of a class object? any tips for that one

Thanks vern!
I had previously tried it with the number 190203 before 090203 and it worked fine I appreciated the help I am just wondering what function I should work on next perhaps initialize a 3-D array of a class object? any tips for that one

I'd say here's your next task (using a struct, not a class, and having no member functions - worry about that later):

struct Part
{
  string pDscript;
  float uPrice; 
  int QOH; 
  int MQG;
};

/* any functions you want to use */

int main ()
{
   Part inventory[9][7][12];

   // read file in and fill in inventory[][][] array.

   // ask user for row, shelf, and bin
   // output all four elements for that Part in a nicely spaced format
   // This will require writing a Display function
}

Input file is the one you have in post 1:

90312 Thing_1 12.34 100 25
20705 Thing_2 54.78 24 25
10101 Another_Thing 123.45 183 [B]4[/B]

So if they enter 1 1 1, they should get:

Another_Thing $123.24   183    [B]4[/B]

If they enter 2 7 5, they should get:

Thing_2     $ 54.78     24    2[B]5[/B]

That gives you one more step towards the project rather than tackling the whole thing at once. Again, no member functions to call, everything's public. Get this working, then when it works, tackle the rest. You can use your parsing code that you wrote previously in this program.

I am working on reading the data into a 3-D array

#include <iostream>
#include <fstream>
#include <string>
using namespace std; 

struct Part
{
       string pDscript;
       float uPrice;
       int QOH;
       int MRQ;
};

int main()
{
    Part item[9][7][12] ;
    ifstream fin;
    int i = 0;
    
    
    fin.open("num.data");
   
      for(i = 0; i < 9; i++)
         for(int j =0; j < 7; j++)
             for(int k = 0; k < 12; k++)
             {       
                      fin>>item[i][j][k].pDscript>>item[i][j][k].uPrice
                      >>item[i][j][k].QOH>>item[i][j][k].MRQ;
             }
   
   
      
    fin.close();
    
    system("Pause");
    return 0;
}

I am just having problems formulating a proccess to sort the part number first read in each line into the array block corresponding for that number Ihave the parse function but meh

I am just having problems formulating a proccess to sort the part number first read in each line into the array block corresponding for that number Ihave the parse function but meh

??? Looks like you were in the middle of a sentence and just stopped wihout finishing the sentence. I don't know what you are trying to say.

Re-read my post 4. You cannot read directly into the array as you do and the indexes will not be i, j, and k. There is no guarantee that every 1, j, and k will have a part associated with it and there is no guaranteed that the parts will be in any kind of order in the file. You need to read the location from the file, then parse it. Then and only then will you know what the appropriate indexes should be, and they won't have anything to do with an i, j, and k from a for-loop. Look at the data file and see whether a for-loop is appropriate.

It seems to be the part number is being read totally seperate to determine to location in the class array and I was reading that the class array takes the values of the default constructor until initalized

So let me make a bit of sense

Would it make more sense to first read the part number
Parse it
Initalize it I assume in the class array?
Read the values after it
Move to next line and read the next part number
parse it...and so on?

I created a basic skeleton code to build upon or you may feel I jumping too far ahead

#include <iostream>
#include <fstream>
#include <string>
using namespace std; 
void ParseLocation(string location, int& shelf, int& row, int& bin);
int main()
{
    string location, script;
    ifstream fin;
    int i = 0;
    int shelf, row, bin;
    float uPrice;
    int QOH, MRQ;
    
    fin.open("num.data");
    
    while(!fin.eof())
    {
    fin>>location>>script>>uPrice>>QOH>>MRQ;
    ParseLocation(location, shelf, row, bin); 
    }
 
    
    fin.close();
    
    
    
    
    system("Pause");
    return 0;
}

void ParseLocation(string location, int& shelf, int& row, int& bin)
{
    string temp;
    
    temp = location.substr(0,1) + location.substr(1,1);//strip the first twp chars in the string with substr
    shelf = atoi(temp.c_str()); //convert to stripped chars from string to int
    
    cout<<shelf<<endl; //string chars converted to int
    
    temp = location.substr(2,1) + location.substr(3,1);
    row = atoi(temp.c_str());
    
    cout<<row<<endl; //row strings converted to int
    
    temp = location.substr(4,1) + location.substr(5,1);
    bin = atoi(temp.c_str());
    
    cout<<bin<<endl;
}

It compiles and works properly as of right now with 1 item in the file (1 line), making jump to the new line grabbing that first string

If this is ok what would I implement next?

Better.

while(!fin.eof())
    {
    fin>>location>>script>>uPrice>>QOH>>MRQ;
    ParseLocation(location, shelf, row, bin); 
    }

It still doesn't put it into the array, though. You need to add more inside the while loop. Nothing is done with any of these variables. You've read them from the file (good), you've parsed the location to get the shelf, row, and bin (good). Now you've done all that hard work and... what are you going to do with these variables? Hint : location's job is done, you can throw it out. But you need all seven of the other variables and you need to do something with them inside the while loop. Hint # 2 - You have 3-dimensional array. You have 4 elements in your Part struct. You have 7 variables after you throw away location. 3 + 4 = 7.

It compiles and works properly as of right now with 1 item in the file (1 line), making jump to the new line grabbing that first string

How do you know that it works properly? You have no display function to confirm that?

So as far as the next steps go:

  1. Put some code in that while loop that fills in the array and uses the 7 variables.
  2. Write a Display function of some type.
  3. After the while loop, ask the user to enter a shelf, row, and bin.
  4. Display the Part information for the Part that is stored there.

When that's all working well (and only then), start turning everything into a class. Start by making everything public (i.e. not private), write the constructor and Initialize function, converting what you have to a class implementation. Also convert your Display function to a class function.

When that's all working, make your data members private one at a time, compile, get the errors, fix them by writing and using the appropriate getter and setter functions.

But I'd finish the program I suggested first (class, not struct, with no member functions). One piece at a time.

I do not know why users are limited to editing posts so many times.
However after giving it more thought

Would this be proper for initializing a class array

while(!fin.eof())
    {
    fin>>location>>script>>uPrice>>QOH>>MRQ;
    ParseLocation(location, shelf, row, bin); 
    [shelf][row][bin].Initialize(script, uPrice, QOH, MRQ);
    }

Eh, just caught your post after I submitted mine. Thanks for the awesome help once again, mate! Too bad I have ran out of reputation points to give. Ill re-read over your post and make some more sense of it

Throw away the location variable? Do I not need it for my Parse function?

commented: About time power_computer gets to be green again :) +26

I do not know why users are limited to editing posts so many times.

I believe it's not a matter of number of times, but rather time limit. You can edit up to a half hour after the original post.

Thanks for the awesome help once again, mate!

You're welcome.

Too bad I have ran out of reputation points to give.

Voila! You're green again. The statute of limitations has run out on the previous bad rep IMO!

Throw away the location variable? Do I not need it for my Parse function?

You do need it for your Parse function. Throw it away AFTER you return from your Parse function. (you don't need to "throw it away". Just don't use it again. It's done its job.)

while(!fin.eof())
    {
    fin>>location>>script>>uPrice>>QOH>>MRQ;
    ParseLocation(location, shelf, row, bin); 
    [shelf][row][bin].Initialize(script, uPrice, QOH, MRQ);
    }

Better. You're on the right track. But if I'm the compiler, I don't know what [shelf][row][bin] refers to. You need to tell me what variable these indexes refer to.

[shelf][row][bin].Initialize(script, uPrice, QOH, MRQ);

You'll do this eventually, but not yet. The idea was to not have any member functions yet, just struct variables (you are of course free to not follow my advice, but if you are trying to follow it, you shouldn't have this yet. And since you haven't written this function, you're going to get an error).

I had something more like this in mind, for now.

inventory[shelf][row][bin].pDscript = script;

Do the same for the other three Part elements.

I was doing something similiar.
I implemented my class in my .cpp just for sakes

and did something similiar

item[shelf][row][bin].Initialize(pDscript, uPrice, QOH, MRQ);

of, course something is causing the program to crash so Im trying to figure that out at the moment

I just implement the Part::Initialize class function before hand I had all the other garbage it cause program to crash, I removed it down to the Part() constructor and Initialize and no crash so time for testing and writing a display function

I went ahead and put the class in a part.h the class implementation in a part.cpp and a driver in drive.cpp
compiles fine no crash so now to work on that display function get input a print pending on item number

#include <iostream>
#include <fstream>
#include <string>
using namespace std; 

class Part
{
      public:
             Part();
             void Initialize(string, float, int, int);
             
      private:
              string pDscript;
              float uPrice;
              int QOH;
              int MRQ;
};

Part::Part()
{
  pDscript = "UNUSED";
  uPrice = 0;
  QOH = 0;
  MRQ = 0;
}

void Part::Initialize(string pDscript, float uPrice, int QOH, int MRQ)
{
     pDscript = pDscript;
     uPrice = uPrice;
     QOH = QOH;
     MRQ = MRQ;
}


void ParseLocation(string location, int& shelf, int& row, int& bin);
int main()
{
    string location, pDscript;
    ifstream fin;
    int i = 0;
    int shelf, row, bin;
    float uPrice;
    int QOH, MRQ;
    Part item[9][7][12];
    
    fin.open("num.data");
    
    while(!fin.eof())
    {
    fin>>location>>pDscript>>uPrice>>QOH>>MRQ;
    ParseLocation(location, shelf, row, bin);
    cout<<shelf<<row<<bin<<endl;
    item[shelf][row][bin].Initialize(pDscript, uPrice, QOH, MRQ);
    }
    fin.close();
    
    system("Pause");
    return 0;
}

void ParseLocation(string location, int& shelf, int& row, int& bin)
{
    string temp;
    
    temp = location.substr(0,1) + location.substr(1,1);//strip the first twp chars in the string with substr
    shelf = atoi(temp.c_str()); //convert to stripped chars from string to int
    
    cout<<shelf<<endl; //string chars converted to int
    
    temp = location.substr(2,1) + location.substr(3,1);
    row = atoi(temp.c_str());
    
    cout<<row<<endl; //row strings converted to int
    
    temp = location.substr(4,1) + location.substr(5,1);
    bin = atoi(temp.c_str());
    
    cout<<bin<<endl;
}

Reasonable approach. I was thinking you should do this a step or two from now, but you need to do it anyway, so go for it. You are going to run into a problem here:

void Part::Initialize(string pDscript, float uPrice, int QOH, int MRQ)
{
     pDscript = pDscript;
     uPrice = uPrice;
     QOH = QOH;
     MRQ = MRQ;
}

Line 3:

pDscript = pDscript[B];[/B]

You're assigning a local variable to itself. It already was itself, so that does nothing. I know what you are TRYING to do here, but that is not what is happening.

Google the keyword "this". "this" refers to the current object. The way you have it:

class Part
{
      public:
             Part();
             void Initialize(string, float, int, int);
             
      private:
              string pDscript;
              float uPrice;
              int QOH;
              int MRQ;
};



void Part::Initialize(string pDscript, float uPrice, int QOH, int MRQ)
{
     pDscript = pDscript;
     uPrice = uPrice;
     QOH = QOH;
     MRQ = MRQ;
}

Red refers to red, green refers to green. Note that the class variable is green. Everything in the function is red. That's not what you want. You want the following:

class Part
{
      public:
             Part();
             void Initialize(string, float, int, int);
             
      private:
              string pDscript;
              float uPrice;
              int QOH;
              int MRQ;
};



void Part::Initialize(string pDscript, float uPrice, int QOH, int MRQ)
{
     this.pDscript = pDscript;
     uPrice = uPrice;
     QOH = QOH;
     MRQ = MRQ;
}

Green refers to green, red refers to red. Adding the keyword "this" with a dot tells the compiler you intend for it to use the class variable, not the function parameter variable.

Your other option besides using "this" is to name the parameter variables slightly different from the class variables:

void Part::Initialize(string script, float uPrice, int QOH, int MRQ)
{
     pDscript = script;
     uPrice = uPrice;
     QOH = QOH;
     MRQ = MRQ;
}

When two variables have the same name, you must tell the compiler which to use or it assumes that you want to use the local variable, not the class variable. Do the same for the other three variables.

My bad. Wrong operator. Use the -> operator, not the dot operator:

Incorrect:

this.pDscript = pDscript;

Correct:

this->pDscript = pDscript;

A line in this code is causing my program to crash and I implemented what you said

void readData()
{
string location, dScript;
ifstream fin;
int shelf, row, bin;
float price;
int quant, reorder;
Part item[9][7][12];

fin.open("num.data");

while(!fin.eof())
{
 fin>>location>>dScript>>price>>quant>>reorder;
 ParseLocation(location, shelf, row, bin);
 item[shelf][row][bin].Initialize(dScript, price, quant, reorder);
}
fin.close();

In class

void Part::Initialize(string dScript, float price, int quant, int reorder)
{
 this->pDscript = dScript;
 this->uPrice = price;
 this->QOH = quant;
 this->MRQ = reorder;
}

The time of limit of editing post need to be abolished to stop mutiple thread bumping.

These posts are mainly for veron however, my problem seems to be inside the while loop assigningt the values of shelf row and bin something in the loop is not liked too much by C++ and compiler because If I take out the 3-D Array.Initialize... of course default values will be assigned to it of 0 0 0 and i did a simple call of outputting the description and it works fine

and once again it is in the there with the Initialization of the function, I am sure it is something I am overlooking possibly
I remove the function after the array no crash, remove array before init function says variable undeclared and everything is spelled correctly can it not be called to a function in not main?

Here the code is

Part inventory[9][7][12];

Second array

int location;
string pDscript;
float uPrice;
int QOH; 
int MQG;

Have a function that parses location into shelf, row and bin, and call it:

void ParseLocation (int location, int& shelf, int& row, int& bin);

starting part

inventory[shelf][row][bin].Initialize (pDscript, uPrice, QOH, MQG);

this should help to operate it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.