I am having an issue with Code Blocks and Xcode on my Mac. Every time I run the code on Code Blocks I receive Segmentation Fault 11 and when I try on Xcode I receive Thread 1: exc_bad_access (code=1 address=0x0xffffffff0000000a). However, if I run this code on a PC via Code Blocks it runs. Does anybody know how to solve this so I can run the program on my Mac.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
struct Book
{
string isbn;
string title;
string author;
double price;
string seller;
};
int main()
{
Book booklist[100];
ifstream infile;
ofstream outfile;
//int numBooks = 0;
int i=0;
char dummy;
outfile.open("readBooks.txt");
infile.open("usedBooks.txt");
if (infile.fail())
{
cout << "The file doesn't exist";
exit(-1);
}
else
{
//for (i=0; i<100; i++)
while (!infile.eof())
{
getline (infile, booklist[i].isbn);
getline (infile, booklist[i].title);
getline (infile, booklist[i].author);
infile >> booklist[i].price;
infile.get(dummy);
getline (infile, booklist[i].seller);
outfile << "ISBN: " << booklist[i].isbn << endl;
outfile << "Title: " << booklist[i].title << endl;
outfile << "Author: " << booklist[i].author << endl;
outfile << "Price: " << booklist[i].price << endl;
outfile << "Seller: " << booklist[i].seller << endl << endl;
i++;
}
}
}
Book booklist[100];
Using magic numbers is poor practice. Are you sure that i
is always less than 100 later in your program? If not then your program may do strange things. You should use std::vector<Book> booklist;
instead. You might also want to use vector's at()
member function to avoid mistakes with indexing the array out of bounds.
//for (i=0; i<100; i++)
while (!infile.eof())
{
Using the .eof()
check with C++ streams in loop conditions is almost always wrong. Instead you probably want:
// returns true of book is successfully read, false otherwise
bool read_book(std::istream &is, Book &book) {
Book tmp;
if (getline(is, tmp.isbn) &&
getline(is, tmp.title) &&
getline(is, tmp.author) &&
is >> tmp.price)
{
is.get(dummy);
if (getline(is, tmp.seller)) {
book = tmp; // book = std::move(tmp)
return true;
}
}
return false;
}
int main() {
std::vector<Book> booklist;
// ...
Book book;
while (read_book(infile, book)) {
booklist.push_back(book);
}
// ...
}
You should always check the result of input operations, and checking eof()
on C++ streams does not do the correct check.
Your following line is causing the problem
while (!infile.eof())
As it depends on what is the size of the file, however your array size is fixed and(.i.e. 100 where you are storing the data).
You should use std::vector in your program as :
std::vector<Book> booklist;
while(/*check about infile>>x instead of !infile.eof()*/) {
Book tmp;
getline (infile, tmp.isbn);
getline (infile, tmp.title);
getline (infile, tmp.author);
infile >> tmp.price;
infile.get(dummy);
getline (infile, tmp.seller);
outfile << "ISBN: " << tmp.isbn << endl;
outfile << "Title: " << tmp.title << endl;
outfile << "Author: " << tmp.author << endl;
outfile << "Price: " << tmp.price << endl;
outfile << "Seller: " << tmp.seller << endl << endl;
//Add into the vector after filling the data into the
//struct Book instance tmp
booklist.push_back(tmp);
}
EDIT
Yes, I we should not check the infile.eof() as this is not reliable way to identify the end of file. Instead of this we should check infile>>x. For more information please refer ISOCPP FAQ link on this: http://isocpp.org/wiki/faq/input-output#istream-and-eof