Hey guys.

Im having some trouble with reading from a text file, into a class with strings and ints.

Here is my code for my read file function:

ifstream infile;
	infile.open("books.txt");

	if (infile.good())
	{
		for (int i=0; i<=5;i++)
		{
			getline(infile, book[i].title);  //string
			getline(infile, book[i].isbn);  //string
			getline(infile, book[i].publisher); //string	
			infile >> book[i].year; //int
			infile >> book[i].price; //double
			infile >> book[i].copies; //int
			infile >> book[i].numAuthor; //int
			getline(infile, book[i].author); //string
		}
		infile.close();
	}
	else
		cout << "Error opening file!" << endl;

It seems to work fine reading from the file until it gets to 'numAuthor'. It reads that int in, then nothing happens for 'author'. It automatically skips to the next book, and then reads in the Author of book1, as the title of book2. Here is the output:

TITLE: Book1 Title
ISBN: 1234567
PUBLISHER: ABCDEF
YEAR: 2005
PRICE: $22.5
COPIES: 2
NUMBER OF AUTHORS: 1
AUTHORS: 

TITLE: Author1, Author
ISBN: Book2 Title
PUBLISHER: 7654321
YEAR: 1900
PRICE: $0
COPIES: 0
NUMBER OF AUTHORS: 0
AUTHORS: Default Author

Then from there it stuffs up and just displays the default values set by the default constructor for the class.

What am i doing wrong?

Any help would be greatly appreciated.

Cheers!

Ancient Dragon commented: Thanks for using code tags :) +36

After getting the last integer and before the next string (author) you need to flush the input string of the '\n' line terminator that's left there by the >> operator. See the Read Me How To Flush The Input Stream thread about how to do that. I'm sure that will fix the problem.

Thank you. That seems to have sorted the problem.

My next issue is that i need to update the number of authors if there are more than one.

The simplest way i thought about doing it would be to check if 'numAuthor' is greater than 1, then append the next line onto 'author'.

This is the code i have:

if (book[i].numAuthor == 1)
				getline(infile, book[i].author);
			else if (book[i].numAuthor == 2)
			{				
				string author1, author2;
				getline(infile, author1);			
				getline(infile, author2);
				author1.append(author2);
				book[i].author = author1;
			}
			else if (book[i].numAuthor == 3)
			{
				string author1, author2, author3;
				getline(infile, author1);
				getline(infile, author2);
				getline(infile, author3);
				author1.append(author2);
				author1.append(author3);
				book[i].author = author1;
			}

But i dont think im using the append function properly? I also want it to be stored in 'book.author' with a space and perhaps a comma. So that the output would be:


AUTHORS: Author1, Author2, Author3

How would i go about appending the next 2 or 3 lines to book.author?

Also, another small issue im having after this is that for some reason, after the first book is displayed, then the "AUTHOR: " bit doesnt show anymore?

This is the output:

TITLE: Book1
ISBN: 123456
PUBLISHER: ABCDEF
YEAR: 2005
PRICE: $10
COPIES: 2
NUMBER OF AUTHORS: 1
AUTHORS: Author1

TITLE: Book2
ISBN: 45678
PUBLISHER: BlaBla
YEAR: 2002
PRICE: $50
COPIES: 4
NUMBER OF AUTHORS: 2
Author1,Author2

"AUTHOR: " is missing in the very last line of the output. It should look like this:

AUTHORS: Author1,Author2

But after the first book it doesnt show up anymore? I dont know why?

Any further info will be great. :)

You've done a good job explaining what the problem is and when it occurs. It might be helpful, though, to post an exact input file that had a few examples of single authors and multiple authors. The exact input file is going to let us know what can be assumed and what can't. For example if all of the multiple authors are on the same line, that might affect how you should read it in as opposed to if they are on different lines. That said, it occurs to me that you read in the number of authors first, then you read in the authors. Seems like a tailor-made job for a for-loop:

infile >> book[i].numAuthor;
for (int j = 0; j < book[i].numAuthor; j++)
{
    // read in author i.  Do you have an array or something else to store this in?
    // or are you storing this in a single string called author and you want to
    // append each new writer to the end of book[i].author?  If I read your post
    // right, it is the latter.
}

If you just want to append all the names to the end, something like this could work:

book[i].author = "Steinbeck";
book[i].author += ",";
book[i].athour +"Orwell";
// add more names if there are any

Thanks. I tried to cover everything, but missed an important part of it! haha

The file has the additional authors on new lines, like this:

2
LastName, FirstName
LastName, FirstName

Where 2 is the number of the authors, and obviously the next 2 lines are the authors.

You are right in assuming that i want to append basically those 2 lines, into book.author.

How can i do that whilst still reading them from the file?

Im not sure if that 2nd bit of code you provided would work, if i still have to read them in from the file?

I also tried this but with no luck:


if (book[i].numAuthor == 1)
	getline(infile, book[i].author);  //read straight into book[i].author
