KandR2 Entab 程序说明

KandR2 Entab program clarification

提问人:Determinante 提问时间:10/24/2023 最后编辑:OkaDeterminante 更新时间:10/24/2023 访问量:37

问:

这是 KandR2 书中的练习 5-11。

练习 5-11。修改程序 “entab” 和 “detab”(在第 1 章中作为练习编写)以接受制表位列表作为参数。如果没有参数,请使用默认选项卡设置。

我只是不明白下面的代码在做什么。这不是我的代码;我已经准备好了自己的代码,但比较下面代码的输出,我怀疑我的解决方案。 下面的第一个代码输出完全相同的输入,当我在 vscode 的终端中输入选项卡时,它不会缩小 entab 程序应该做的选项卡。

是不是程序在 vscode 中的终端上运行导致输出不正确?因为编写此代码的人/她使用.txt文件来测试它获得正确的输出。

这是解决方案的链接 https://clc-wiki.net/wiki/K%26R2_solutions:Chapter_5:Exercise_11#Solution_by_anonymous 请检查链接以获得清晰的图片。 这里有什么问题?

''' `

#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;
        }
  }` '''

这是一个示例测试,将文本文件与 entab 一起使用,以查看选项卡宽度 3 是否正确输出。

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

请检查上面给出的链接中的pipe.txt,因为它在此处显示直接导致格式问题。

这是我得到的结果:

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

我已经输入了 5 个空格来到达自定义制表位 5,我在这里只收到输入,但实际上,根据原始的 entab 程序,光标应该在第 8 个位置,因为默认的 shell/系统制表位是 8。

预期结果是:

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

我不知道这是怎么回事,.txt文件在做什么?

C IO 控制台 Kernighan-and-Ritchie

评论

0赞 Armali 10/24/2023
代码做错了,这就是为什么你无法理解;对所谓的自然制表符的整个差别处理是不合适的 - 修改后的制表符列表应该被视为硬制表符。

答: 暂无答案