0

I have a file records.txt that contains the following text:

John    Smith   Sales   555-1234

Mary    Jones   Wages   555-9876

Paul    Harris  Accts   555-4321

I've copied the following code from C++ Programming by Mike McGrath into a file format.cpp to read the data in records.txt:

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

int main()
{
  const int RANGE = 12;
  string tab[RANGE];
  int i = 0, j = 0;
  ifstream reader("records.txt");
  if (!reader)
    {
      cout << "Error opening input file" << endl;
      return -1;
    }
  while (!reader.eof())
    {
      if ((i + 1) % 4 == 0)
        getline(reader, tab[i++], '\n');
      else
        getline(reader, tab[i++], '\t');
    }
  reader.close();
  i = 0;
  while (i < RANGE)
    {
      cout << endl << "Record Number: " << ++j << endl;
      cout << "Forename: " << tab[i++] << endl;
      cout << "Surname: " << tab[i++] << endl;
      cout << "Daprtment: " << tab[i++] << endl;
      cout << "Telephone: " << tab[i++] << endl;
    }
  return 0;
}

Now, in my .emacs file, I have tabs automatically converted to spaces in all my files, per the following command:

(setq-default indent-tabs-mode nil)

So when I compile and run format.out, I get the following output:

$ ./format.out 

Record Number: 1
Forename: John    Smith   Sales   555-1234
Mary    Jones   Wages   555-9876
Paul    Harris  Accts   555-4321

Surname: 
Daprtment: 
Telephone: 

Record Number: 2
Forename: 
Surname: 
Daprtment: 
Telephone: 

Record Number: 3
Forename: 
Surname: 
Daprtment: 
Telephone: 

This isn't what I want. What I want is for each tab-separated item to be printed after its corresponding label.

So I go into emacs and enter the following command to convert spaces to tabs within records.txt:

M-x tabify

But now when I re-run my script, I get a seg fault:

$ ./format.out 
Segmentation fault (core dumped)

Why is this, and what can I do to fix it? (Or, if a reason isn't apparent, what can I do to investigate this further?)

There seems to be a problem in my c++ code, not the file itself, because when I read records.txt in python, I can see that it is as expected:

In [1]: with open('records.txt') as f:
   ...:     x = f.readlines()
   ...:     

In [2]: x
Out[2]: 
['John\tSmith\tSales\t555-1234\n',
 'Mary\tJones\tWages\t555-9876\n',
 'Paul\tHarris\tAccts\t555-4321\n']
dbliss
  • 8,060
  • 13
  • 43
  • 74

1 Answers1

0

You could start by reading why while (!reader.eof()) is wrong, Why is iostream::eof inside a loop condition considered wrong?. Seems the book you copied the code from is not very good.

I expect this is the cause of your seg fault, because of the incorrect eof check you are going too many times around your loop and doing an out of bounds access on your array. You could check this by increasing the size of your array to 13.

Get a better book (what was it by the way?).

Here's a possible way to read the file (untested code)

for (;;)
{
    char delim;
    if ((i + 1) % 4 == 0)
        delim = '\n';
    else
        delim = '\t';
    if (!getline(reader, tab[i++], delim))
        break; // eof or some other error
}
Community
  • 1
  • 1
john
  • 71,156
  • 4
  • 49
  • 68
  • thanks for the heads up. one thing is for sure: the author of the book wanted to highlight the use of the delimiter argument in `getline` in this code sample. i'm not seeing how i can keep the calls to `getline` the same while using the fix suggested at the question you linked to. – dbliss Sep 08 '15 at 07:24
  • increasing the array size to 13 confirmed this is the reason for the seg fault. – dbliss Sep 08 '15 at 07:26
  • i'm wondering whether i'm getting this seg fault (in contrast to what the author is saying he got) because `emacs` adds a new line to the end of my files automatically. – dbliss Sep 08 '15 at 07:27
  • 1
    It's precisely because emacs adds a newline to the end of your file that the code doesn't work. It's this new line that prevents eof being true after the twelfth item has been read. – john Sep 08 '15 at 07:37
  • @dbliss I'll update the code with another way to read the file – john Sep 08 '15 at 07:37
  • okey doke. yeah, i just removed the new line at the end of the file and the code ran as the book proposed it should. the book, by the way, is *c++ programming* by mike mcgrath. – dbliss Sep 08 '15 at 07:40