Thread: EOF is my nemesis

  1. #1
    Widdle Coding Peon Aerie's Avatar
    Join Date
    Dec 2004
    Posts
    115

    EOF is my nemesis

    I was playing around with a particular solution to the exercise to create a program that would convert whitespaces to tabs, when possible, preserving the original appearance of the text.

    TABSTOP is 8 because that's the number of spaces a tab comes to on my terminal.

    Anyway, this program has performed adequately in every test I could throw at it, save one:

    If I input almost anything, but don't hit Enter at the end, (Instead, hitting Ctrl+D to break the input sequence), the text is 'slightly' off. In the particular case I have in mind, I had a sequence of spaces and tabs with an 'a' right before the end of the input, so I could see where the 'a' ended up after I hit Ctrl+D a few times. The 'a' was about 4 columns to the left of where it should have been, but nearly identical input with a carriage return at the end was handled correctly.

    What confuses me is that -- assuming my console isn't doing anything really weird with the input -- I thought the fillarray function explicitly would check for EOF and break, to '\0' terminate the string if it found it....

    I'm prolly not connecting a couple of obvious dots, but I'd like some help seeing what I'm doing wrong(Oh, yeah, and commentary on better approaches to the original problem would be nice, too.)

    Code:
    #include <stdio.h>
    #define MAXARR 1024
    #define TABSTOP 8
    
    void fillarray(char [], int);
    void parsearray(char []);
    int checknumspaces(char [], int);
    
    int main(void)
    {
    	char charbox[MAXARR];
    
    	fillarray(charbox, MAXARR);
    
    	parsearray(charbox);
    
    	printf("\n----------------\n%s\n", charbox);
    
    	return 0;
    }
    
    void fillarray(char charbox[], int lim)
    {
    	int i, c;
    	i = 0;
    	while((c = getchar()) != EOF && i < lim-1) {
    		charbox[i] = c;
    		i++;
    	}
    	charbox[i] = '\0';
    }
    
    void parsearray(char charbox[])
    {
    	int m, i, s, t, n, lim;
    
    	lim = 0;
    
    	for(i = 0; charbox[i] != '\0'; i++)
    		lim++;
    
    	m = i = s = t = n = 0;
    
    	while(i < lim || m < lim) {
    		s = TABSTOP - ((i - t) % TABSTOP);
    		if(charbox[i] == '\t' || charbox[i] == '\n') {
    			charbox[m] = charbox[i];
    				m++, i++;
    				t = i;
    		}
    		else if(charbox[i] == ' ') {
    			n = checknumspaces(charbox, i);
    			if(n >= s) {
    				charbox[m] = '\t';
    				t = i;
    				m++, i += n;
    			}
    			else if(n == 0)
    				i++;
    			else {
    				charbox[m] = charbox[i];
    				m++, i++;
    			}
    		}
    		else if(charbox[i] == '\0')
    			break;
    		else {
    			charbox[m] = charbox[i];
    			i++, m++;
    		}
    	}
    	charbox[m] = '\0';
    }
    
    int checknumspaces(char charbox[], int i) 
    {
    	int c = 0;
    	while(1) {
    		if(c >= TABSTOP)
    			return c;
    		else if (charbox[i] == ' ')
    			c++, i++;
    		else if(charbox[i] == '\0')
    			return -1;
    		else if(charbox[i] == '\n' || charbox[i] == '\t')
    			return 0;
    		else
    			return c;
    	}
    }
    Last edited by Aerie; 04-26-2005 at 11:36 AM.
    I live in a giant bucket.

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Quote Originally Posted by Aerie
    I was playing around with a particular solution to the exercise...

    (Oh, yeah, and commentary on better approaches to the original problem would be nice, too.)
    What exercise? What problem?

    Tell us what sequence of characters you are entering (exactly), what you expect to see as output and what you are getting as output instead.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Widdle Coding Peon Aerie's Avatar
    Join Date
    Dec 2004
    Posts
    115
    The exercise is from K&R:
    Write a program that replaces strings of blanks by the minimum number of tabs and blanks to achieve the same spacing.

    It also asks whether a space or a tab should be used when either will have the same result; I chose tabs because it was easier to code.

    So the solution I came up with was to always convert any number of whitespaces to tabs except in the situation that it's a series of spaces that is terminated by non-whitespace before the next tabstop. (The way it's coded has the additional effect of stripping spaces from the end of lines, but not tabs)

    How odd, it's now working correctly when I hit Ctrl+D... I think I may have fixed something and forgotten to recompile. (Discovered this when trying to replicate te problem -- I can't make it do the same thing it was, now)

    Anyway, commentary on the actual solution I came up with would be appreciated.
    I live in a giant bucket.

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    For the moment, something else to look at:
    http://users.powernet.co.uk/eton/kandr2/krx121.html
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Widdle Coding Peon Aerie's Avatar
    Join Date
    Dec 2004
    Posts
    115
    Neither solution on that page work, Dave.

    I changed the defines for TABSTOP and TAB2SPACE to 8 and compiled both and they totally didn't work.

    Edit: they work till you do things like
    Code:
    "                         \t             \t              \t        a"
    Last edited by Aerie; 04-26-2005 at 12:55 PM.
    I live in a giant bucket.

  6. #6
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    That looks like way too much work to accomplish:
    Write a program that replaces strings of blanks by the minimum number of tabs and blanks to achieve the same spacing.
    Code:
    itsme@dreams:~/C$ cat blanks.c
    #include <stdio.h>
    #include <string.h>
    
    #define SPACES_PER_TAB 8
    
    void do_string(char *str)
    {
      int len = strlen(str);
      int ntabs, nspaces;
      char *s = str;
    
      printf("Before (%06d chars): '%s'\n", len, str);
    
      ntabs = len / SPACES_PER_TAB;
      nspaces = len % SPACES_PER_TAB;
    
      while(ntabs--)
        *s++ = '\t';
      while(nspaces--)
        *s++ = ' ';
      *s = '\0';
    
      printf("After  (%06d chars): '%s'\n", s - str, str);
    }
    
    int main(void)
    {
      int i;
      char strings[5][80] = { "       ",
                              "                                  ",
                              "               ",
                              "   ",
                              "                      " };
    
      for(i = 0;i < 5;++i)
        do_string(strings[i]);
    
      return 0;
    }
    That looks alright on mine...
    If you understand what you're doing, you're not learning anything.

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by Aerie
    Neither solution on that page work, Dave.

    I changed the defines for TABSTOP and TAB2SPACE to 8 and compiled both and they totally didn't work.

    Edit: they work till you do things like
    Code:
    "                         \t             \t              \t        a"
    For the first one, you may want to change the hard-coded 3's to (TAB2SPACE - 1) as well, judging from the comments.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #8
    Widdle Coding Peon Aerie's Avatar
    Join Date
    Dec 2004
    Posts
    115
    Uh, itsme, I infered from the way the surrounding text was written that this program was supposed to be able to accept any input and convert it appropriately... including indiscriminately mixed tabs and spaces. I'm not so sure your code would be able to do that, either.
    I live in a giant bucket.

  9. #9
    Widdle Coding Peon Aerie's Avatar
    Join Date
    Dec 2004
    Posts
    115
    Dave: Let me look at the code again. I only changed the define, assumed that would take care of things. Seems kind of stupid to post a solution where you put the magic number in a define, then go and hardcode it anyway...
    I live in a giant bucket.

  10. #10
    Widdle Coding Peon Aerie's Avatar
    Join Date
    Dec 2004
    Posts
    115
    I replaced each 3 with (TAB2SPACE-1) and ran it again... the results were even more hideous.

    Edit: Uh, nevermind. That was me being stupid and re-copying the code, fixing the numbers, but forgetting to change the original define to 8 from 4 again.
    Last edited by Aerie; 04-26-2005 at 01:19 PM.
    I live in a giant bucket.

  11. #11
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Well, "strings of blanks" sounds like a string of blanks to me. And from "minimum number of tabs and blanks" you can infer that blanks = spaces. So it seems like my program meets the exercise's requirements. It looks like you're going one step further
    If you understand what you're doing, you're not learning anything.

  12. #12
    Widdle Coding Peon Aerie's Avatar
    Join Date
    Dec 2004
    Posts
    115
    Hah, hah. Yeah, I know I could have scraped by doing that, but I wanted to address a slightly more interesting problem, wherein "blanks" is defined as "any whitespace."

    (Of course, I'm also the guy who, in 4th grade, astounded his teacher by calculating out the volume of a 3d object on paper when she asked for the area of a 2d object -- not exactly hard math, even at that age, but more than she asked for)

    Edit:

    Given the actual problem I chose to address, how would you rate my solution?
    I live in a giant bucket.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. EOF Explanation Anybody?
    By blackcell in forum C Programming
    Replies: 1
    Last Post: 01-29-2008, 09:09 PM
  2. EOF or not EOF?
    By CornedBee in forum Linux Programming
    Replies: 2
    Last Post: 09-14-2007, 02:25 PM
  3. EOF messing up my input stream?
    By Decrypt in forum C++ Programming
    Replies: 4
    Last Post: 09-30-2005, 03:00 PM
  4. whats the deal with EOF really ???
    By gemini_shooter in forum C Programming
    Replies: 7
    Last Post: 03-06-2005, 04:04 PM
  5. files won't stop being read!!!
    By jverkoey in forum C++ Programming
    Replies: 15
    Last Post: 04-10-2003, 05:28 AM