Thread: detab---improper spacing

  1. #1
    Registered User
    Join Date
    Nov 2009
    Posts
    12

    detab---improper spacing

    Like many others, I'm teaching myself C via K&R and am having a lot of trouble with exercise 1-20, the detab program. My code almost does exactly what I want it to, but the difference is inexplicable. It correctly inserts the number of spaces to replace the tabs; however, it treats the first tab as being 8 characters, but all others as 7. I've poured over the issue for hours; I've even downloaded solutions online and run them, without ever seeing what the problem with my code is.. (Some didn't even work; all implemented the program somewhat differently than I.)

    Would someone please point in the right direction? I appreciate all assistance.

    Here's the code; I'm compiling with a simple "gcc -o detab detab.c", on GNU/Linux kernel 2.6.26, with gcc version 4.3.2. Debian Lenny.
    Code:
    #include <stdio.h>
    
    #define TABSTOP 8
    #define MAXLINE 10000
    
    int getline(char s[], int lim);
    int tabber(char s[], int tabspot);
    
    main()
    {
    	char string[MAXLINE];
    	int i, realspot = 0;
    
    	while (getline(string, MAXLINE) > 0) {
    		for(i=0,realspot=0; string[i] != '\0'; ++i,++realspot)
    			if (string[i] == '\t')
    				realspot += tabber(string,realspot);
    			else 
    				putchar(string[i]);
    	}
    	return 0;
    }
    
    int tabber(char s[], int tabspot)
    {
    	int numspace, i;
    
    	numspace = TABSTOP - (tabspot % TABSTOP);
    	for (i=0; i<numspace; ++i)
    		putchar('_'); 
    	return numspace;
    }
    
    int getline(char s[], int lim)
    {
    	int c, i;
    
    	for (i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
    		s[i] = c;
    	if (c == '\n') 
    		s[i++] = c;
    	s[i] = '\0';
    	return i;
    }

  2. #2
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    So in main(), it seems that i is keeping track of where in the string you are, and realspot is keeping track of where on the terminal things are, right? Thus when you print out a tab, that's only one character (so i advances only 1), but it's actually 1-8 characters, depending on position, and realspot is incremented by this many characters.

    The problem is that you unconditionally increment realspot along with i, each iteration of the loop; but at the same time, when there's a tab, you add the number of spaces you print out to realspot. As a result, realspot's value is one too many (you're counting both the '\t' and the actual spaces, but you shouldn't count the '\t').

    There are multiple ways to fix this, so pick one you think is best.

    I'd also recommend using “int main(void)” instead of just “main()”. While C89 has implicit int, C99 doesn't, and it's good style to declare a return type anyhow. As for (void) versus (), the (void) creates a prototype and () doesn't. This tends not to be a huge issue for main() since you rarely write a program that recursively calls main; but I would argue that consistency is a good thing, and since (void) always means “no parameters” in C, it should always be used for that purpose. Why not avail yourself of the best safety if it's available?

  3. #3
    Registered User
    Join Date
    Nov 2009
    Posts
    12
    Quote Originally Posted by cas View Post
    The problem is that you unconditionally increment realspot along with i, each iteration of the loop; but at the same time, when there's a tab, you add the number of spaces you print out to realspot. As a result, realspot's value is one too many (you're counting both the '\t' and the actual spaces, but you shouldn't count the '\t').
    I wonder why that didn't result in a differing tab length every tab? Instead, it decremented the tab length after the first tab, then resulted in a constant tab length every time thereafter.

    Still, you're obviously correct; I changed the formula to:
    Code:
    realspot += tabber(string,realspot) - 1;
    And everything works fine. So thanks for the assistance.

    Thanks also for the advice on "int main(void)". I'll make that a habit (though won't I rarely have a "void" main, since more often than not I'll have command-line argument to import there?).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Better spacing issues
    By swgh in forum C++ Programming
    Replies: 2
    Last Post: 01-02-2008, 04:46 PM
  2. lowest spacing between numbers
    By Ene Dene in forum C++ Programming
    Replies: 8
    Last Post: 12-05-2007, 04:08 PM
  3. Dev C++ Spacing Problem
    By Darklighter137 in forum C++ Programming
    Replies: 7
    Last Post: 11-13-2006, 10:48 AM
  4. improper pointer/ integer combination?
    By pinkpenguin in forum C Programming
    Replies: 4
    Last Post: 11-16-2005, 03:47 PM
  5. Spacing?
    By trenzterra in forum C++ Programming
    Replies: 5
    Last Post: 11-28-2002, 10:42 PM