else if (book[i].numAuthor == 2)
{				
	string author1, author2;  //declare some temp strings
	getline(infile, author1);  //read in the 1st author into the temp string
	getline(infile, author2);  //read in the 2nd author into the temp string
	author1.append(", ");  //append a space to author1
	author1.append(author2);  //append the 2nd author
	book[i].author = author1;  //set the string to book[i].author
}
else if (book[i].numAuthor == 3)
{
	string author1, author2, author3;  //declare some temp strings
	getline(infile, author1);  //read in 1st author to temp author1 string
	getline(infile, author2);  //read in 2nd author to temp author2 string
	getline(infile, author3);  //read in 3rd author to temp author3 string
	author1.append(", ");  //append a space to author1
	author1.append(author2);  //append the 2nd author
	author1.append(", ");  //append another space to author1
	author1.append(author3);  //append the 3rd author
	book[i].author = author1;  //set the string to book[i].author
}

I can deal with having the if statements like that because i know in the file there is only a maximum of 3 authors.

The above doesnt work though. The output is incorrect.

Thanks. I tried to cover everything, but missed an important part of it! haha

The file has the additional authors on new lines, like this:

2
LastName, FirstName
LastName, FirstName

Where 2 is the number of the authors, and obviously the next 2 lines are the authors.

You are right in assuming that i want to append basically those 2 lines, into book.author.

How can i do that whilst still reading them from the file?

Im not sure if that 2nd bit of code you provided would work, if i still have to read them in from the file?

I also tried this but with no luck:


if (book[i].numAuthor == 1)
	getline(infile, book[i].author);  //read straight into book[i].author
else if (book[i].numAuthor == 2)
{				
	string author1, author2;  //declare some temp strings
	getline(infile, author1);  //read in the 1st author into the temp string
	getline(infile, author2);  //read in the 2nd author into the temp string
	author1.append(", ");  //append a space to author1
	author1.append(author2);  //append the 2nd author
	book[i].author = author1;  //set the string to book[i].author
}
else if (book[i].numAuthor == 3)
{
	string author1, author2, author3;  //declare some temp strings
	getline(infile, author1);  //read in 1st author to temp author1 string
	getline(infile, author2);  //read in 2nd author to temp author2 string
	getline(infile, author3);  //read in 3rd author to temp author3 string
	author1.append(", ");  //append a space to author1
	author1.append(author2);  //append the 2nd author
	author1.append(", ");  //append another space to author1
	author1.append(author3);  //append the 3rd author
	book[i].author = author1;  //set the string to book[i].author
}

I can deal with having the if statements like that because i know in the file there is only a maximum of 3 authors.

The above doesnt work though. The output is incorrect.

Please be more specific about what is wrong with the output. I am guessing that the problem with the output is that the first author doesn't show up? If so, Ancient Dragon touched upon the reason for that (and I forgot to implement it in my sample code). There's an extra '\n' left in the infile buffer that we need to "eat up". Make sure you have this line:

infile.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );

before reading in the authors. I ran this code:

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

struct booklayout
{
    int numAuthor;
    string author;
};


int main ()
{
    booklayout book[5];
    
    ifstream infile;
    infile.open ("input.txt");

    int i = 0;
    infile >> book[i].numAuthor;
    infile.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );

    if (book[i].numAuthor == 1)
    	getline(infile, book[i].author);  //read straight into book[i].author
    else if (book[i].numAuthor == 2)
    {				
    	string author1, author2;  //declare some temp strings
    	getline(infile, author1);  //read in the 1st author into the temp string
    	getline(infile, author2);  //read in the 2nd author into the temp string
    	author1.append(", ");  //append a space to author1
    	author1.append(author2);  //append the 2nd author
    	book[i].author = author1;  //set the string to book[i].author
    }
    else if (book[i].numAuthor == 3)
    {
    	string author1, author2, author3;  //declare some temp strings
    	getline(infile, author1);  //read in 1st author to temp author1 string
    	getline(infile, author2);  //read in 2nd author to temp author2 string
    	getline(infile, author3);  //read in 3rd author to temp author3 string
    	author1.append(", ");  //append a space to author1
    	author1.append(author2);  //append the 2nd author
    	author1.append(", ");  //append another space to author1
    	author1.append(author3);  //append the 3rd author
    	book[i].author = author1;  //set the string to book[i].author
    }	
     
    infile.close ();
    
    cout << book[i].author << endl;
    return 0;
}

with this input file called "input.txt":

3
Steinbeck, John
Twain, Mark
Orwell, George

and got these results:

Steinbeck, John, Twain, Mark, Orwell, George

The for-loop is a separate problem. The code you posted looks fine to me and should work. The for loop gets rid of the if and else if statements, but is basically your code.

infile >> book[i].numAuthor;
    infile.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
    book[i].author = "";
    
    for (int j = 0; j < book[i].numAuthor; j++)
    {
        string temp;
        getline (infile, temp, '\n');
        book[i].author.append (temp);
        book[i].author.append (", ");
    }

The above leaves an extra comma at the end, which you can get rid of with an if-statement inside of the loop.

Thanks. That seems to have solved it. Much appreciate the help.

Now onto figuring out my 'search for books' function. lol

Keep an eye out for another one of my threads. haha

Cheers guys, and thanks again!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.