Lines of zeros when reading from file

I am trying to read the following information from a file called inputInventory.txt but i get a bunch of zeros when ran
Im trying to get in this format
shea butter 2.00 20 0
mint shampoo 5.00 15 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
  #include<iostream>
#include<string>
#include<fstream>
#include<sstream>
#include<iomanip>

using namespace std;

void logo(); //function prototype
void menu(); //function prototype
bool readInvetory(string[], double[], int[][2]); //function prototype
void displayInventory(string[], double[], int[][2]);  //function prototype
void writeFile(string[], double[], int[][2]); //function prototype
//Alex Dubraj

const string FILE_INPUT = "inputInventory.txt";
const string FILE_OUTPUT = "outputInventory.txt";
const int MAX = 10;
string itemNames[MAX];
double itemCost[MAX];
int itemNoShip[MAX][2];
//Alex Dubraj
int main()
{

    int choice;
    ifstream inputFile(FILE_INPUT, ios::in);
    string line;

    for (int i = 0; i < MAX; i++)
    {
        inputFile >> itemNames[i] >> itemCost[i] >> itemNoShip[i][0] >> itemNoShip[i][1];
    }

    do
    {
        logo();
        menu();
        cin >> choice;
        switch (choice)
        {

        case 1:
            displayInventory(itemNames, itemCost, itemNoShip);
            break;
        case 2:
            cout << "You pressed 2!"; //testing switch statement 2
            break;
        case 3:
        {
            cout << "File written to outputInventory.txt..." << endl;
            cout << endl;
            writeFile(itemNames, itemCost, itemNoShip); //testing switch statement 3
            break;
        }
        case 4:
            cout << "You pressed 4! GoodBye!"; //testing switch statement 4
            break;

        default:
            cout << "Invalid Menu Item entered...must enter 1-4..." << endl;
        }
    } while (choice != 4);

    inputFile.close();

}
//Nicolas Polanco
void logo()
{
    cout << "Vander Vormar's Galaxy Diner" << endl;
    cout << "********************************" << endl;
    cout << "       **          **" << endl;
    cout << "       **          **" << endl;
    cout << "        **        **" << endl;
    cout << "         **      **" << endl;
    cout << "          **    **" << endl;
    cout << "           *****" << endl;
    cout << "            ***" << endl;
    cout << "" << endl;
    cout << "********************************" << endl;
}

void menu()
{
    cout << "1.  Read Inventory" << endl;
    cout << "2.  Display Inventory" << endl;
    cout << "3.  Write to file" << endl;
    cout << "4.  Exit" << endl;
}

//Alex Dubraj
void writeFile(string itemNames[], double itemCost[], int itemNoShip[][2])
{
    ofstream outputFile;
    outputFile.open(FILE_OUTPUT, ios::out);
    for (int i = 0; i < MAX; i++)
    {
        outputFile << setw(13) << itemNames[i] << setw(6) << itemCost[i] << setw(6);
        outputFile << itemNoShip[i][0] << setw(6) << itemNoShip[i][1] << endl;
    }


} 
void displayInventory(string[], double[], int[][2])
{

    ifstream inputFile;
    inputFile.open(FILE_INPUT, ios::in);
    for (int i = 0; i < MAX; i++)
    {

        inputFile >> itemNames[i] >> itemCost[i] >> itemNoShip[i]
            << endl;

        
    }




}

bool readInventory(string itemNames[], double itemCost[], int itemNoShip[][2])
{
    bool open = false;
    ifstream inputfile;
    inputfile.open(FILE_INPUT);
    
    if (inputfile)
    {
        open = true;
        getline(inputfile, itemNames[]);

        inputfile >> itemCost[];
        inputfile >> itemNoShip[][0]; 
        inputfile >> itemNoShip[][1];
        cout << endl;
        cout << "File read successfully...\n";
    
        inputFile.close();
    }
     else {
        cout << "File missing!" << endl;
    }


    return open;


}
It is invariably better to isolate the problem and write a short program. Assuming the data is well-formed with 2 strings (always) followed by 3 numbers (always):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main () {
    string word_1, word_2;
    double number_1;
    int number_2, number_3;
    
  ifstream myfile ("test.txt");
  if (myfile.is_open())
  {
    while ( myfile >> word_1 >> word_2 >> number_1 >> number_2 >> number_3)
    {
      cout
        << word_1 + ' ' + word_2  << ' '
        << number_1 << ' ' << number_2 << ' ' << number_3 << '\n';
    }
    myfile.close();
  }

  else cout << "Unable to open file";

  return 0;
}


