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?