Thread: reading fixed length

  1. #1
    Registered User Cpro's Avatar
    Join Date
    Oct 2006
    Posts
    149

    reading fixed length

    I'm reading from a file that is using fixed length entries:
    Code:
    Will       Smith      25 Place        Tulsa           OK 38135     
    Corey      Black      Elm Street      Dallas          TX 89148     
    Tanner     Hall       Mount View      Denver          CO 52742
    And, i have to rewrite the (>>) operator to read the fixed length fields.

    My code:
    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    
    
    class Person
    {
    public:
    	char FirstName [11];
    	char LastName[11];
    	char Address [16];
    	char City [16];
    	char State [3];
    	char ZipCode [10];
    	Person();
    };
    Person::Person()
    {
    	LastName[0] = 0;
    	FirstName[0] = 0;
    	Address[0] = 0;
    	City[0] = 0;
    	State[0] = 0;
    	ZipCode[0] = 0;
    }
    ostream & operator << (ostream & stream, Person & p)
    {	
    	
    	stream << "First Name :" << p.FirstName << endl;
    	stream << "Last Name  :" << p.LastName << endl;
    	stream << "Address    :" << p.Address << endl;
    	stream << "City       :" << p.City << endl;
    	stream << "State      :" << p.State << endl;
    	stream << "ZipCode    :" << p.ZipCode << endl;
    	stream << flush;
    
    	return stream;
    }
    istream & operator >> (istream & stream, Person & p)
    {	
    	stream.get(p.FirstName, 11);	
    	stream.get(p.LastName, 11);
    	stream.get(p.Address, 16);
    	stream.get(p.City, 16);
    	stream.get(p.State, 3);
    	stream.get(p.ZipCode, 10);
    	
    
    	return stream;
    }
    
    int main()
    {
    	fstream inFile;
    	inFile.open("fixedlength.txt");
    
    	Person person1;	
    	
    	inFile >> person1;
    	cout << person1;
    	cout << endl;
    	cout << endl;
    	
    	cout << person1.FirstName << "Test" << endl;
    	cout << person1.LastName << "Test" << endl;
    	cout << person1.Address << "Test" << endl;
    	cout << person1.City << "Test" << endl;
    	cout << person1.State << "Test" << endl;
    	cout << person1.ZipCode << "Test" << endl;
    	
    
    	cout << endl;
    	cin.get();
    	cout << endl;
    	return 0;
    }
    So, i want the first 11 characters (including spaces) to be read into first name, the next 11 into last name and so on. For some reason they are not being read in correctly. The output looks like:
    Code:
    First Name :Will
    Last Name  : Smith
    Address    :  25 Place
    City       :   Tulsa
    State      :
    ZipCode    :  OK 3813
    
    
    Will      Test
     Smith    Test
      25 Place     Test
       Tulsa       Test
      Test
      OK 3813Test
    As you can see, the spacing is messed up. The amount of spacing on the first name entry is 10 instead of 11 (one missing space). So, it looks like this space is being read into the next entry (last name), and that is why there is a space before smith. If i increase:
    Code:
    stream.get(p.FirstName, 11);	
    to
    stream.get(p.FirstName, 12);
    the output is even more messed up.
    I originally tried:
    Code:
    stream >> p.FirstName;
    stream >> p.LastName;
    stream >> p.Address;
    stream >> p.City;
    stream >> p.State;
    stream >> p.ZipCode;
    but it wouldn't read in the spaces. Added stream >> noskipws; to that, and it didn't work right.
    Basically i want to force it to read in the fixed amount, even if the characters are spaces.

    Thanks.
    IDE - Visual Studio 2005
    Windows XP Pro

  2. #2
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Why don't you use the istream::read() function and pass the size you want to read?
    The >> operator stops when it hits whitespace, which probably isn't what you want.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    stream.get(p.FirstName, 11) reads 10, not 11, characters into p.FirstName, since the 11th character is the null character. Therefore a space is left in the input stream, and this space is then read by stream.get(p.LastName, 11). One way to solve this is to place a stream.ignore() after each call to get() so as to ignore the next character remaining in the buffer.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User Cpro's Avatar
    Join Date
    Oct 2006
    Posts
    149
    Thank you both. Works now.
    IDE - Visual Studio 2005
    Windows XP Pro

  5. #5
    Registered User Cpro's Avatar
    Join Date
    Oct 2006
    Posts
    149
    Sorry, one more question.
    I'm doing another program that is almost exactly the same, except it reads from a file using length indicators.
    So, the input file looks like:
    Code:
    04Will05Smith0825 Place05Tulsa02OK0538135
    05Corey05Black10Elm Street06Dallas02TX0589148
    So, about everything is the same except:
    Code:
    istream & operator >> (istream & stream, Person & p)
    {	
            int length = 0
            stream >> length;
    
    	stream.get(p.FirstName, length);	
    	stream.get(p.LastName, length);
    	stream.get(p.Address, length);
    	stream.get(p.City, length);
    	stream.get(p.State, length);
    	stream.get(p.ZipCode, length);
    	
    
    	return stream;
    }
    So, i'm reading in the length indicator and reading that many characters into the appropriate place. The problem i am having is that i only want two digits to be read into length. Currently, it will read the number no matter how long it is. So, when it gets to the address:
    Code:
    0825 Place
    It is reading in 825 into length, instead of 8.
    So, i guess my question is, how can i get only two numbers read into "length" while still keeping it an int.
    If there is a better way of doing this, let me know. My way seems to work fine, except for this problem.

    By the way, I copied and pasted my earlier code, so the first bug has not been corrected in this post, but it has in my program.

    Thanks
    IDE - Visual Studio 2005
    Windows XP Pro

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Replies: 3
    Last Post: 03-05-2009, 03:14 AM
  3. Replies: 7
    Last Post: 02-02-2009, 07:27 AM
  4. Reading from binary file; fread problems?
    By pmgeahan in forum C Programming
    Replies: 3
    Last Post: 01-15-2009, 05:07 PM
  5. reading into an int
    By Cpro in forum C++ Programming
    Replies: 2
    Last Post: 07-07-2008, 01:30 PM