Search code examples
ctabsmodulokernighan-and-ritchieentab-detab

understanding detab in K&R


I'm teaching myself C and working through K&R. I'm doing exercise 1-20:

Write a Program entab that replaces strings of blanks by the minimum number of tabs and blanks to acheive the same spacing. Use the same tab stops as for detab.

I worked through this program myself, but was reviewing other solutions:

#include<stdio.h>
#define TABINC 8

int main(void)
{
  int nb,pos,c;

  nb = 0;
  pos = 1;

  while((c=getchar())!=EOF)
  {
    if( c == '\t')
    {
      nb = TABINC - (( pos - 1) % TABINC);   // <---- How does this work

      while( nb > 0)
      {
        putchar('#');
        ++pos;
        --nb;
      }
    }
    else if( c == '\n')
    {
      putchar(c);
      pos = 1;
    }
    else
    {
      putchar(c);
      ++pos;
    }
  }

  return 0;
}

I have difficulty understanding how this part works nb = TABINC - (( pos - 1) % TABINC);. Can someone please explain what this is exactly doing step by step? Perhaps walk me through an example?

Thank you.


Solution

  • Consider the following input text:

    \tone\ntwo\tthree\nsixteen\tseventeen\teighteen\n
    

    This is what we want it to produce (tabs replaced with ···):

             Column: |       |       |       |
             123456789012345678901234567890123
    Line: 1  ········one
          2  two·····three
          3  sixteen·seventeen·······eighteen
    

    The number of spaces required for each tab character is always going to be a number from 1 to TABINC (i.e., 8) inclusive. The tabs in the above example are expanded as follows:

    Current   Next tab   No. spaces
    column#   position   required
       1          9         8
       4          9         5
       8          9         1
      18         25         7
    

    You should be able to see a pattern here. If we are already at a tab position (1, 9, 17, etc.), we need to add 8 spaces. And in general, if we are n characters past a tab position (where 0 <= n <= 7), then we need to add 8-n spaces.

    We can calculate n easily:

    n = (pos - 1) % 8
    

    so nb (the number of spaces we need to add) can simply be calculated as follows:

    nb = 8 - n
    

    Hence

    nb = 8 - ((pos - 1) % 8)
    

    Or, more generally,

    nb = TABINC - ((pos - 1) % TABINC)