3

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++;
    }
  }
}
  • You do no checking to see if "i" >= 100. We have no idea how many lines are in that file, so why isn't your while() condition a little more robust? `while (i < 100 && !infile.eof())` – PaulMcKenzie Apr 17 '14 at 17:32
  • I forgot to give you the sample input file: 013283071X Absolute C++, 5th Edition Walter Savitch 71.89 I tried making the while loop more robust but it still does not fix the problem. – user3546210 Apr 17 '14 at 17:41
  • There is currently 76 lines in the input file. – user3546210 Apr 17 '14 at 17:48

2 Answers2

2

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

Mantosh Kumar
  • 5,317
  • 3
  • 19
  • 43
  • @LightnessRacesinOrbit: Thanks for pointing it out. I have corrected it in my post and also mentioned the appropriate link about this information. – Mantosh Kumar Apr 17 '14 at 18:17
  • Better. The problem is not that `eof` is "not reliable"; it's that the check was being performed at entirely the wrong place in the code. By checking for EOF/failures _as_ we read, we remove that problem. – Lightness Races in Orbit Apr 17 '14 at 18:24
2
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.

Community
  • 1
  • 1
bames53
  • 79,748
  • 13
  • 162
  • 229