Hoang Minh
Hoang Minh

Reputation: 1220

Read int and string with a delimeter from a file in C++

I'm trying to read line by line in a file. Basically each line will have the Id number, price, qty and the name of the book. I know that after each input, I have to put the delimiter flag there to stop the reading, but I don't know how. I was trying to use getline(), yet, getline() can only take in a string, and that is not the case for the id #, the price and the qty. Would anyone care to show me the way how to read the file ? Thank you, and this is what I have so far.

Example: The file should contain many line, each line will have a format like this: - The first number is the id number - The second one is the price - Third one is the qty - The last one is the title of the book

123,19.99,5,summer is fun

void ReadFromFile(int ids[], int prices[], int qty[], string titles[], int& count)
{
    ifstream infile("tomatoes.txt");
    if(!infile.is_open())
        cout << "File does not exists" << endl;
    else
    {
        while(!infile.eof())
        {
            infile >> ids[count];
            infile >> prices[count];
            infile >> qty[count];
            getline(infile, titles[count]);
            if(!infile.eof())
                count++;
        }
    }
}

Upvotes: 2

Views: 4780

Answers (3)

Thomas Matthews
Thomas Matthews

Reputation: 57678

So, here we go again, another parsing issue.

The fundamental read loop.
Reading a file does not use the eof method to determine end of file. You can search StackOverflow for "c++ read eof while" for some examples.

std::string textline;
while (getline(infile, textline)
{
}

The above loop will read one text line at a time until it fails reading one, which is usually the end of the file.

Parsing the text
We can parse the text string by treating it as an input stream. This involves using std::istringstream, and getline. There is an overloaded version of getline that will read text until a specified delimiter is found. In your case, this delimiter is a comma.

std::string textline;
while (getline(infile, textline)
{
   string comma_string;
   std::istringstream text_stream(textline);
   text_stream >> id;
   getline(text_stream, comma_string, ','); // Read characters after number until comma.
   text_stream >> price;
   getline(text_stream, comma_string, ','); // Read characters after number until comma.
   text_stream >> quantity;
   getline(text_stream, comma_string, ','); // Read characters after number until comma.
   // Read the remaining text, until end of line, as the title.
   getline(text_stream, title, '\n');
}

Storing the record
The input loop has been expanded to read in the fields. They should be stored in an object.

std::string textline;
while (getline(infile, textline)
{
   string comma_string;
   std::istringstream text_stream(textline);
   text_stream >> id;
   getline(text_stream, comma_string, ','); // Read characters after number until comma.
   text_stream >> price;
   getline(text_stream, comma_string, ','); // Read characters after number until comma.
   text_stream >> quantity;
   getline(text_stream, comma_string, ','); // Read characters after number until comma.

   // Read the remaining text, until end of line, as the title.
   getline(text_stream, title, '\n');

   // Put the file data fields into an object.
   book.id = id;
   book.price = price;
   book.quantity = quantity;
   book.title = title;
}

Append data to container

std::string textline;
std::vector<Book> catalog;
while (getline(infile, textline)
{
   string comma_string;
   std::istringstream text_stream(textline);
   text_stream >> id;
   getline(text_stream, comma_string, ','); // Read characters after number until comma.
   text_stream >> price;
   getline(text_stream, comma_string, ','); // Read characters after number until comma.
   text_stream >> quantity;
   getline(text_stream, comma_string, ','); // Read characters after number until comma.

   // Read the remaining text, until end of line, as the title.
   getline(text_stream, title, '\n');

   // Put the file data fields into an object.
   book.id = id;
   book.price = price;
   book.quantity = quantity;
   book.title = title;

   // Append the book to the catalog
   catalog.push_back(book);
}

Conclusion
You should not expect people to give you exactly what you want, but you should be able to take code fragments and compare them to yours and see if you can make them work.

Upvotes: 3

Lother
Lother

Reputation: 1797

There is an overloaded version of get that allows you to specify a delimiter.

One way to solve this is to:

for(int count = 0; infile.eof() == false; count++ )
{
   // for the line
   stringstream currentLine;

   // get a line at a time
   infile.get(currentLine)

   // for the element
   stringstream currentElement;

   // work on that line
   currentLine.get(currentElement,',');
   currentElement >> ids[count];
   currentElement.str();

   currentLine.get(currentElement,',');
   currentElement >> prices[count];
   currentElement.str();

   // etc...

}

Upvotes: 1

rendon
rendon

Reputation: 2363

Read the whole line and then use sscanf() to extract the values:

string line;
getline(infile, line);

int id, quantity;
double price;
char title[20];

sscanf(line.c_str(), "%d,%lf,%d,%[^\n]", &id, &price, &quantity, title);

cout << "id = " << id << endl;
cout << "price = " << price << endl;
cout << "quantity = " << quantity << endl;
cout << "title = " << title << endl;

A little dirty but it works. BTW: %[^\n] reads all characters till the end of the line.

Upvotes: 1

Related Questions