Thread: Reading a file containing a blank line

  1. #1
    Registered User
    Join Date
    Jan 2011
    Posts
    2

    Reading a file containing a blank line

    Hey everyone,

    i want to read in a file that has two parts. The first part is letters and the second part is numbers. They are separated by a blank line.

    I'm having trouble actually finding the blank line that separates the two parts of the text file.

    So the file format is:
    a b c d
    e f g h
    i j k l

    1 2 3
    4 5 6
    7 8 9

    and so forth.

    Here's what I'm trying to do

    Code:
            string t1, t2, t3, t4;
    	int n1, n2, n3;
            int blankFound = 0;
    	while (!in1.eof()&&(blankFound==0)) {            // read first part of file
    		string s;
    		getline(in1, s);
    		if(s.compare("")==0){
                           blankFound=1;
                    }
    		in1 >> t1 >> t2 >> t3 >> t4;
    		cout << t1 << t2 << t3 << t4 << endl; 
    	}
    	while(!in1.eof()) {                                         //read second part
    		in1 >> n1 >> n2 >> n3;
    		cout << n1 << n2 << n3 << endl;
    	}
    I get the output (I'm missing the first line of the file somewhere!)

    efgh
    ijlk
    123
    456
    789

    My mixing of getline() and the >> operator is probably not good and is not working out.

    Anyway I can test for a blank line with >> operator? It just seems to skip ahead and read the next text, and if i do noskipws it just reads every white space which isnt whta i want either.

    Any help wud be great,

    Cheers!

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Why wouldn't you just test your input for length = 0 ?
    Blank the blank line should be the only one with length < 1.

  3. #3
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Finding the blank line is not at all important, since operator>> skips whitespace anyway, but you do need to know where you are in the file; if only to extract the right type variables from it. You can also do this in a single loop.

    To find out where you are, you need to execute a statement like

    in1 >> c;

    where c is a char of any name. Then figure out if that c represents a text digit '0' through '9'. If c is a digit, then do

    in1.putback(c);

    and read the group of numbers from in1. Else, do in1.putback(c); and read the group of letters as strings.

    One more thing that I would remove in the existing code is that !in1.eof() expression. For info on what happens when you do that, read this: Cprogramming.com FAQ > Why it's bad to use feof() to control a loop. Despite the title, everything that page says, applies here. You could actually make the in1 >> c expression your loop condition to remedy the mistake, and the loop will end on time; just make sure to always execute the putback(c) call before you actually read the file.
    Last edited by whiteflags; 01-26-2011 at 09:39 PM.

  4. #4
    Registered User
    Join Date
    Jan 2011
    Posts
    2
    Quote Originally Posted by CommonTater View Post
    Why wouldn't you just test your input for length = 0 ?
    Blank the blank line should be the only one with length < 1.
    Hey Tater, do you mean if i change
    Code:
    if(s.compare("")==0){
    to
    Code:
    if(s.length()==0){
    that still skips the first line in the file.

    Also hey whiteflags,

    I need to find the blank line because the file changes from having four variables per line to having 3 variables per line. The four variables can actually be a mix of numbers and letters so I can't rely on a test for variable type.


    Ideally I'd like to do this without getline and just use the >> operator to get the data and also discover the blank line.

    Thanx guys any ideas wud be great!

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You're doomed to be disappointed then, since ">> skips whitespace" means that it will skip the blank line without comment, if you let it.

    And once you determine that s has positive length you need to get your t1 t2 t3 t4 variables out of s, not out of the file.

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Hmmmm... I figured that since a blank line would still have a newline at the end (beginning?) the function would return with length = 0 .... And you are right, in that case he'd have to get his variables out of strings read from the file.

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    And of course, the way to get variables out of strings is to use a stringstream. So far as I can see, there's no way to actually use a stringstream in I/O (whether oversight or deliberate decision I don't know), so you have to use your string s in the getline call, then use that s to initialize a stringstream object, then use >> to get things out of the stringstream.

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Hmmm... Ok.... I suppose I should let this one go, since I'm so new to C++ anything but the most barebones simple advice is bound to be wrong. It's just that is how I would have done it in C...

  9. #9
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Never have eof() as the loop condition. Bad idea.


    Of course, as an alternative to iostream-based parsing, you could use Boost.Spirit for parsing. In spirit, a parser for your file format looks like this:

    Code:
    ((char_ - char_(" \n")) % char_(" \n")) >> "\n\n" >> (int_ % char_(" \n"))
    This reads: parse a list of single characters (not space or newline) separated by space or newline, followed by two consecutive newlines, followed by a list of integers separated by space or newline.

    This parser is rather unflexible in that it requires exactly one whitespace character to separate any two characters. This makes it way easier to write, because a blank line is hard to recognize otherwise. There are other ways to cope with this too, but this is the easiest.

    Once you have this parser, you can parse.
    Code:
    #include <boost/spirit/include/qi_match_attr.hpp>
    #include <boost/spirit/include/qi_char.hpp>
    #include <boost/spirit/include/qi_int.hpp>
    #include <boost/spirit/include/qi_string.hpp>
    #include <boost/spirit/include/qi_operator.hpp>
    using namespace boost::spirit::qi;
    
    void foo() {
      std::vector<char> characters;
      std::vector<int> numbers;
      in1 >> match(
        ((char_ - char_(" \n")) % char_(" \n")) >> "\n\n" >> (int_ % char_(" \n")),
        characters, numbers);
      // characters and numbers now contain the data from the file
    }
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can you help me about tolower() in file
    By nctar in forum C Programming
    Replies: 7
    Last Post: 05-12-2010, 10:04 AM
  2. Reading a specific line from a text file
    By acidrain in forum C Programming
    Replies: 3
    Last Post: 12-01-2009, 02:23 PM
  3. Reading text file by line number
    By whiskedaway in forum C++ Programming
    Replies: 13
    Last Post: 06-16-2009, 10:09 AM
  4. Ignoring line in C++ when reading from file
    By falzone in forum C++ Programming
    Replies: 7
    Last Post: 11-16-2007, 12:08 AM
  5. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM