Kamal
Kamal

Reputation: 630

trouble reading from file in c++

I am trying to read a file where the first line is a integer, and the next line is a string (I have to read this into a char array). I used the >> operator on the input stream object to read the integer, then i used the .get() method and the .ignore() method to read the next line into a char array, however when i try to read into the char array i get a blank string I'm not sure why I get a blank string, do you know why this could be?

Here is the code that I use to read from the file:

BookList::BookList()
{
    //Read in inventory.txt and initialize the booklist
    ifstream invStream("inventory.txt", ifstream::in);
    int lineIdx = 0;
    int bookIdx = 0;
    bool firstLineNotRead = true;

    while (invStream.good()) {
        if (firstLineNotRead) {
            invStream >> listSize;
            firstLineNotRead = false;
            bookList = new Book *[listSize];
            for (int i = 0; i < listSize; i++) {
                bookList[i] = new Book();
            }

        } else {
            if (lineIdx % 3 == 0) {
                char tempTitle[200];
                invStream.get(tempTitle, 200, '\n');
                invStream.ignore(200, '\n');
                bookList[bookIdx] = new Book();
                bookList[bookIdx]->setTitle(tempTitle);
            } else if (lineIdx % 3 == 1) {
                int bookCnt;
                invStream >> bookCnt;
                bookList[bookIdx]->changeCount(bookCnt);
            } else if (lineIdx % 3 == 2) {
                float price;
                invStream >> price;
                bookList[bookIdx]->setPrice(price);
                bookIdx++;
            }
            lineIdx++;
        }
    }
}

so listSize is the first integer that is read from the first line in the file, and tempTitle is a temporary buffer used to read in the string from the second line of the file. But when I do invStream.get() and invStream.ignore(), I see the tempTitle string is blank. why?

Upvotes: 1

Views: 76

Answers (2)

Jerry Coffin
Jerry Coffin

Reputation: 490018

After you read the first integer in from the file, there's a new-line in the file waiting to be read.

You then proceed to tell it to read a string. It does so--interpreting the new-line as the end of the string, so the string you read is empty.

After that, everything's out of kilter, so all the rest of the reading is pretty much guaranteed to fail (at least fail to achieve what you want).

As an aside, I'd go about a task like this rather differently--probably more like this:

#include <iostream>
#include <vector>
#include <bitset>
#include <string>
#include <conio.h>

class Book {
    std::string title;
    int count;
    float price;
public:

    friend std::istream &operator>>(std::istream &is, Book &b) {
        std::getline(is, title);
        is >> count;
        is >> price;
        is.ignore(100, '\n');
        return is;
    }
};

int main() {
    int count;

    std::ifstream invStream("inventory.txt");

    invStream >> count;
    invStream.ignore(200, '\n');

    std::vector<Book> books;

    Book temp;

    for (int i = 0; i<count && invStream >> temp;)
        books.push_back(temp);
}

Upvotes: 3

R Sahu
R Sahu

Reputation: 206557

You can most likely fix your program by swapping the lines

invStream.get(tempTitle, 200, '\n');
invStream.ignore(200, '\n');

i.e., use:

invStream.ignore(200, '\n');
invStream.get(tempTitle, 200, '\n');

As a general guideline, if the contents of a file are formatted such that lines of text have specific meaning, it will be easier for you to read the contents of the file line by line and process the contents of each line.

std::string line;
while (getline(invStream, line)) {

   if (firstLineNotRead) {
      // Extract the listSize from the first line using 
      // a istringstream.
      std::istringstream str(line);
      str >> listSize;
      firstLineNotRead = false;
      bookList = new Book *[listSize];
      for (int i = 0; i < listSize; i++) {
         bookList[i] = new Book();
      }
   }

   else {
      // The line has already been read.
      // Use it.

      ...

   }
}

Upvotes: 1

Related Questions