Thread: Entab - replacing blanks with tabs and blanks

  1. #1
    Tears of the stars thames's Avatar
    Join Date
    Oct 2012
    Location
    Rio, Brazil
    Posts
    193

    Entab - replacing blanks with tabs and blanks

    Good evening. I have the following exercise from K&R:

    Write a program entab that replaces strings of blanks with the minimum number of tabs and blanks to achieve the same spacing. Use the same stops as for detab . When either a tab or a single blank would suffice to reach a tab stop, which should be given preference?

    What can I do to fit the logic of numberOfBlanks, numberOfTabs and printBlanks inside the code? I mean, I tried to put it after the else but that didn't work. I got something like:

    Sansa s t a r k

    I thought I could get the sum of every occurrence of a white space and then print all blanks after a word.


    Code:
    #include <stdio.h> 
    
    #define MAX_BUFFER 1024
    #define SPACE ' ' 
    #define TAB '\t' 
    
    //  gets a line
    int getLine(char s[], int lim);
    
    // calculates the number of spaces for a tab (a tab = 5 blanks)
    int calculateNumberOfSpaces(int offset, int tabSize);
    
    // calculates only the number of blanks
    int numberOfBlanks(int whitespaces, int tabSize);
    
    // calculates only the number of tabs
    int numberOfTabs(int whitespaces, int tabSize);
    
    // prints the amount of number of blanks and tabs
    void printBlanks(int numberofblanks, int numberoftabs);
    
    void printBlanks(int numberofblanks, int numberoftabs) 
    { 
      int i; 
      for(i = 0; i < numberoftabs; i++) 
      { 
        putchar('\t');  
      }
      for(i = 0; i < numberofblanks; i++) 
      { 
        putchar(' ');  
      }                  
    }      
    
    int numberOfBlanks(int whitespaces, int tabSize) 
    { 
       return whitespaces % tabSize;
    }     
    
    int numberOfTabs(int whitespaces, int tabSize) 
    { 
       return whitespaces/tabSize;
    }     
    
    int calculateNumberOfSpaces(int offset, int tabSize)
    { 
       return tabSize - (offset % tabSize);    
    }          
    
    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;
         ++i;   
       }        
       s[i] = '\0';                     
       return i;
    }
    
    int main() 
    { 
       /* 
        nw - number of white spaces
        tabSize - amount of white spaces for tab
        l - number of characters input
        j - number of spaces for tab
        nb - number of blanks only
        nt - number of tabs only
    
       */
       int i, nw, tabSize, l, j, k, nb, nt; 
       nt = nb = j = nw = i = 0;
       tabSize = 5;
       char buffer[MAX_BUFFER];
       
       while(getLine(buffer, MAX_BUFFER) > 0) 
       { 
         for(i = 0, l = 0; buffer[i] != '\0'; i++) 
         { 
            if(buffer[i] == TAB) 
            { 
              j = calculateNumberOfSpaces(l, tabSize);    
              nw += j;
              
              for(k = 0; k < j; k++) 
              { 
                l++;      
              }
            }
            else if(buffer[i] == SPACE) 
            { 
               ++nw;
               l++;
            }
            else { 
              putchar(buffer[i]);
              l++;    
            }
            /*
            I don't know how to fit these functions
            
            nb = numberOfBlanks(nw, tabSize);  
            nt = numberOfTabs(nw, tabSize);
            printBlanks(nb, nt);                             
            */
         }              
       }           
       return 0;     
    }

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Don't know how this post got missed, sorry for the delayed reply:

    Is this supposed to only "entab" at the beginning of a line, or in the middle too?

    If at the beginning only, the logic is pretty simple. For each line you read:
    1. Calculate the number of "spaces" before the first non-space, i.e. the column number the first non-space char would appear in.
    2. Calculate the number of tabs (spaces / tabsize) and the leftover spaces (spaces % tabsize) required to retab/entab it.
    3. Using loops, print that many tabs followed by that many ("leftover") spaces.
    4. Print the rest of the line.

    Also, I might move that if-else logic from main into calculateNumberOfSpaces.

    If you have to deal with this in the middle of a line too, it's a bit more complicated. I'm not totally clear on what the behavior should be, so I can't really help you.

    On a side note:
    Code:
        /* 
        nw - number of white spaces
        tabSize - amount of white spaces for tab
        l - number of characters input
        j - number of spaces for tab
        nb - number of blanks only
        nt - number of tabs only
     
       */
    If you need a comment block like this, it means your variable names suck. They should have clear, concise, descriptive names. How about numWhitespaces, inputLen, numSpaces, numBlanks, numTabs? Then your code makes sense when you read it and you don't need to keep looking back at the comment block to figure out wtf you were using l for. The usage of a variable is clear every time you type/read it. And l (lower case ell) in particular is a horrible variable name. It often looks very similar or identical to a 1 (one) and I (upper case I).

  3. #3
    Gates' arch nemesis
    Join Date
    Oct 2004
    Posts
    18
    While I agree with anduril's assessment and would make those changes for myself, don't take the "suck" part too roughly. I agree that one-to-two letter variable names rings of 1970s BASIC and FORTRAN programs where for any kind of sophisticated program, its comprehension and maintenance could revolve around keeping straight in one's head the difference between variables A1 and A3 and A4. For a large program with many variables, the value of rich descriptive names becomes high.

    However for very short programs, not such a big deal IMO. As it happens, 90% of my integer loops begin with "for i =" and I sleep well for not having said iLoopControlVariableForBruisedAppleTally And I quite agree with anduril that small letter ell (l) sucks. For a long int, I just declare long dong; and use dong instead of i

    It's a balancing act. I'm just going to be good cop and say that you (thames) didn't do anything tragic by using short names. But the bad cop's advice is sound

    Variable type-suffixes like $ were a big improvement back in the short variable name days, for a while, BTW. A later similar and more modern improvement was "Hungarian notation." It's worth at least a short study for newer coders. It has its proponents and detractors, and its failure to achieve universal use says something. But at least understanding and appreciating how it works at very least, I believe, focuses one's discipline in variable naming.

    Zen counts.

    [BTW anduril, I often tweak abbreviations into 16 letter variable names because I $@#$#$@ing hate scrolling in any direction, and that's sometimes more direct than using an alias. Sometimes I see a couple of more parentheses because I used num or Ctl vs. number or Control. Of course, it still comes down to a balancing act.]
    Last edited by GatesAntichrist; 10-19-2012 at 03:49 PM. Reason: add last para.

  4. #4
    Tears of the stars thames's Avatar
    Join Date
    Oct 2012
    Location
    Rio, Brazil
    Posts
    193
    No problem if the reply took some time. Thank you anyways. I will take a closer look at the variables from now on. The main thing is to make "entabs" between the words and because of this, I got lost. There is another program, from users.powernet.co.uk that I'll analyse. Many thanks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 02-27-2012, 06:38 AM
  2. Need help for program that uses threshold and blanks!
    By BiomedOne in forum C Programming
    Replies: 4
    Last Post: 11-14-2011, 06:11 PM
  3. Fill the blanks in the program...
    By sreeramu in forum C Programming
    Replies: 19
    Last Post: 10-18-2007, 05:26 AM
  4. Fill in the blanks
    By Prelude in forum C++ Programming
    Replies: 22
    Last Post: 09-17-2006, 08:08 AM
  5. please help remove blanks from string
    By cjtotheg in forum C Programming
    Replies: 2
    Last Post: 10-24-2001, 12:21 PM

Tags for this Thread