test.txt:
shea butter 2.00 20 0
mint shampoo 5.00 15 1



Output:
shea butter 2 20 0
mint shampoo 5 15 1
Program ended with exit code: 0





More answer than you asked for, but here goes:


(1) using namespace std;


You should learn to write programs without the using namespace std; line. Your program does so few things using standard objects it would be ever so easy to just change every coutstd::cout, etc.

1
2
3
4
5
6
7
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

//using namespace std; 


(2) Globals & constants


It is my opinion that globals, constant or otherwise, should be listed first thing in your source code. In your case, however, the only objects you should have as globals are the input and output filenames. Everything else should be a local variable in main().

9
10
const string FILE_INPUT = "inputInventory.txt";
const string FILE_OUTPUT = "outputInventory.txt";
19
20
21
22
23
24
int main()
{
    const int MAX = 10;
    string itemNames[MAX];
    double itemCost[MAX];
    int itemNoShip[MAX][2];


(3) Naming issues


You have three arrays:
 • itemNames
 • itemCost (no ‘s’?)
 • itemNoShip (???)

The first problem is semantic: you have an array of multiple names, and a matching array of multiple cost... er, costs? Pick one or the other, but mixing and matching looks sloppy.

23
24
25
    string itemNames[MAX];
    double itemCosts[MAX];
    int itemNoShips[MAX][2];
23
24
25
    string itemName[MAX];
    double itemCost[MAX];
    int itemNoShip[MAX][2];

The second issue is clarity. I have no idea what a “NoShip” tuple is. If it is:
 • number in inventory
 • number shipped
then that is two separate things, and again we have a weird semantic problem. If an item is composed of:
 • name
 • cost
 • inventory
 • number shipped
...then why are the last two grouped while the first two are not also?

Either use a strut to manage a complete item:
12
13
14
15
16
17
18
struct Item
{
  string name;
  double cost;
  int inventory;
  int shipped;
};
19
20
21
22
int main()
{
    const int MAX = 10;
    Item items[MAX];


...or use four separate arrays:
19
20
21
22
23
24
25
int main()
{
    const int MAX = 10;
    string itemName[MAX];
    double itemCost[MAX];
    int itemNumber[MAX];
    int itemShipped[MAX];


(4) Array size VS array used
this is the cause of the problem you are asking about


An array has a size (which you have declared with MAX) but the problem is that you have a variable number of items. Your code, however, assumes that there are always MAX items. Given your two-item example, you then have 8 unused-but-still-displayed items, each named "". See why you get a bunch of zeros?

The way to fix it is to keep track of the number of items you read from file.

19
20
21
22
23
int main()
{
    const int MAX = 10;
    Item items[MAX];
    int itemCount = 0;  // start with zero items 


Every time you successfully read an item from file you increment the item count. This leads into to the next problem:


(5) file reading issues


You have a function to read inventory, but you do not use it. You will need to provide a proper prototype and matching function below which modifies both your item array and your item count:

 
bool readInventory( Items items[], int & itemCount, int MAX );

You then need to call it properly at the right time:

1
2
3
4
        if (!readInventory( items, itemCount, MAX ))
        {
            std::cerr << "Failure to read inventory!\n";
        }

At the moment you have code on lines 27–33 to read the file instead of using the readInventory() function. If you wish to start your program by reading the file automatically you should replace it with a call to readInventory(). Otherwise you should just get rid of it.
─────

The next trick is to properly implement a read loop. (This is the other reason you are getting zeros.) However, you have made life extra difficult by allowing spaces in your item names AND use spaces to separate fields in your item record. Also, setting field widths when writing the file does you more harm than good (adding an additional difficulty with reading it properly).

Is the file format up to you? That is, can you change it?

Answer that and I (or someone else) can give you more help with reading it properly. (Because as-is it is really kind of beyond your current skill level to read very easily.)


(6) The menu


Your current menu and switch statement do not match. For example, your printed menu says "1" means read the inventory file. But your switch statement instead displays the current items.


That is all to get you started. Please answer the question about your file format.

Oh, and by the way, it looks like Mr. Polanco has done nothing more than print a couple of strings while you are doing all the work (logo() and menu()). You should try to even things out a bit if you want to be graded fairly.
Last edited on
Is the file format up to you? That is, can you change it?
Answer that and I (or someone else) can give you more help with reading it properly. (Because as-is it is really kind of beyond your current skill level to read very easily.)

If the format is sane, there's probably tabs between the fields, so the fields can be read like this (assuming C-style arrays and the strange 2D itemNoShip array must be used):

1
2
3
4
5
while (getline(inputfile, itemNames[i], '\t') && inputfile >> itemCost[i] >> itemNoShip[i][0] >> itemNoShip[i][1])
{
    inputfile.ignore(9999, '\n');
    i++;
}

Note the similarity to https://www.cplusplus.com/forum/general/283045/ which has tabs between the fields, but also has underscores instead of spaces in the first string!
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <fstream>
#include <string>

#include <sstream>

int main ()
{
    std::string word_1, word_2;
    double number_1;
    int number_2, number_3;
    
    std::ifstream myfile ("test.txt");
    if (myfile.is_open())
    {
        
        
        // ALTERNATIVE 1
        while ( myfile >> word_1 >> word_2 >> number_1 >> number_2 >> number_3)
        {
            std::cout
            << "     Name: " << (word_1 + ' ' + word_2) << ' '
            << "No. 1: " << number_1 << ' '
            << "No. 2: " << number_2 << ' '
            << "No. 3: " << number_3 << '\n';
        }
        std::cout << '\n';
        
        
        
        // ALTERNATIVE 2
        myfile.ios_base::clear();
        myfile.seekg (0, myfile.beg);
        
        std::string line;
        std::stringstream iss;
        
        std::string name;
        while (getline(myfile, line))
        {
            std::cout << " Raw line: " << line << '\n';
            
            for( int i = 0; i < 3; i ++)
            {
                size_t pos = line.find_last_of(' ');
                line.replace(pos,1,1,',');
            }
            iss.clear();
            iss.str("");
            
            std::cout << "     Line: " << line << '\n';
            iss << line;
            std::cout << "iss.str(): " << iss.str() << '\n';
            
            char ch; // DUMMY TO HANDLE SEPARATOR
            
            while
                (
                 std::getline(iss, name, ',')  and
                 iss >> number_1 >> ch >> number_2 >> ch >> number_3)
            {
                std::cout
                << "     Name: " << name << ' '
                << "No. 1: " << number_1 << ' '
                << "No. 2: " << number_2 << ' '
                << "No. 3: " << number_3 << "\n\n";
            }
        }
        myfile.close();
    }
    else
        std::cout << "Unable to open file";
    
    return 0;
}



     Name: shea butter No. 1: 2 No. 2: 20 No. 3: 0
     Name: mint shampoo No. 1: 5 No. 2: 15 No. 3: 1

 Raw line: shea butter 2.00 20 0
     Line: shea butter,2.00,20,0
iss.str(): shea butter,2.00,20,0
     Name: shea butter No. 1: 2 No. 2: 20 No. 3: 0

 Raw line: mint shampoo 5.00 15 1
     Line: mint shampoo,5.00,15,1
iss.str(): mint shampoo,5.00,15,1
     Name: mint shampoo No. 1: 5 No. 2: 15 No. 3: 1

Program ended with exit code: 0
Topic archived. No new replies allowed.