KandR2 Entab program clarification

40 views Asked by At

This is Exercise 5-11 in the KandR2 book.

Exercise 5-11. Modify the program "entab" and "detab" (written as exercises in Chapter 1.) to accept a list of tab stops as arguments. Use the default tab settings if there are no arguments.

I just cannot understand what the below code is doing.This is not my code; I had my own code ready but comparing the output of the code below, I doubt my solution. The first code below outputs exactly the same input, it does not shrink the tabs which is what the entab program should do, when I input tabs in the terminal of vscode.

Is it that the program being run on a terminal in vscode causing incorrect output? because he/she who wrote this code used a .txt file to test it getting correct output.

This is the link to the solution https://clc-wiki.net/wiki/K%26R2_solutions:Chapter_5:Exercise_11#Solution_by_anonymous Please do check the link to get a clear picture. What is the issue here?

''' `

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

#define DEFAULT_TAB_STOP 8 // length of default tab stop. For entab, this needs to be the tab stop size of the shell/tool that displays the contents since tabs are in the output.
#define MAX_TABS 1000      // max supported custom tabs

void shellsort(int v[], int n);

int main(int argc, char *argv[])
{
    int c, i = 0, j, k, col = 0, spaces = 0; // i is index in tabs, j is the next custom/default tab stop, k is the distance to the natural tab stops to see if a tab will fit
    int tabs[MAX_TABS];
    while (--argc > 0) // get all arguments and store them in tabs
    {
      if (i >= MAX_TABS)
        return 1; // too many arguments
      else if (isdigit(**++argv)) // only allow arguments that start with a digit
        tabs[i++] = atoi(*argv); // gets all valid digits in string and turns it into an int
      else
         return 2; // argument started with non-digit
    }
int n = 0; // this is used as a multiplier to fill tabs up with the default tab stop if no custom tab stops were provided or not enough of them were provided to fill up tabs
   if (i > 0) // if i > 0, then custom tab stops were provided as an argument
    {
       shellsort(tabs, i); // puts ints in numerical order
       n = tabs[i - 1]; // gets the largest value in tabs
       n += DEFAULT_TAB_STOP - (n % DEFAULT_TAB_STOP); // moves n to the next default tab stop
       n /= DEFAULT_TAB_STOP; // gets the base of the number to use in the next while loop
     }
while (i < MAX_TABS) // adds the rest of the default tabs to tabs array
    tabs[i++] = n++ * DEFAULT_TAB_STOP; // uses base n to get value of next tab stop after the last largest custom one. Appends to it the end of tabs
i = 0; // resets index

while ((c = getchar()) != EOF)
{
    if (c != ' ') // if the char is not a space, all saved spaces need to be processed before it is printed
    {
        while (spaces > 0) // this allows the below logic to only think about things one iteration at a time
        {
            k = DEFAULT_TAB_STOP - (col % DEFAULT_TAB_STOP); // find the next default tab stop
            while (tabs[i] <= col && i < MAX_TABS) // get the next custom/default tab stop
                i++;
            if (i < MAX_TABS)                      // but only if not out of bounds of array
                j = tabs[i] - col;
            if (k <= j && spaces - k >= 0) // if the natural tab is less than the custom tab and there are enough spaces, substitute a tab for the spaces
            {
                putchar('\t');
                col += k; // updates col position
                spaces -= k; // updates spaces used
            }
            else // if natural tab is greater than custom one, fill in the spaces until the custom tab stop is met. Keep track of col position and spaces left
            {
                while (spaces > 0 && j-- > 0)
                {
                    putchar(' ');
                    col++;
                    spaces--;
                }
            }
        }
    }

    switch (c)
    {
    case ' ': // don't print the spaces, but keep track of the number of them (they are processed above)
        spaces++;
        break;
    case '\n': // reset the col and tabs index and print it
        col = 0;
        i = 0;
        putchar(c);
        break;
    case '\t': // find the next custom tab, subtract the number of spaces from it to current col and add that to spaces. These spaces will be processed the next iteration
        while (tabs[i] <= col && i < MAX_TABS)
            i++;
        if (i < MAX_TABS)
            j = tabs[i] - col;
        spaces += j;
        break;
    default: // all other chars are printed and col position is incremented by one
        putchar(c);
        col++;
        break;
    }
}
return 0;
}

// sort v[0]...v[n-1] into increasing order
void shellsort(int v[], int n)
{
   int gap, i, j, temp;

 for (gap = n / 2; gap > 0; gap /= 2)
    for (i = gap; i < n; i++)
        for (j = i - gap; j >= 0 && v[j] > v[j + gap]; j -= gap)
        {
            temp = v[j];
            v[j] = v[j + gap];
            v[j + gap] = temp;
        }
  }` '''

This is an example test of using the text file with entab to see if a tab width of 3 outputs correctly.

cat pipe.txt | ./entab 3 6 9 12 15 18 21 24 27 30 33

Please check the pipe.txt in the link given above as it being displayed here directly causes formatting issues.

This is the result I got:

 PS C:\Users\nivek\OneDrive\Desktop\Ccode\entabcompare1> .\a.exe 5 6 9
      |
      |

I have inputted 5 spaces to reach the custom tabstop 5 and i receive just the input here but in reality according to the original entab program the cursor should be at the 8th position as the default shell/system tabstop is 8.

The expected result is :

`PS C:\Users\nivek\OneDrive\Desktop\Ccode\entab> .\a.exe 5 6 9`
      |
         |

I don't know what's going on here and what is the .txt file doing?

0

There are 0 answers