Search code examples
c++structfstreamdisplaytxt

how to display text file in c++?


I want to display the text file in my c++ program but nothing appears and the program just ended. I am using struct here. I previously used this kind of method, but now I am not sure why it isn't working. I hope someone could help me. Thanks a lot.

struct Records{
    int ID;
    string desc;
    string supplier;
    double price;
    int quantity;
    int rop;
    string category;
    string uom; 
    
}record[50];
void inventory() {
    int ID, quantity, rop;
    string desc, supplier, category, uom;
    double price;

    ifstream file("sample inventory.txt");
    
    if (file.fail()) {
        cout << "Error opening records file." <<endl;
        exit(1);
    }
    
    int i = 0;
    while(! file.eof()){
        file >> ID >> desc >> supplier >> price >> quantity >> rop >> category >> uom;
        record[i].ID = ID;
        record[i].desc = desc;
        record[i].supplier = supplier;
        record[i].price = price;
        record[i].quantity = quantity;
        record[i].rop = rop;
        record[i].category = category;
        record[i].uom = uom;
        i++;
    }  
    
    for (int a = 0; a < 15; a++) {
        cout << "\n\t";
        cout.width(10); cout << left << record[a].ID;
        cout.width(10); cout << left << record[a].desc;
        cout.width(10); cout << left << record[a].supplier;
        cout.width(10); cout << left << record[a].price;
        cout.width(10); cout << left << record[a].quantity;
        cout.width(10); cout << left << record[a].rop;
        cout.width(10); cout << left << record[a].category;
        cout.width(10); cout << left << record[a].uom << endl;
    }
    
    file.close();
}

Here is the txt file: enter image description here


Solution

  • Here are a couple of things you should consider.

    1. Declare the variables as you need them. Don’t declare them at the top of your function. It makes the code more readable.
    2. Use the file’s full path to avoid confusions. For instance "c:/temp/sample inventory.txt".
    3. if ( ! file ) is shorter.
    4. To read data in a loop, use the actual read as a condition while( file >> ID >>... ). This would have revealed the cause of your problem.
    5. Read about the setw manipulator.
    6. file's destructor will close the stream - you don't need to call close()

    Your file format consists of a header and data. You do not read the header. You are trying to directly read the data. You try to match the header against various data types: strings, integers, floats; but the header is entirely made of words. Your attempt will invalidate the stream and all subsequent reading attempts will fail. So, first discard the header – you may use getline.

    Some columns contain data consisting of more than one word. file >> supplier reads one word, not two or more. So you will get "Mongol", not "Mongol Inc." Your data format needs a separator between columns. Otherwise you won’t be able to tell where the column ends. If you add a separator, again, you may use getline to read fields.

    The CATEGORY column is empty. Trying to read it will result in reading from a different column. Adding a separator will also solve the empty category column problem.

    This is how your first rows will look like if you use comma as separator:

    ID,PROD DESC,SUPPLIER,PRICE,QTY,ROP,CATEGORY,UOM
    001,Pencil,Mongol Inc.,8,200,5,,pcs
    

    A different format solution would be to define a string as a zero or more characters enclosed in quotes:

    001 "Pencil" "Mongol Inc." 8 200 5 "" "pcs"

    and take advantage of the quoted manipulator (note the empty category string):

    const int max_records_count = 50;
    Record records[max_records_count];
    
    istream& read_record(istream& is, Record& r) // returns the read record in r
    {
      return is >> r.ID >> quoted(r.desc) >> quoted(r.supplier) >> r.price >> r.quantity >> r.rop >> quoted(r.category) >> quoted(r.uom);
    }
    
    istream& read_inventory(istream& is, int& i) // returns the number of read records in i
    {
      //...
      for (i = 0; i < max_records_count && read_record(is, records[i]); ++i)
        ; // no operation
      return is;
    }