-3

Using the below code I am reading a .txt file and I can't get it to output properly. It either doesn't break the first input correctly (with all comma delimiters) or it doesn't break properly if I only use a comma delimiter after only the item name (2nd item in the text file).

Here the code:

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

int main()
{
    ifstream inventoryFile;
    string itemType[100], itemName[100], matCost[100], manHours[100];
//  float matCost[100], manHours[100];
    string temp;

    inventoryFile.open("items2.txt");

    cout << endl << endl;

    if(!inventoryFile)
    {
        cout << "\n\nCan't read from file.\n";
        exit(1);
    }
    int numItems=0;

    getline(inventoryFile, temp, ',');
    while(!inventoryFile.eof())
    {
        itemType[numItems] = temp;
        inventoryFile >> itemName[numItems];
        inventoryFile.ignore();
        inventoryFile >> matCost[numItems];
        inventoryFile.ignore();
        inventoryFile >> manHours[numItems];
        inventoryFile.ignore();
        numItems++;
        getline(inventoryFile, temp, ',');
    }

    for(int j=0; j<numItems; j++)
    {
        cout << "Item Type:\t" << itemType[j] << endl;
        cout << "ITem Name:\t" << itemName[j] << endl;
        cout << "Mats Cost:\t" << matCost[j] << endl;
        cout << "Man Hours:\t$" << manHours[j] << endl << endl; 
    }

    return 0;
}

The items.txt file is:

1, Xiphos, 7.46, 2
2, Dao, 3.45, 2.7
3, Jian, 2.31, 0.5
1, Rapier, 8.32, 2.3
2, Hook Sword, 2.11, 0.75
1, Panzerstecher, 2.23, 1.25
2, Kopis, 14.89, 2.3
3, Longsword, 5.43, 0.5
1, Tuck, 2.5, 15
1, Small Sword, 7.5, 2
3, Broadsword, 0.5, 0.25

The items2.txt file is:

1 Xiphos, 7.46 2
2 Dao, 3.45 2.7
3 Jian, 2.31 0.5
1 Rapier, 8.32 2.3
2 Hook Sword, 2.11 0.75
1 Panzerstecher, 2.23 1.25
2 Kopis, 14.89 2.3
3 Longsword, 5.43 0.5
1 Tuck, 2.5 15
1 Small Sword, 7.5 2
3 Broadsword, 0.5 0.25
Christophe
  • 54,708
  • 5
  • 52
  • 107
RockRat
  • 15
  • 3
  • Related, see [How does ifstream's eof() work?](https://stackoverflow.com/q/4533063/608639) and [Why is iostream::eof inside a loop condition considered wrong?](https://stackoverflow.com/q/5605125/608639) – jww Nov 11 '18 at 16:58
  • Please add an example of how you'd like it to look. Also, there's no reference to `items.txt` in the code. Remove it if it's not needed. – Ted Lyngmo Nov 11 '18 at 16:59
  • If you want to continue to use line-based parsing, then you might consider `while(getline(stream, line))`, put `line` in a `stringstream ss(line)`, and then follow with stream parsing with the insertion operator. – jww Nov 11 '18 at 17:04
  • Possible duplicate of [Why does std::getline() skip input after a formatted extraction?](https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction). – πάντα ῥεῖ Nov 11 '18 at 17:07
  • Possible duplicate of [Why does std::getline() skip input after a formatted extraction?](https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction) – jww Nov 11 '18 at 17:11

2 Answers2

0

This should work for the format in items2.txt.

string itemType[100], itemName[100];
float matCost[100], manHours[100];
//...
//getline(inventoryFile, temp, ',');
// get itemType and the whitespace after it
while(inventoryFile >> itemType[numItems] >> std::ws)
{
    std::getline(inventoryFile, itemName[numItems], ',');
    inventoryFile >> matCost[numItems] >> manHours[numItems];
    // don't count this entry if the stream is in a failed state
    if(inventoryFile.fail()) break;
    inventoryFile.ignore();
    ++numItems;
}
Ted Lyngmo
  • 37,764
  • 5
  • 23
  • 50
0

For items.txt this should work:

#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

struct Row {
    int itemType;
    string itemName;
    float matCost;
    float manHours;
};

istream& operator>>(istream& in, Row& row){
    char comma;
    char firstCharOfName;
    in >> row.itemType >> comma >> firstCharOfName;
    in.putback(firstCharOfName);
    getline(in, row.itemName, ',');
    return in >> row.matCost >> comma >> row.manHours;
}

int main() {
    vector<Row> table;
    {
        ifstream inventoryFile("item.txt");
        string line;
        cout << "\n\n";

        if (!inventoryFile) {
            cerr << "\n\nCan't read from file.\n";
            return EXIT_FAILURE;
        }
        while (getline(inventoryFile, line)) {
            // make room for next row
            istringstream iss(line);
            table.resize(table.size() + 1U);
            Row &newRow = table.back();
            iss >> newRow;
            if (!iss) {
                // skip row on error
                table.resize(table.size() - 1U);
            }
        }
    }

    for (int j = 0; j < table.size(); j++) {
        cout << "Item Type:\t" << table[j].itemType << '\n'
             << "ITem Name:\t" << table[j].itemName << '\n'
             << "Mats Cost:\t$" << table[j].matCost << '\n'
             << "Man Hours:\t" << table[j].manHours << "\n\n";
    }

    return EXIT_SUCCESS;
}

PS: Moved the $ to Mats Cost.

Bo R
  • 1,899
  • 1
  • 5
  • 15